Compare commits
22 Commits
master
...
alpha_2020
Author | SHA1 | Date |
---|---|---|
![]() |
e63ec1404f | |
![]() |
a719aa2864 | |
![]() |
29413979fa | |
![]() |
48def49f8b | |
![]() |
31bbcbfe25 | |
![]() |
96eebb01db | |
![]() |
dd68d381ac | |
![]() |
5f25739286 | |
![]() |
5316c8938d | |
![]() |
c87769a06e | |
![]() |
ffb32cca9c | |
![]() |
dac935f66d | |
![]() |
ac33d98ad5 | |
![]() |
1caafaf5b3 | |
![]() |
179ea504d0 | |
![]() |
07f6f01d92 | |
![]() |
8fdc74a3c4 | |
![]() |
ef79b4343d | |
![]() |
b8f4d5cd53 | |
![]() |
6826d5d660 | |
![]() |
02e9fa9830 | |
![]() |
f028745f52 |
|
@ -1,52 +0,0 @@
|
|||
name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkitarm
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
- name: Get ctr_firm_builder commit
|
||||
run: echo "FIRM_BUILDER_COMMIT=$(git ls-remote https://github.com/derrekr/ctr_firm_builder.git HEAD | cut -f1)" >> $GITHUB_ENV
|
||||
|
||||
- name: Cache ctr_firm_builder
|
||||
id: cache-firm-builder
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ctr_firm_builder
|
||||
key: ${{ runner.os }}-${{ env.FIRM_BUILDER_COMMIT }}
|
||||
|
||||
- name: Install ctr_firm_builder dependencies
|
||||
if: steps.cache-firm-builder.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install gcc
|
||||
|
||||
- name: Build ctr_firm_builder
|
||||
if: steps.cache-firm-builder.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --depth 1 --recurse-submodules https://github.com/derrekr/ctr_firm_builder.git
|
||||
cd ctr_firm_builder
|
||||
make
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
export PATH=$PWD/ctr_firm_builder:$PATH
|
||||
make nightly
|
||||
echo ${{ github.sha }} >> ./nightly/nightly_commit.txt
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: open_agb_firm_nightly
|
||||
path: ./nightly
|
||||
if-no-files-found: error
|
|
@ -1,9 +1,11 @@
|
|||
/.*
|
||||
!/.git*
|
||||
/arm[19]*/build/
|
||||
/arm[19]*/open_agb_firm[19]*.*
|
||||
/tools/gba-db/gba_db.*
|
||||
!/tools/gba-db/gba_db.py
|
||||
/tools/gba-db/gba.*
|
||||
!/tools/gba-db/gba.csv
|
||||
/open_agb_firm*.*
|
||||
arm9/build/
|
||||
arm11/build/
|
||||
eclipse_project/
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
arm9/open_agb_firm9.bin
|
||||
arm11/open_agb_firm11.bin
|
||||
arm9/open_agb_firm9.elf
|
||||
arm11/open_agb_firm11.elf
|
||||
open_agb_firm.firm
|
||||
open_agb_firm*.7z
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[submodule "libraries/libn3ds"]
|
||||
path = libraries/libn3ds
|
||||
url = https://github.com/profi200/libn3ds.git
|
||||
[submodule "tools/lgyFbScaler/lodepng"]
|
||||
path = tools/lgyFbScaler/lodepng
|
||||
url = https://github.com/lvandeve/lodepng.git
|
||||
[submodule "libraries/inih"]
|
||||
path = libraries/inih
|
||||
url = https://github.com/benhoyt/inih.git
|
56
Makefile
56
Makefile
|
@ -9,25 +9,16 @@ export TARGET := open_agb_firm
|
|||
ENTRY9 := 0x08000040
|
||||
ENTRY11 := 0x1FF89034
|
||||
SECTION0_ADR := 0x08000040
|
||||
ifeq ($(strip $(USE_FIRMTOOL)),1)
|
||||
SECTION0_TYPE := NDMA
|
||||
else
|
||||
SECTION0_TYPE := 0
|
||||
endif
|
||||
SECTION0_FILE := arm9/$(TARGET)9.bin
|
||||
SECTION1_ADR := 0x1FF89000
|
||||
ifeq ($(strip $(USE_FIRMTOOL)),1)
|
||||
SECTION1_TYPE := XDMA
|
||||
else
|
||||
SECTION1_TYPE := 1
|
||||
endif
|
||||
SECTION1_FILE := arm11/$(TARGET)11.bin
|
||||
|
||||
|
||||
export VERS_STRING := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i')
|
||||
export VERS_MAJOR := $(shell echo "$(VERS_STRING)" | sed 's/v\([0-9]*\)\..*/\1/i')
|
||||
export VERS_MINOR := $(shell echo "$(VERS_STRING)" | sed 's/.*\.\([0-9]*\).*/\1/')
|
||||
NPROC := $(shell nproc)
|
||||
|
||||
|
||||
.PHONY: checkarm9 checkarm11 clean release
|
||||
|
@ -39,66 +30,35 @@ all: checkarm9 checkarm11 $(TARGET).firm
|
|||
|
||||
#---------------------------------------------------------------------------------
|
||||
checkarm9:
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9
|
||||
@$(MAKE) -j4 --no-print-directory -C arm9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
checkarm11:
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm11
|
||||
@$(MAKE) -j4 --no-print-directory -C arm11
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(TARGET).firm: arm9/$(TARGET)9.bin arm11/$(TARGET)11.bin
|
||||
ifeq ($(strip $(USE_FIRMTOOL)),1)
|
||||
firmtool build $(TARGET).firm -n $(ENTRY9) -e $(ENTRY11) -A $(SECTION0_ADR) $(SECTION1_ADR) \
|
||||
-D $(SECTION0_FILE) $(SECTION1_FILE) -C $(SECTION0_TYPE) $(SECTION1_TYPE)
|
||||
else
|
||||
firm_builder $(TARGET).firm $(ENTRY9) $(ENTRY11) $(SECTION0_ADR) $(SECTION0_TYPE) \
|
||||
$(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE)
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
arm9/$(TARGET)9.bin:
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9
|
||||
@$(MAKE) -j4 --no-print-directory -C arm9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
arm11/$(TARGET)11.bin:
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm11
|
||||
@$(MAKE) -j4 --no-print-directory -C arm11
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@$(MAKE) --no-print-directory -C arm9 clean
|
||||
@$(MAKE) --no-print-directory -C arm11 clean
|
||||
rm -fr $(TARGET).firm *.7z nightly
|
||||
rm -f $(TARGET).firm *.7z
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
release: clean
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9 NO_DEBUG=1
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm11 NO_DEBUG=1
|
||||
ifeq ($(strip $(USE_FIRMTOOL)),1)
|
||||
firmtool build $(TARGET).firm -n $(ENTRY9) -e $(ENTRY11) -A $(SECTION0_ADR) $(SECTION1_ADR) \
|
||||
-D $(SECTION0_FILE) $(SECTION1_FILE) -C $(SECTION0_TYPE) $(SECTION1_TYPE)
|
||||
else
|
||||
@$(MAKE) -j4 --no-print-directory -C arm9 NO_DEBUG=1
|
||||
@$(MAKE) -j4 --no-print-directory -C arm11 NO_DEBUG=1
|
||||
firm_builder $(TARGET).firm $(ENTRY9) $(ENTRY11) $(SECTION0_ADR) $(SECTION0_TYPE) \
|
||||
$(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE)
|
||||
endif
|
||||
@7z a -mx -m0=ARM -m1=LZMA $(TARGET)$(VERS_STRING).7z $(TARGET).firm
|
||||
@7z u -mx -m0=LZMA $(TARGET)$(VERS_STRING).7z resources/gba_db.bin
|
||||
@7z u -mx -m0=PPMD $(TARGET)$(VERS_STRING).7z libraries/libn3ds/LICENSE.txt libraries/libn3ds/libraries/fatfs/LICENSE.txt libraries/inih/LICENSE.txt LICENSE.txt README.md
|
||||
@7z rn $(TARGET)$(VERS_STRING).7z resources/gba_db.bin 3ds/open_agb_firm/gba_db.bin libraries/libn3ds/LICENSE.txt LICENSE_libn3ds.txt libraries/libn3ds/libraries/fatfs/LICENSE.txt LICENSE_FatFs.txt libraries/inih/LICENSE.txt LICENSE_inih.txt
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
nightly: clean
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9 NO_DEBUG=1
|
||||
@$(MAKE) -j$(NPROC) --no-print-directory -C arm11 NO_DEBUG=1
|
||||
ifeq ($(strip $(USE_FIRMTOOL)),1)
|
||||
firmtool build $(TARGET).firm -n $(ENTRY9) -e $(ENTRY11) -A $(SECTION0_ADR) $(SECTION1_ADR) \
|
||||
-D $(SECTION0_FILE) $(SECTION1_FILE) -C $(SECTION0_TYPE) $(SECTION1_TYPE)
|
||||
else
|
||||
firm_builder $(TARGET).firm $(ENTRY9) $(ENTRY11) $(SECTION0_ADR) $(SECTION0_TYPE) \
|
||||
$(SECTION0_FILE) $(SECTION1_ADR) $(SECTION1_TYPE) $(SECTION1_FILE)
|
||||
endif
|
||||
@mkdir -p nightly/3ds/open_agb_firm
|
||||
@cp -t nightly $(TARGET).firm LICENSE.txt README.md
|
||||
@cp resources/gba_db.bin nightly/3ds/open_agb_firm
|
||||
@cp libraries/libn3ds/LICENSE.txt nightly/LICENSE_libn3ds.txt
|
||||
@cp libraries/libn3ds/libraries/fatfs/LICENSE.txt nightly/LICENSE_FatFs.txt
|
||||
@cp libraries/inih/LICENSE.txt nightly/LICENSE_inih.txt
|
||||
@7z u -mx -m0=PPMD $(TARGET)$(VERS_STRING).7z LICENSE.txt README.md
|
||||
|
|
296
README.md
296
README.md
|
@ -1,276 +1,44 @@
|
|||
# open_agb_firm
|
||||
open_agb_firm is a bare metal interface for *natively* running GBA games and homebrew using the 3DS's built-in GBA hardware.
|
||||
|
||||
open_agb_firm is also a complete and better alternative to GBA VC injects (AGB_FIRM), allowing for:
|
||||
* Launching GBA files directly from the SD card
|
||||
* Writing save files directly to the SD card
|
||||
* Automatic save type configuration using an included database
|
||||
* User configuration, such as gamma settings
|
||||
* Button remapping
|
||||
* Border support for 1:1 scaling mode
|
||||
* Gamma correction to fix the washed out look of games
|
||||
* Color correction to mimic the look of the GBA/DS phat LCD
|
||||
* And more to come!
|
||||
|
||||
Unlike AGB_FIRM open_agb_firm is not affected by the famous bug where the video output wraps around leaving garbled lines at the bottom of the screen. SD cluster size doesn't matter.
|
||||
open_agb_firm is a bare metal app for running GBA homebrew/games using the 3DS builtin GBA hardware.
|
||||
|
||||
## Disclaimer
|
||||
open_agb_firm is currently in beta. While open_agb_firm is relatively stable and safe to use, some quirks that have not been fixed. See [Known Issues](#known-issues) for more information.
|
||||
We are not responsible for any damage that may occur to your system as a direct or indirect result of you using open_agb_firm.
|
||||
|
||||
Additionally, we are not responsible for any damage that may occur to your system as a direct or indirect result of you using open_agb_firm.
|
||||
## How to build
|
||||
To compile open_agb_firm you need
|
||||
* [devkitARM](https://sourceforge.net/projects/devkitpro/)
|
||||
* [Corelink DMA-330 assembler](https://github.com/profi200/dma330as)
|
||||
* [CTR firm builder](https://github.com/derrekr/ctr_firm_builder)
|
||||
|
||||
## Setup
|
||||
* Download the [latest release](https://github.com/profi200/open_agb_firm/releases/latest) and extract it.
|
||||
* Copy the `open_agb_firm.firm` file to your 3DS's SD card at `/luma/payloads` if you're using Luma3DS or elsewhere if you're using fastboot3DS.
|
||||
* Copy the `3ds` folder to the root of your 3DS's SD card. Merge folders if asked.
|
||||
* Launch open_agb_firm using Luma3DS by holding START while booting your 3DS or assign it to a slot if you're using fastboot3DS.
|
||||
* After open_agb_firm launches, use the file browser to navigate to a `.gba` ROM to run.
|
||||
installed in your system. Additionally you need 7-Zip or on Linux p7z installed to make release builds. Also make sure the CTR firm builder and dma330as binaries are in your $PATH environment variable and accessible to the Makefile. Build open_agb_firm as debug build via `make` or as release build via `make release`.
|
||||
|
||||
## Controls
|
||||
A/B/L/R/START/SELECT - GBA buttons, respectively
|
||||
|
||||
SELECT+Y - Dump hardware frame output to `/3ds/open_agb_firm/screenshots/YYYY_MM_DD_HH_MM_SS.bmp`
|
||||
* The file name is the current date and time from your real-time clock.
|
||||
* If the screen output freezes, press HOME to fix it. This is a hard to track down bug that will be fixed.
|
||||
|
||||
X+UP/DOWN - Adjust screen brightness up or down by `backlightSteps` units.
|
||||
|
||||
X+LEFT - Turn off LCD backlight.
|
||||
|
||||
X+RIGHT - Turn on LCD backlight.
|
||||
|
||||
Hold the X button while launching a game to skip applying patches (if present)
|
||||
|
||||
Hold the power button to turn off the 3DS.
|
||||
|
||||
## Configuration
|
||||
Settings are stored in `/3ds/open_agb_firm/config.ini`.
|
||||
|
||||
### General
|
||||
General settings.
|
||||
|
||||
`u8 backlight` - Backlight brightness in luminance (cd/m²).
|
||||
* Default: `64`
|
||||
* Possible values:
|
||||
* Old 3DS: `20`-`117`
|
||||
* New 3DS: `16`-`142`
|
||||
* Values ≤`64` are recommended.
|
||||
* Hardware calibration from your CTRNAND is required to get the correct brightness for both LCDs.
|
||||
|
||||
`u8 backlightSteps` - How much to adjust backlight brightness by.
|
||||
* Default: `5`
|
||||
|
||||
`bool directBoot` - Skip GBA BIOS intro at game startup.
|
||||
* Default: `false`
|
||||
|
||||
`bool useGbaDb` - Use `gba_db.bin` to get save types.
|
||||
* Default: `true`
|
||||
|
||||
`bool useSavesFolder` - Use `/3ds/open_agb_firm/saves` for save files instead of the ROM directory.
|
||||
* Default: `true`
|
||||
|
||||
### Video
|
||||
Video-related settings.
|
||||
|
||||
`string scaler` - Video scaler.
|
||||
* Default: `matrix`
|
||||
* Options: `none`, `bilinear`, `matrix`
|
||||
|
||||
`string colorProfile` - Color correction profile.
|
||||
* Default: `none`
|
||||
* Options:
|
||||
* `none` Disable all color correction options.
|
||||
* `gba` Game Boy Advance.
|
||||
* `gb_micro` Game Boy micro.
|
||||
* `gba_sp101` Game Boy Advance SP (AGS-101).
|
||||
* `nds` Nintendo DS (DS phat).
|
||||
* `ds_lite` Nintendo DS lite.
|
||||
* `nso` Nintendo Switch Online.
|
||||
* `vba` Visual Boy Advance/No$GBA full.
|
||||
* `identity` No color space conversion.
|
||||
* If you just want less saturated colors or to change other basic settings like contrast or brightness then set this to `identity`.
|
||||
* Due to most 2/3DS LCDs not being calibrated correctly from factory the look may not match exactly what you see on real hardware.
|
||||
* Due to a lot of extra RAM access and extra CPU processing per frame, battery runtime is affected with color profiles other than `none`.
|
||||
|
||||
`float contrast` - Screen gain. No effect when `colorProfile=none`.
|
||||
* Default: `1.0`
|
||||
|
||||
`float brightness` - Screen lift. No effect when `colorProfile=none`.
|
||||
* Default: `0.0`
|
||||
|
||||
`float saturation` - Screen saturation. No effect when `colorProfile=none`.
|
||||
* Default: `1.0`
|
||||
|
||||
### Audio
|
||||
Audio settings.
|
||||
|
||||
`string audioOut` - Audio output.
|
||||
* Default: `auto`
|
||||
* Options: `auto`, `speakers`, `headphones`
|
||||
|
||||
`s8 volume` - Audio volume. Values above 48 mean control via volume slider. Range -128 (muted) to -20 (100%). Avoid the range -19 to 48.
|
||||
* Default: `127`
|
||||
|
||||
### Input
|
||||
Input settings. Each entry allows one or multiple buttons. Buttons are separated by a `,` without spaces.
|
||||
Allowed buttons are `A B SELECT START RIGHT LEFT UP DOWN R L X Y TOUCH CP_RIGHT CP_LEFT CP_UP CP_DOWN`.
|
||||
TOUCH reacts to all touchscreen presses. The CP in front is short for Circle-Pad.
|
||||
|
||||
Note that button mappings can cause input lag of up to 1 frame depending on when the game reads inputs. For this reason the default mapping of the Circle-Pad to D-Pad is no longer provided.
|
||||
|
||||
`A` - Button map for the A button.
|
||||
* Default: `none`
|
||||
|
||||
`B` - Button map for the B button.
|
||||
* Default: `none`
|
||||
|
||||
`SELECT` - Button map for the SELECT button.
|
||||
* Default: `none`
|
||||
|
||||
`START` - Button map for the START button.
|
||||
* Default: `none`
|
||||
|
||||
`RIGHT` - Button map for the RIGHT button.
|
||||
* Default: `none`
|
||||
|
||||
`LEFT` - Button map for the LEFT button.
|
||||
* Default: `none`
|
||||
|
||||
`UP` - Button map for the UP button.
|
||||
* Default: `none`
|
||||
|
||||
`DOWN` - Button map for the DOWN button.
|
||||
* Default: `none`
|
||||
|
||||
`R` - Button map for the R button.
|
||||
* Default: `none`
|
||||
|
||||
`L` - Button map for the L button.
|
||||
* Default: `none`
|
||||
|
||||
Example which maps the D-Pad and Circle-Pad to the GBA D-Pad:
|
||||
```
|
||||
[input]
|
||||
RIGHT=RIGHT,CP_RIGHT
|
||||
LEFT=LEFT,CP_LEFT
|
||||
UP=UP,CP_UP
|
||||
DOWN=DOWN,CP_DOWN
|
||||
```
|
||||
|
||||
### Game
|
||||
Game-specific settings. Only intended to be used in the per-game settings (romName.ini in `/3ds/open_agb_firm/saves`).
|
||||
|
||||
`u8 saveSlot` - Savegame slot (0-9).
|
||||
* Default: `0`
|
||||
|
||||
`string saveType` - Override to use a specific save type.
|
||||
* Default: `auto`
|
||||
* Options starting with `rom_256m` are intended for 32 MiB games. Options ending with `rtc` enable the hardware real-time clock:
|
||||
* `eeprom_8k`
|
||||
* `rom_256m_eeprom_8k`
|
||||
* `eeprom_64k`
|
||||
* `rom_256m_eeprom_64k`
|
||||
* `flash_512k_atmel_rtc`
|
||||
* `flash_512k_atmel`
|
||||
* `flash_512k_sst_rtc`
|
||||
* `flash_512k_sst`
|
||||
* `flash_512k_panasonic_rtc`
|
||||
* `flash_512k_panasonic`
|
||||
* `flash_1m_macronix_rtc`
|
||||
* `flash_1m_macronix`
|
||||
* `flash_1m_sanyo_rtc`
|
||||
* `flash_1m_sanyo`
|
||||
* `sram_256k`
|
||||
* `none`
|
||||
* `auto`
|
||||
|
||||
### Advanced
|
||||
Options for advanced users. No pun intended.
|
||||
|
||||
`bool saveOverride` - Open save type override menu after selecting a game.
|
||||
* Default: `false`
|
||||
|
||||
`string defaultSave` - Save type default when save type is not in `gba_db.bin` and cannot be autodetected. Same options as for `saveType` above except `auto` is not supported.
|
||||
* Default: `sram_256k`
|
||||
|
||||
## Patches
|
||||
open_agb_firm supports automatically applying IPS and UPS patches. To use a patch, rename the patch file to match the ROM file name (without the extension).
|
||||
* If you wanted to apply an IPS patch to `example.gba`, rename the patch file to `example.ips`
|
||||
|
||||
## Known Issues
|
||||
## Known issues
|
||||
This section is reserved for a listing of known issues. At present only this remains:
|
||||
* Sleep mode is not fully implemented.
|
||||
* Using SELECT+Y to dump screen output to a file can freeze the screen output sometimes.
|
||||
* Save type autodetection may still fail for certain games using EEPROM.
|
||||
* Lack of settings.
|
||||
* No cheats and other enhancements.
|
||||
* Save type detection may still fail for certain games using EEPROM.
|
||||
* No settings (including brightness control), no cheats and other enhancements.
|
||||
|
||||
If you happen to stumble over another bug, please [open an issue](https://github.com/profi200/open_agb_firm/issues) or contact profi200 via other platforms.
|
||||
If you happen to stumble over another bug, please open an issue in the [official open_agb_firm repo on GitHub](https://github.com/profi200/open_agb_firm/issues) or contact me via other platforms.
|
||||
|
||||
## Hardware Limitations
|
||||
open_agb_firm using the 3DS's built-in GBA hardware. Unfortunately, this comes with limitations compared to GBA emulators. This is a list of limitations we can't solve in software or are very hard to work around.
|
||||
* \>32 MiB (>256 Mbit) games and homebrew.
|
||||
* Games with extra hardware built into the cartridge (except real-time clocks). Patches are required.
|
||||
* Proper save autodetection (can't find save type during gameplay).
|
||||
* GBA serial port (aka Link Cable).
|
||||
* \>32 KiB (>256 Kbit) SRAM (homebrew games/emulators).
|
||||
* Reboots are required for switching between games.
|
||||
* No save states. Very difficult to implement because no direct hardware access.
|
||||
* Sound has lots of aliasing issues. No known workaround (hardware bug).
|
||||
## Hardware limitations
|
||||
This is a list of limitations we can't solve in software or are very hard to work around. This doesn't mean it will never happen (unless stated otherwise).
|
||||
* 64 MiB (512 mbit) games. Not possible to support.
|
||||
* Games with extra hardware built into the cartridge (except Real-Time Clock). Patches are required.
|
||||
* GBA Serial port (aka. Link Cable).
|
||||
* 64 KiB (512 kbit) SRAM (homebrew games/emulators). Not possible to support.
|
||||
* Can't switch back to 3DS mode from GBA mode requiring a reboot for booting a different game.
|
||||
* Savestates. Very difficult to implement because no direct hardware access.
|
||||
|
||||
## EEPROM Fixer
|
||||
Most emulators output EEPROM saves differently than what open_agb_firm expects, making them incompatible. Fortunately, they are very easy to fix, using [this tool](https://exelotl.github.io/gba-eeprom-save-fix/) by exelotl.
|
||||
## Troubleshooting
|
||||
Known problems and the solution.
|
||||
|
||||
The tool also works vise versa, if you want to use a save generated by open_agb_firm with an emulator.
|
||||
|
||||
## FAQ
|
||||
**Q: Why isn't open_agb_firm a normal 3DS app?**\
|
||||
A: To access the 3DS's GBA hardware, open_agb_firm needs to run with full hardware access, which can only be provided by running as a FIRM.
|
||||
|
||||
**Q: Is this safe to use?**\
|
||||
A: Of course! While open_agb_firm does run with full hardware access, a lot of work has been put in by several people to ensure that nothing unexpected happens. Some backend code from open_agb_firm is actually used in [fastboot3ds](https://github.com/derrekr/fastboot3DS)!
|
||||
|
||||
**Q: What games work with open_agb_firm?**\
|
||||
A: In theory, all of them, except those that fall within the [hardware limitations](#hardware-limitations).
|
||||
|
||||
**Q: How can I increase the brightness?**\
|
||||
A: Increase the value of the `backlight` setting in `config.ini`. See [Configuration](#configuration) for more information.
|
||||
|
||||
**Q: Why do the colors look off?**\
|
||||
A: The default gamma settings are intended to make up for the washed out colors the 3DS LCD has. If they look weird to you, setting the `outGamma` setting to `2.2` might help.
|
||||
|
||||
**Q: Why do some of my ROM hacks/homebrew games have saving issues?**\
|
||||
A: open_agb_firm resorts to save autodetection when it can't find an entry for the game it's running in `gba_db.bin` (which only contains data for official games), and it's a bit wonky for games that use EEPROM or misleading SDK save strings.
|
||||
|
||||
**Q: Why doesn't my save file from an emulator work?**\
|
||||
A: There's a good chance that the save you're having issues with is an EEPROM save, which most emulators output differently. See [EEPROM Fixer](#eeprom-fixer).
|
||||
|
||||
**Q: My game doesn't save properly!**\
|
||||
A: First, please ensure that the GBA ROM you are playing is not modified in any way, and matches its [No-Intro](https://datomatic.no-intro.org/) checksums. Second, make sure you aren't using an existing `.SAV` file, because some may have issues for various reasons. Third, make sure your [`gba_db.bin`](resources/gba_db.bin) is up-to-date. If everything seems to be in order but the game still doesn't save properly, please [open an issue](https://github.com/profi200/open_agb_firm/issues) so it can be fixed. In the meantime, the `useGbaDb` and `saveOverride` settings may be useful (see [Configuration](#configuration) for more information).
|
||||
|
||||
## Nightlies
|
||||
If you want to test the latest changes you have 2 download options. The first is recommended.
|
||||
|
||||
**With GitHub account**\
|
||||
Log into your account, go to the Actions tab at the top, click on the first entry and download the file under `Artifacts` (`open_agb_firm_nightly`).
|
||||
|
||||
**Without GitHub account**\
|
||||
nightly.link is a thirdparty site to make builds available to everyone. I'm not affiliated with nightly.link or their developers and neither are they with GitHub. Use at your own risk.\
|
||||
https://nightly.link/profi200/open_agb_firm/workflows/c-cpp/master/open_agb_firm_nightly.zip
|
||||
|
||||
## Compiling
|
||||
To compile open_agb_firm, the following needs to be installed:
|
||||
* [devkitARM](https://devkitpro.org/wiki/devkitPro_pacman)
|
||||
* [CTR Firm Builder](https://github.com/derrekr/ctr_firm_builder) or [firmtool](https://github.com/TuxSH/firmtool)
|
||||
|
||||
Additionally, `p7zip` (or if available, `p7zip-full`) needs to be installed to make release builds. Also, make sure that the `dma330as` and `firm_builder`/`firmtool` binaries are in the PATH environment variable and accessible to the Makefile.
|
||||
|
||||
Clone this repository using `git clone --recurse-submodules https://github.com/profi200/open_agb_firm`and update via `git pull && git submodule update --init --recursive`.
|
||||
|
||||
Build open_agb_firm as a debug build via `make`, or as a release build via `make release`.
|
||||
Problem: The game crashes/shows white or blackscreens or shows a savegame corrupt message.\
|
||||
Solution: Try to delete the savegame file. If this doesn't help report the issue.\
|
||||
Note: EEPROM saves made by some emulators are incompatible because they have every 8 bytes block endian swapped.
|
||||
|
||||
## License
|
||||
You may use this under the terms of the GNU General Public License GPL v3 or the terms of any later revisions of the GPL. Refer to the provided `LICENSE.txt` file for further information.
|
||||
You may use this under the terms of the GNU General Public License GPL v3 or under the terms of any later revisions of the GPL. Refer to the provided `LICENSE.txt` file for further information.
|
||||
|
||||
## Thanks to...
|
||||
* **yellows8**
|
||||
|
@ -279,17 +47,13 @@ You may use this under the terms of the GNU General Public License GPL v3 or the
|
|||
* **Normmatt**
|
||||
* **WinterMute**
|
||||
* **ctrulib devs**
|
||||
* **LumaTeam**
|
||||
* **Luma 3DS devs**
|
||||
* **devkitPro**
|
||||
* **ChaN** (fatfs)
|
||||
* **benhoyt** (inih)
|
||||
* **fastboot3DS project**
|
||||
* **MAME**
|
||||
* **No-Intro**
|
||||
* **Wolfvak, Sono and all the other people in #GodMode9 on freenode/Discord**
|
||||
* **endrift, Extrems and all the other people in #mgba on Libera.Chat**
|
||||
* **Oleh Prypin (oprypin) for nightly.link**
|
||||
* **[hunterk and Pokefan531 for their amazing libretro shaders](https://forums.libretro.com/t/real-gba-and-ds-phat-colors/1540/220)**
|
||||
* **Wolfvak, Sono and all the other people in #GodMode9 on IRC/Discord**
|
||||
* **endrift, Extrems and all the other people in #mgba on Freenode**
|
||||
* ...everyone who contributed to **3dbrew.org**
|
||||
|
||||
Copyright (C) 2024 derrek, profi200, d0k3
|
||||
Copyright (C) 2020 derrek, profi200, d0k3
|
||||
|
|
|
@ -8,7 +8,6 @@ endif
|
|||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/base_rules
|
||||
include $(TOPDIR)/../libraries/libn3ds/libn3ds11.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
|
@ -19,10 +18,12 @@ include $(TOPDIR)/../libraries/libn3ds/libn3ds11.mk
|
|||
#---------------------------------------------------------------------------------
|
||||
#TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES += ../source ../source/arm11 ../libraries/inih
|
||||
SOURCES := ../kernel/source ../source ../source/hardware ../source/arm11 \
|
||||
../source/arm11/allocator ../source/arm11/hardware \
|
||||
../source/arm11/util/rbtree ../thirdparty/inih
|
||||
DATA :=
|
||||
INCLUDES += ../include ../libraries
|
||||
DEFINES := -D__ARM11__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
INCLUDES := ../kernel/include ../include ../thirdparty
|
||||
DEFINES := -DARM11 -D_3DS -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
|
||||
ASSETS :=
|
||||
|
||||
|
@ -33,18 +34,18 @@ endif
|
|||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
|
||||
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork
|
||||
|
||||
CFLAGS := $(ARCH) -std=c23 -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
CFLAGS := $(ARCH) -std=c17 -O2 -g -flto -mword-relocations \
|
||||
-ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
CXXFLAGS := $(ARCH) -std=c++17 -O2 -g -flto -fno-rtti -fno-exceptions \
|
||||
-mword-relocations -ffunction-sections -fno-math-errno -Wall -Wextra
|
||||
CXXFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
ASFLAGS := $(ARCH) -gdwarf-4 -flto $(INCLUDE) $(DEFINES)
|
||||
LDFLAGS = $(ARCH) -gdwarf-4 -flto -specs=../arm11.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
|
||||
ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES)
|
||||
LDFLAGS = $(ARCH) -g -flto -specs=../arm11.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
|
||||
|
||||
ifeq ($(strip $(NO_DEBUG)),)
|
||||
CFLAGS := $(subst -flto,,$(CFLAGS)) -fstack-protector-strong -fno-inline
|
||||
|
|
|
@ -8,7 +8,6 @@ endif
|
|||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITARM)/base_rules
|
||||
include $(TOPDIR)/../libraries/libn3ds/libn3ds9.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
|
@ -19,10 +18,10 @@ include $(TOPDIR)/../libraries/libn3ds/libn3ds9.mk
|
|||
#---------------------------------------------------------------------------------
|
||||
#TARGET := $(notdir $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES += ../source/arm9
|
||||
SOURCES := ../source ../source/hardware ../source/arm9 ../source/arm9/hardware ../thirdparty/fatfs
|
||||
DATA :=
|
||||
INCLUDES += ../include
|
||||
DEFINES := -D__ARM9__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
INCLUDES := ../include ../thirdparty
|
||||
DEFINES := -DARM9 -D_3DS -DVERS_STRING=\"$(VERS_STRING)\" \
|
||||
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
|
||||
|
||||
ifneq ($(strip $(NO_DEBUG)),)
|
||||
|
@ -32,25 +31,18 @@ endif
|
|||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
|
||||
ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork
|
||||
|
||||
CFLAGS := $(ARCH) -std=c23 -O2 -gdwarf-4 -flto -mword-relocations \
|
||||
CFLAGS := $(ARCH) -std=c17 -O2 -g -flto -mword-relocations \
|
||||
-ffunction-sections -Wall -Wextra
|
||||
CFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
|
||||
CXXFLAGS := $(ARCH) -std=c++17 -O2 -g -flto -fno-rtti -fno-exceptions \
|
||||
-mword-relocations -ffunction-sections -Wall -Wextra
|
||||
CXXFLAGS += $(INCLUDE) $(DEFINES)
|
||||
|
||||
ASFLAGS := $(ARCH) -gdwarf-4 -flto $(INCLUDE) $(DEFINES)
|
||||
LDFLAGS = $(ARCH) -gdwarf-4 -flto -specs=../arm9.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
|
||||
|
||||
ifeq ($(strip $(NO_DEBUG)),)
|
||||
CFLAGS := $(subst -flto,,$(CFLAGS)) -fstack-protector-strong -fno-inline
|
||||
CXXFLAGS := $(subst -flto,,$(CXXFLAGS)) -fstack-protector-strong -fno-inline
|
||||
ASFLAGS := $(subst -flto,,$(ASFLAGS))
|
||||
LDFLAGS := $(subst -flto,,$(LDFLAGS)) -fstack-protector-strong -fno-inline -Wl,-wrap=malloc,-wrap=calloc,-wrap=free
|
||||
endif
|
||||
ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES)
|
||||
LDFLAGS = $(ARCH) -g -flto -specs=../arm9.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
|
||||
|
||||
LIBS :=
|
||||
|
||||
|
|
|
@ -0,0 +1,324 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
#include "types.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Program status register (CPSR/SPSR)
|
||||
#define PSR_USER_MODE (16)
|
||||
#define PSR_FIQ_MODE (17)
|
||||
#define PSR_IRQ_MODE (18)
|
||||
#define PSR_SVC_MODE (19)
|
||||
#define PSR_ABORT_MODE (23)
|
||||
#define PSR_UNDEF_MODE (27)
|
||||
#define PSR_SYS_MODE (31)
|
||||
#define PSR_MODE_MASK (PSR_SYS_MODE)
|
||||
|
||||
#define PSR_T (1<<5) // Thumb mode
|
||||
#define PSR_F (1<<6) // Interrupts (FIQ) disable flag
|
||||
#define PSR_I (1<<7) // Interrupts (IRQ) disable flag
|
||||
#define PSR_A (1<<8) // Imprecise aborts disable flag
|
||||
#define PSR_E (1<<9) // Big endian
|
||||
#define PSR_J (1<<24) // Jazelle mode
|
||||
#define PSR_Q (1<<27)
|
||||
#define PSR_V (1<<28) // Overflow flag
|
||||
#define PSR_C (1<<29) // Carry flag
|
||||
#define PSR_Z (1<<30) // Zero flag
|
||||
#define PSR_N (1<<31) // Negative flag
|
||||
#define PSR_INT_OFF (PSR_I | PSR_F) // IRQ and FIQ disabled flags
|
||||
|
||||
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
|
||||
#define MAKE_INTR_NO_INOUT(isVolatile, name, ...) \
|
||||
ALWAYS_INLINE void __##name(void) \
|
||||
{ \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#name : : : __VA_ARGS__); \
|
||||
else \
|
||||
__asm__(#name : : : __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define MAKE_INTR_GET_REG(isVolatile, name, inst) \
|
||||
ALWAYS_INLINE u32 __##name(void) \
|
||||
{ \
|
||||
u32 reg; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(inst : "=r" (reg) : : ); \
|
||||
else \
|
||||
__asm__(inst : "=r" (reg) : : ); \
|
||||
return reg; \
|
||||
}
|
||||
|
||||
#define MAKE_INTR_SET_REG_ZERO(isVolatile, name, inst, ...) \
|
||||
ALWAYS_INLINE void __##name(void) \
|
||||
{ \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(inst : : "r" (0) : __VA_ARGS__); \
|
||||
else \
|
||||
__asm__(inst : : "r" (0) : __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define MAKE_INTR_SET_REG(isVolatile, name, inst, ...) \
|
||||
ALWAYS_INLINE void __##name(u32 reg) \
|
||||
{ \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(inst : : "r" (reg) : __VA_ARGS__); \
|
||||
else \
|
||||
__asm__(inst : : "r" (reg) : __VA_ARGS__); \
|
||||
}
|
||||
|
||||
|
||||
#define __bkpt(val) __asm__ volatile("bkpt #" #val : : : )
|
||||
|
||||
#if !__thumb__
|
||||
// Program status register
|
||||
MAKE_INTR_GET_REG(1, getCpsr, "mrs %0, cpsr")
|
||||
MAKE_INTR_SET_REG(1, setCpsr_c, "msr cpsr_c, %0", "memory")
|
||||
MAKE_INTR_SET_REG(1, setCpsr, "msr cpsr_cxsf, %0", "memory")
|
||||
MAKE_INTR_GET_REG(1, getSpsr, "mrs %0, spsr")
|
||||
MAKE_INTR_SET_REG(1, setSpsr_c, "msr spsr_c, %0", "memory")
|
||||
MAKE_INTR_SET_REG(1, setSpsr, "msr spsr_cxsf, %0", "memory")
|
||||
|
||||
// Control Register
|
||||
MAKE_INTR_GET_REG(1, getCr, "mrc p15, 0, %0, c1, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setCr, "mcr p15, 0, %0, c1, c0, 0", "memory")
|
||||
#endif // if !__thumb__
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
#define __cpsid(flags) __asm__ volatile("cpsid " #flags : : : "memory")
|
||||
#define __cpsie(flags) __asm__ volatile("cpsie " #flags : : : "memory")
|
||||
#define __setend(end) __asm__ volatile("setend " #end : : : "memory")
|
||||
|
||||
MAKE_INTR_NO_INOUT(1, nop)
|
||||
MAKE_INTR_NO_INOUT(1, wfi, "memory")
|
||||
MAKE_INTR_NO_INOUT(1, wfe, "memory")
|
||||
MAKE_INTR_NO_INOUT(1, sev)
|
||||
|
||||
#if !__thumb__
|
||||
ALWAYS_INLINE u8 __ldrexb(vu8 *addr)
|
||||
{
|
||||
u8 res;
|
||||
__asm__ volatile("ldrexb %0, %1" : "=r" (res) : "Q" (*addr) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u16 __ldrexh(vu16 *addr)
|
||||
{
|
||||
u16 res;
|
||||
__asm__ volatile("ldrexh %0, %1" : "=r" (res) : "Q" (*addr) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u32 __ldrex(vu32 *addr)
|
||||
{
|
||||
u32 res;
|
||||
__asm__ volatile("ldrex %0, %1" : "=r" (res) : "Q" (*addr) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
/*ALWAYS_INLINE u64 __ldrexd(vu64 *addr)
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 r32[2];
|
||||
u64 r64;
|
||||
} r;
|
||||
|
||||
// TODO: "Error: even register required -- `ldrexd r3,r2,[r0]'"
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__asm__ volatile("ldrexd %0, %1, %2" : "=r" (r.r32[0]), "=r" (r.r32[1]) : "Q" (*addr) : );
|
||||
#else // Big endian
|
||||
__asm__ volatile("ldrexd %0, %1, %2" : "=r" (r.r32[1]), "=r" (r.r32[0]) : "Q" (*addr) : );
|
||||
#endif
|
||||
return r.r64;
|
||||
}*/
|
||||
|
||||
ALWAYS_INLINE u32 __strexb(vu8 *addr, u8 val)
|
||||
{
|
||||
u32 res;
|
||||
__asm__ volatile("strexb %0, %2, %1" : "=&r" (res), "=Q" (*addr) : "r" (val) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u32 __strexh(vu16 *addr, u16 val)
|
||||
{
|
||||
u32 res;
|
||||
__asm__ volatile("strexh %0, %2, %1" : "=&r" (res), "=Q" (*addr) : "r" (val) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE u32 __strex(vu32 *addr, u32 val)
|
||||
{
|
||||
u32 res;
|
||||
__asm__ volatile("strex %0, %2, %1" : "=&r" (res), "=Q" (*addr) : "r" (val) : );
|
||||
return res;
|
||||
}
|
||||
|
||||
/*ALWAYS_INLINE u32 __strexd(vu64 *addr, u64 val)
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 r32[2];
|
||||
u64 r64;
|
||||
} r;
|
||||
r.r64 = val;
|
||||
|
||||
// TODO: "Error: even register required -- `strexd r0,r3,r2,[r1]'"
|
||||
u32 res;
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
__asm__ volatile("strexd %0, %2, %3, %1" : "=&r" (res), "=Q" (*addr) : "r" (r.r32[0]), "r" (r.r32[1]) : );
|
||||
#else // Big endian
|
||||
__asm__ volatile("strexd %0, %2, %3, %1" : "=&r" (res), "=Q" (*addr) : "r" (r.r32[1]), "r" (r.r32[0]) : );
|
||||
#endif
|
||||
return res;
|
||||
}*/
|
||||
|
||||
MAKE_INTR_NO_INOUT(1, clrex, "memory")
|
||||
|
||||
// Debug ID Register
|
||||
MAKE_INTR_GET_REG(0, getDidr, "mrc p14, 0, %0, c0, c0, 0")
|
||||
|
||||
// Debug Status and Control Register
|
||||
MAKE_INTR_GET_REG(1, getDscr, "mrc p14, 0, %0, c0, c1, 0")
|
||||
MAKE_INTR_SET_REG(1, setDscr, "mcr p14, 0, %0, c0, c1, 0", "memory")
|
||||
|
||||
// Data Transfer Register
|
||||
|
||||
// Vector Catch Register
|
||||
MAKE_INTR_GET_REG(1, getVcr, "mrc p14, 0, %0, c0, c7, 0")
|
||||
MAKE_INTR_SET_REG(1, setVcr, "mcr p14, 0, %0, c0, c7, 0", "memory")
|
||||
|
||||
// Breakpoint Value Register 0-5
|
||||
MAKE_INTR_GET_REG(1, getBvr0, "mrc p14, 0, %0, c0, c0, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr0, "mcr p14, 0, %0, c0, c0, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr1, "mrc p14, 0, %0, c0, c1, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr1, "mcr p14, 0, %0, c0, c1, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr2, "mrc p14, 0, %0, c0, c2, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr2, "mcr p14, 0, %0, c0, c2, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr3, "mrc p14, 0, %0, c0, c3, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr3, "mcr p14, 0, %0, c0, c3, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr4, "mrc p14, 0, %0, c0, c4, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr4, "mcr p14, 0, %0, c0, c4, 4", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBvr5, "mrc p14, 0, %0, c0, c5, 4")
|
||||
MAKE_INTR_SET_REG(1, setBvr5, "mcr p14, 0, %0, c0, c5, 4", "memory")
|
||||
|
||||
// Breakpoint Control Register 0-5
|
||||
MAKE_INTR_GET_REG(1, getBcr0, "mrc p14, 0, %0, c0, c0, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr0, "mcr p14, 0, %0, c0, c0, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr1, "mrc p14, 0, %0, c0, c1, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr1, "mcr p14, 0, %0, c0, c1, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr2, "mrc p14, 0, %0, c0, c2, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr2, "mcr p14, 0, %0, c0, c2, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr3, "mrc p14, 0, %0, c0, c3, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr3, "mcr p14, 0, %0, c0, c3, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr4, "mrc p14, 0, %0, c0, c4, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr4, "mcr p14, 0, %0, c0, c4, 5", "memory")
|
||||
MAKE_INTR_GET_REG(1, getBcr5, "mrc p14, 0, %0, c0, c5, 5")
|
||||
MAKE_INTR_SET_REG(1, setBcr5, "mcr p14, 0, %0, c0, c5, 5", "memory")
|
||||
|
||||
// Watchpoint Value Register 0-1
|
||||
MAKE_INTR_GET_REG(1, getWvr0, "mrc p14, 0, %0, c0, c0, 6")
|
||||
MAKE_INTR_SET_REG(1, setWvr0, "mcr p14, 0, %0, c0, c0, 6", "memory")
|
||||
MAKE_INTR_GET_REG(1, getWvr1, "mrc p14, 0, %0, c0, c1, 6")
|
||||
MAKE_INTR_SET_REG(1, setWvr1, "mcr p14, 0, %0, c0, c1, 6", "memory")
|
||||
|
||||
// Watchpoint Control Register 0-1
|
||||
MAKE_INTR_GET_REG(1, getWcr0, "mrc p14, 0, %0, c0, c0, 7")
|
||||
MAKE_INTR_SET_REG(1, setWcr0, "mcr p14, 0, %0, c0, c0, 7", "memory")
|
||||
MAKE_INTR_GET_REG(1, getWcr1, "mrc p14, 0, %0, c0, c1, 7")
|
||||
MAKE_INTR_SET_REG(1, setWcr1, "mcr p14, 0, %0, c0, c1, 7", "memory")
|
||||
|
||||
ALWAYS_INLINE u32 __getCpuId(void)
|
||||
{
|
||||
u32 cpuId;
|
||||
__asm__("mrc p15, 0, %0, c0, c0, 5" : "=r" (cpuId) : );
|
||||
return cpuId & 3;
|
||||
}
|
||||
|
||||
// Auxiliary Control Register
|
||||
MAKE_INTR_GET_REG(1, getAcr, "mrc p15, 0, %0, c1, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setAcr, "mcr p15, 0, %0, c1, c0, 1", "memory")
|
||||
|
||||
// Translation Table Base Register 0
|
||||
MAKE_INTR_GET_REG(1, getTtbr0, "mrc p15, 0, %0, c2, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setTtbr0, "mcr p15, 0, %0, c2, c0, 0", "memory")
|
||||
|
||||
// Translation Table Base Register 1
|
||||
MAKE_INTR_GET_REG(1, getTtbr1, "mrc p15, 0, %0, c2, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setTtbr1, "mcr p15, 0, %0, c2, c0, 1", "memory")
|
||||
|
||||
// Translation Table Base Control Register
|
||||
MAKE_INTR_GET_REG(1, getTtbcr, "mrc p15, 0, %0, c2, c0, 2")
|
||||
MAKE_INTR_SET_REG(1, setTtbcr, "mcr p15, 0, %0, c2, c0, 2", "memory")
|
||||
|
||||
// Domain Access Control Register
|
||||
MAKE_INTR_GET_REG(1, getDacr, "mrc p15, 0, %0, c3, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setDacr, "mcr p15, 0, %0, c3, c0, 0", "memory")
|
||||
|
||||
// Data Fault Status Register
|
||||
MAKE_INTR_GET_REG(1, getDfsr, "mrc p15, 0, %0, c5, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setDfsr, "mcr p15, 0, %0, c5, c0, 0", "memory")
|
||||
|
||||
// Instruction Fault Status Register
|
||||
MAKE_INTR_GET_REG(1, getIfsr, "mrc p15, 0, %0, c5, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setIfsr, "mcr p15, 0, %0, c5, c0, 1", "memory")
|
||||
|
||||
// Fault Address Register
|
||||
MAKE_INTR_GET_REG(1, getFar, "mrc p15, 0, %0, c6, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setFar, "mcr p15, 0, %0, c6, c0, 0", "memory")
|
||||
|
||||
// Watchpoint Fault Address Register
|
||||
MAKE_INTR_GET_REG(1, getWfar, "mrc p15, 0, %0, c6, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setWfar, "mcr p15, 0, %0, c6, c0, 1", "memory")
|
||||
|
||||
// Flush Prefetch Buffer
|
||||
// Data Synchronization Barrier
|
||||
// Data Memory Barrier
|
||||
MAKE_INTR_SET_REG_ZERO(1, isb, "mcr p15, 0, %0, c7, c5, 4", "memory")
|
||||
MAKE_INTR_SET_REG_ZERO(1, dsb, "mcr p15, 0, %0, c7, c10, 4", "memory")
|
||||
MAKE_INTR_SET_REG_ZERO(1, dmb, "mcr p15, 0, %0, c7, c10, 5", "memory")
|
||||
|
||||
// FCSE PID Register
|
||||
MAKE_INTR_GET_REG(1, getFcsepidr, "mrc p15, 0, %0, c13, c0, 0")
|
||||
MAKE_INTR_SET_REG(1, setFcsepidr, "mcr p15, 0, %0, c13, c0, 0", "memory")
|
||||
|
||||
// Context ID Register
|
||||
MAKE_INTR_GET_REG(1, getCidr, "mrc p15, 0, %0, c13, c0, 1")
|
||||
MAKE_INTR_SET_REG(1, setCidr, "mcr p15, 0, %0, c13, c0, 1", "memory")
|
||||
#endif // if !__thumb__
|
||||
|
||||
#elif ARM9
|
||||
|
||||
#if !__thumb__
|
||||
MAKE_INTR_SET_REG_ZERO(1, wfi, "mcr p15, 0, %0, c7, c0, 4", "memory")
|
||||
#endif // if !__thumb__
|
||||
#endif // ifdef ARM11
|
||||
|
||||
#undef MAKE_INTR_NO_INOUT
|
||||
#undef MAKE_INTR_GET_REG
|
||||
#undef MAKE_INTR_SET_REG_ZERO
|
||||
#undef MAKE_INTR_SET_REG
|
||||
|
||||
#endif // if !__ASSEMBLER__
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @file vram.h
|
||||
* @brief VRAM allocator.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Allocates a 0x80-byte aligned buffer.
|
||||
* @param size Size of the buffer to allocate.
|
||||
* @return The allocated buffer.
|
||||
*/
|
||||
void* vramAlloc(size_t size);
|
||||
|
||||
/**
|
||||
* @brief Allocates a buffer aligned to the given size.
|
||||
* @param size Size of the buffer to allocate.
|
||||
* @param alignment Alignment to use.
|
||||
* @return The allocated buffer.
|
||||
*/
|
||||
void* vramMemAlign(size_t size, size_t alignment);
|
||||
|
||||
/**
|
||||
* @brief Reallocates a buffer.
|
||||
* Note: Not implemented yet.
|
||||
* @param mem Buffer to reallocate.
|
||||
* @param size Size of the buffer to allocate.
|
||||
* @return The reallocated buffer.
|
||||
*/
|
||||
void* vramRealloc(void* mem, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the allocated size of a buffer.
|
||||
* @return The size of the buffer.
|
||||
*/
|
||||
size_t vramGetSize(void* mem);
|
||||
|
||||
/**
|
||||
* @brief Frees a buffer.
|
||||
* @param mem Buffer to free.
|
||||
*/
|
||||
void vramFree(void* mem);
|
||||
|
||||
/**
|
||||
* @brief Gets the current VRAM free space.
|
||||
* @return The current VRAM free space.
|
||||
*/
|
||||
u32 vramSpaceFree(void);
|
|
@ -1,89 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 magic; // "BM"
|
||||
u32 fileSize;
|
||||
u16 reserved;
|
||||
u16 reserved2;
|
||||
u32 pixelOffset; // From file start.
|
||||
} PACKED BmpHeader;
|
||||
static_assert(sizeof(BmpHeader) == 14);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BI_RGB = 0u,
|
||||
BI_RLE8 = 1u, // 8 bit per pixel only.
|
||||
BI_RLE4 = 2u, // 4 bit per pixel only.
|
||||
BI_BITFIELDS = 3u, // BitmapV2Infoheader RGB masks, BitmapV3Infoheader+ RGBA masks.
|
||||
BI_JPEG = 4u, // BitmapV4Infoheader+.
|
||||
BI_PNG = 5u, // BitmapV4Infoheader+.
|
||||
BI_CMYK = 11u, // Only Windows Metafile (WMF) CMYK.
|
||||
BI_CMYKRLE8 = 12u, // Only Windows Metafile (WMF) CMYK.
|
||||
BI_CMYKRLE4 = 13u // Only Windows Metafile (WMF) CMYK.
|
||||
} BitmapCompr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 headerSize; // Size of this header. 40 bytes.
|
||||
s32 width;
|
||||
s32 height; // If >=0, pixel lines are in order bottom to top. Otherwise top to bottom.
|
||||
u16 colorPlanes; // Must be 1.
|
||||
u16 bitsPerPixel; // 1, 4, 8, 16, 24, 32.
|
||||
u32 compression; // See BitmapCompr enum.
|
||||
u32 imageSize; // Can be 0 if compression is BI_RGB.
|
||||
s32 xPixelsPerMeter;
|
||||
s32 yPixelsPerMeter;
|
||||
u32 colorsUsed;
|
||||
u32 colorsImportant;
|
||||
} PACKED Bitmapinfoheader;
|
||||
static_assert(sizeof(Bitmapinfoheader) == 0x28);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BmpHeader header;
|
||||
Bitmapinfoheader dib;
|
||||
} PACKED BmpV1;
|
||||
static_assert(sizeof(BmpV1) == 0x36);
|
||||
|
||||
// Note: Technically this is BMP V2 but we use the shorter Bitmapinfoheader (V1).
|
||||
// The color masks are only needed for compression BI_BITFIELDS.
|
||||
typedef struct
|
||||
{
|
||||
BmpHeader header;
|
||||
Bitmapinfoheader dib;
|
||||
u32 rMask;
|
||||
u32 gMask;
|
||||
u32 bMask;
|
||||
} PACKED BmpV1WithMasks;
|
||||
static_assert(sizeof(BmpV1WithMasks) == 0x42);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -1,76 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "oaf_error_codes.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define OAF_WORK_DIR "sdmc:/3ds/open_agb_firm"
|
||||
#define OAF_SAVE_DIR "saves" // Relative to work dir.
|
||||
#define OAF_SCREENSHOT_DIR "screenshots" // Relative to work dir.
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// [general]
|
||||
u8 backlight; // Both LCDs.
|
||||
u8 backlightSteps;
|
||||
bool directBoot;
|
||||
bool useGbaDb;
|
||||
bool useSavesFolder;
|
||||
|
||||
// [video]
|
||||
u8 scaler; // 0 = 1:1/none, 1 = bilinear (GPU) x1.5, 2 = matrix (hardware) x1.5.
|
||||
u8 colorProfile; // 0 = none, 1 = GBA, 2 = GB micro, 3 = GBA SP (AGS-101), 4 = DS phat, 5 = DS lite, 6 = Nintendo Switch Online, 7 = Visual Boy Advance/No$GBA, 8 = identity.
|
||||
float contrast; // Range 0.0-1.0.
|
||||
float brightness; // Range 0.0-1.0.
|
||||
float saturation; // Range 0.0-1.0.
|
||||
|
||||
// [audio]
|
||||
u8 audioOut; // 0 = auto, 1 = speakers, 2 = headphones.
|
||||
s8 volume; // -128 = muted, -127 - 48 = -63.5 - +24 dB.
|
||||
// Higher than 48 = volume control via slider.
|
||||
|
||||
// [input]
|
||||
u32 buttonMaps[10]; // A, B, Select, Start, Right, Left, Up, Down, R, L.
|
||||
|
||||
// [game]
|
||||
u8 saveSlot;
|
||||
u8 saveType;
|
||||
|
||||
// [advanced]
|
||||
bool saveOverride;
|
||||
u16 defaultSave; // TODO: Should be u8. Investigate if u8 has any downsides.
|
||||
} OafConfig;
|
||||
|
||||
extern OafConfig g_oafConfig; // Global config in config.c.
|
||||
|
||||
|
||||
|
||||
Result parseOafConfig(const char *const path, OafConfig *cfg, const bool newCfgOnError);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,192 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This code is part of ctrulib (https://github.com/smealum/ctrulib)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file console.h
|
||||
* @brief 3ds stdio support.
|
||||
*
|
||||
* Provides stdio integration for printing to the 3DS screen as well as debug print
|
||||
* functionality provided by stderr.
|
||||
*
|
||||
* General usage is to initialize the console by:
|
||||
* @code
|
||||
* consoleDemoInit()
|
||||
* @endcode
|
||||
* or to customize the console usage by:
|
||||
* @code
|
||||
* consoleInit()
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "hardware/gfx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CONSOLE_ESC(x) "\x1b[" #x
|
||||
#define CONSOLE_RESET CONSOLE_ESC(0m)
|
||||
#define CONSOLE_BLACK CONSOLE_ESC(30m)
|
||||
#define CONSOLE_RED CONSOLE_ESC(31;1m)
|
||||
#define CONSOLE_GREEN CONSOLE_ESC(32;1m)
|
||||
#define CONSOLE_YELLOW CONSOLE_ESC(33;1m)
|
||||
#define CONSOLE_BLUE CONSOLE_ESC(34;1m)
|
||||
#define CONSOLE_MAGENTA CONSOLE_ESC(35;1m)
|
||||
#define CONSOLE_CYAN CONSOLE_ESC(36;1m)
|
||||
#define CONSOLE_WHITE CONSOLE_ESC(37;1m)
|
||||
|
||||
/// A callback for printing a character.
|
||||
typedef bool(*ConsolePrint)(void* con, int c);
|
||||
|
||||
/// A font struct for the console.
|
||||
typedef struct ConsoleFont
|
||||
{
|
||||
const u8* gfx; ///< A pointer to the font graphics
|
||||
u16 asciiOffset; ///< Offset to the first valid character in the font table
|
||||
u16 numChars; ///< Number of characters in the font graphics
|
||||
}ConsoleFont;
|
||||
|
||||
/**
|
||||
* @brief Console structure used to store the state of a console render context.
|
||||
*
|
||||
* Default values from consoleGetDefault();
|
||||
* @code
|
||||
* PrintConsole defaultConsole =
|
||||
* {
|
||||
* //Font:
|
||||
* {
|
||||
* (u8*)default_font_bin, //font gfx
|
||||
* 0, //first ascii character in the set
|
||||
* 128, //number of characters in the font set
|
||||
* },
|
||||
* 0,0, //cursorX cursorY
|
||||
* 0,0, //prevcursorX prevcursorY
|
||||
* 40, //console width
|
||||
* 30, //console height
|
||||
* 0, //window x
|
||||
* 0, //window y
|
||||
* 32, //window width
|
||||
* 24, //window height
|
||||
* 3, //tab size
|
||||
* 0, //font character offset
|
||||
* 0, //print callback
|
||||
* false //console initialized
|
||||
* };
|
||||
* @endcode
|
||||
*/
|
||||
typedef struct PrintConsole
|
||||
{
|
||||
ConsoleFont font; ///< Font of the console
|
||||
|
||||
u16 *frameBuffer; ///< Framebuffer address
|
||||
|
||||
int cursorX; ///< Current X location of the cursor (as a tile offset by default)
|
||||
int cursorY; ///< Current Y location of the cursor (as a tile offset by default)
|
||||
|
||||
int prevCursorX; ///< Internal state
|
||||
int prevCursorY; ///< Internal state
|
||||
|
||||
int consoleWidth; ///< Width of the console hardware layer in characters
|
||||
int consoleHeight; ///< Height of the console hardware layer in characters
|
||||
|
||||
int windowX; ///< Window X location in characters (not implemented)
|
||||
int windowY; ///< Window Y location in characters (not implemented)
|
||||
int windowWidth; ///< Window width in characters (not implemented)
|
||||
int windowHeight; ///< Window height in characters (not implemented)
|
||||
|
||||
int tabSize; ///< Size of a tab
|
||||
int fg; ///< Foreground color
|
||||
int bg; ///< Background color
|
||||
int flags; ///< Reverse/bright flags
|
||||
|
||||
ConsolePrint PrintChar; ///< Callback for printing a character. Should return true if it has handled rendering the graphics (else the print engine will attempt to render via tiles).
|
||||
|
||||
bool consoleInitialised; ///< True if the console is initialized
|
||||
}PrintConsole;
|
||||
|
||||
#define CONSOLE_COLOR_BOLD (1<<0) ///< Bold text
|
||||
#define CONSOLE_COLOR_FAINT (1<<1) ///< Faint text
|
||||
#define CONSOLE_ITALIC (1<<2) ///< Italic text
|
||||
#define CONSOLE_UNDERLINE (1<<3) ///< Underlined text
|
||||
#define CONSOLE_BLINK_SLOW (1<<4) ///< Slow blinking text
|
||||
#define CONSOLE_BLINK_FAST (1<<5) ///< Fast blinking text
|
||||
#define CONSOLE_COLOR_REVERSE (1<<6) ///< Reversed color text
|
||||
#define CONSOLE_CONCEAL (1<<7) ///< Concealed text
|
||||
#define CONSOLE_CROSSED_OUT (1<<8) ///< Crossed out text
|
||||
|
||||
/// Console debug devices supported by libnds.
|
||||
typedef enum {
|
||||
debugDevice_NULL, ///< Swallows prints to stderr
|
||||
debugDevice_3DMOO, ///< Directs stderr debug statements to 3dmoo
|
||||
debugDevice_CONSOLE, ///< Directs stderr debug statements to 3DS console window
|
||||
} debugDevice;
|
||||
|
||||
/**
|
||||
* @brief Loads the font into the console.
|
||||
* @param console Pointer to the console to update, if NULL it will update the current console.
|
||||
* @param font The font to load.
|
||||
*/
|
||||
void consoleSetFont(PrintConsole* console, ConsoleFont* font);
|
||||
|
||||
/**
|
||||
* @brief Sets the print window.
|
||||
* @param console Console to set, if NULL it will set the current console window.
|
||||
* @param x X location of the window.
|
||||
* @param y Y location of the window.
|
||||
* @param width Width of the window.
|
||||
* @param height Height of the window.
|
||||
*/
|
||||
void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height);
|
||||
|
||||
/**
|
||||
* @brief Gets a pointer to the console with the default values.
|
||||
* This should only be used when using a single console or without changing the console that is returned, otherwise use consoleInit().
|
||||
* @return A pointer to the console with the default values.
|
||||
*/
|
||||
PrintConsole* consoleGetDefault(void);
|
||||
|
||||
/**
|
||||
* @brief Make the specified console the render target.
|
||||
* @param console A pointer to the console struct (must have been initialized with consoleInit(PrintConsole* console)).
|
||||
* @return A pointer to the previous console.
|
||||
*/
|
||||
PrintConsole *consoleSelect(PrintConsole* console);
|
||||
|
||||
/**
|
||||
* @brief Returns the currently used console.
|
||||
* @return A pointer to the current console.
|
||||
*/
|
||||
PrintConsole *consoleGet(void);
|
||||
|
||||
/**
|
||||
* @brief Returns the currently used foreground color.
|
||||
* @return The foreground color in RGB565.
|
||||
*/
|
||||
u16 consoleGetFgColor(void);
|
||||
|
||||
/**
|
||||
* @brief Initialise the console.
|
||||
* @param screen The screen to use for the console.
|
||||
* @param console A pointer to the console data to initialize (if it's NULL, the default console will be used).
|
||||
* @return A pointer to the current console.
|
||||
*/
|
||||
PrintConsole* consoleInit(u8 screen, PrintConsole* console);
|
||||
|
||||
/// Clears the screan by using iprintf("\x1b[2J");
|
||||
void consoleClear(void);
|
||||
|
||||
void consoleSetCursor(PrintConsole* console, int x, int y);
|
||||
|
||||
void drawConsoleWindow(PrintConsole* console, int thickness, u8 colorIndex);
|
||||
|
||||
u16 consoleGetRGB565Color(u8 colorIndex);
|
||||
|
||||
ssize_t con_write(UNUSED struct _reent *r,UNUSED void *fd,const char *ptr, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
noreturn void panic(void);
|
||||
noreturn void panicMsg(const char *msg);
|
||||
|
||||
// Exception tests
|
||||
/*static inline regTest(void)
|
||||
{
|
||||
__asm__ volatile("mov r0, #1\n\tmov r1, #2\n\tmov r2, #3\n\tmov r3, #4\n\tmov r4, #5\n\t"
|
||||
"mov r5, #6\n\tmov r6, #7\n\tmov r7, #8\n\tmov r8, #9\n\tmov r9, #10\n\t"
|
||||
"mov r10, #11\n\tmov r11, #12\n\tmov r12, #13\n\tmov r13, #14\n\t"
|
||||
"mov r14, #15\n\tmov r15, #16\n\t" : :);
|
||||
}
|
||||
|
||||
static inline breakpointTest(void)
|
||||
{
|
||||
__asm__ volatile("bkpt #0xCAFE" : :);
|
||||
}
|
||||
|
||||
static inline dataAbortTest(void)
|
||||
{
|
||||
__asm__ volatile("mov r0, #4\n\tmov r1, #0xEF\n\tstr r1, [r0]" : :);
|
||||
}
|
||||
|
||||
static inline undefInstrTest(void)
|
||||
{
|
||||
__asm__ volatile("udf #0xDEAD" : :);
|
||||
}*/
|
|
@ -1,34 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2021 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "error_codes.h"
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result browseFiles(const char *const basePath, char selected[512]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||
* * Requiring preservation of specified reasonable legal notices or
|
||||
* author attributions in that material or in the Appropriate Legal
|
||||
* Notices displayed by works containing it.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
u32 ee_vsnprintf(char *const buf, u32 size, const char *const fmt, va_list arg);
|
||||
u32 ee_vsprintf(char *const buf, const char *const fmt, va_list arg);
|
||||
__attribute__ ((format (printf, 2, 3))) u32 ee_sprintf(char *const buf, const char *const fmt, ...);
|
||||
__attribute__ ((format (printf, 3, 4))) u32 ee_snprintf(char *const buf, u32 size, const char *const fmt, ...);
|
||||
__attribute__ ((format (printf, 1, 2))) u32 ee_printf(const char *const fmt, ...);
|
||||
u32 ee_puts(const char *const str);
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define debug_printf(fmt, ...) ((void)0)
|
||||
#define debug_puts(str) ((void)0)
|
||||
#else
|
||||
#define debug_printf(fmt, ...) ee_printf(fmt, ##__VA_ARGS__)
|
||||
#define debug_puts(str) ee_puts(str)
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "types.h"
|
||||
|
||||
|
||||
// Temporary define for all incomplete entries.
|
||||
#define UNSPECIFIED 0xFF
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char gameCode[3]; // Without the region letter.
|
||||
u8 type;
|
||||
} SaveTypeLut;
|
||||
static_assert(offsetof(SaveTypeLut, type) == 3, "Error: Member 'type' of SaveTypeLut is not at offset 3!");
|
||||
|
||||
|
||||
/*
|
||||
* 0x0 = 16 MiB or smaller ROM + EEPROM 4k/8k (512/1024 bytes)
|
||||
* 0x1 = 32 MiB ROM + EEPROM 4k/8k (512/1024 bytes)
|
||||
* 0x2 = 16 MiB or smaller ROM + EEPROM 64k (8 KiB)
|
||||
* 0x3 = 32 MiB ROM + EEPROM 64k (8 KiB)
|
||||
* 0x4 = Flash 512k (64 KiB) with RTC, ID=0x3D1F, Atmel
|
||||
* 0x5 = Flash 512k (64 KiB) without RTC, ID=0x3D1F, Atmel
|
||||
* 0x6 = Flash 512k (64 KiB) with RTC, ID=0xD4BF, SST
|
||||
* 0x7 = Flash 512k (64 KiB) without RTC, ID=0xD4BF, SST
|
||||
* 0x8 = Flash 512k (64 KiB) with RTC, ID=0x1B32, Panasonic
|
||||
* 0x9 = Flash 512k (64 KiB) without RTC, ID=0x1B32, Panasonic
|
||||
* 0xA = Flash 1M (128 KiB) with RTC, ID=0x09C2, Macronix
|
||||
* 0xB = Flash 1M (128 KiB) without RTC, ID=0x09C2, Macronix
|
||||
* 0xC = Flash 1M (128 KiB) with RTC, ID=0x1362, Sanyo
|
||||
* 0xD = Flash 1M (128 KiB) without RTC, ID=0x1362, Sanyo
|
||||
* 0xE = SRAM/FRAM/FeRAM 256k (32 KiB)
|
||||
* 0xF = No save chip
|
||||
*/
|
||||
|
||||
/*
|
||||
* [] = Optional
|
||||
* <> = Required
|
||||
*
|
||||
* Format:
|
||||
* // [SDK save string if any]
|
||||
* // <no-intro game release names sepearated by newlines>
|
||||
* {"<game code without region (last letter)>", <save type>},
|
||||
*
|
||||
* All entries ordered by release number.
|
||||
*/
|
||||
alignas(4) static const SaveTypeLut saveTypeLut[] =
|
||||
{
|
||||
// EEPROM_V120
|
||||
// 0002 - Super Mario Advance - Super Mario USA + Mario Brothers (Japan)
|
||||
// 0049 - Super Mario Advance (USA, Europe)
|
||||
// 1570 - Chaoji Maliou 2 (China)
|
||||
// x116 - Super Mario Advance (USA, Europe) (Wii U Virtual Console)
|
||||
{"AMA", 0x0},
|
||||
|
||||
// EEPROM_V122
|
||||
// 0237 - Super Mario Advance 2 - Super Mario World + Mario Brothers (Japan)
|
||||
// 0288 - Super Mario Advance 2 - Super Mario World (USA, Australia)
|
||||
// 0389 - Super Mario Advance 2 - Super Mario World (Europe) (En,Fr,De,Es)
|
||||
// 2328 - Chaoji Maliou Shijie (China)
|
||||
{"AA2", 0x2},
|
||||
|
||||
// EEPROM_V122
|
||||
// 0578 - Super Mario Advance 3 - Yoshi's Island (USA)
|
||||
// 0580 - Super Mario Advance 3 - Yoshi's Island + Mario Brothers (Japan)
|
||||
// 0608 - Super Mario Advance 3 - Yoshi's Island (Europe) (En,Fr,De,Es,It)
|
||||
// 2299 - Yaoxi Dao (China)
|
||||
// x115 - Super Mario Advance 3 - Yoshi's Island (USA) (Wii U Virtual Console)
|
||||
// x161 - Super Mario Advance 3 - Yoshi's Island (Europe) (En,Fr,De,Es,It) (Wii U Virtual Console)
|
||||
{"A3A", 0x2},
|
||||
};
|
|
@ -1,45 +1,289 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2021 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
||||
// 360x240, no filter.
|
||||
alignas(16) static const u8 gbaGpuInitList[1136] =
|
||||
{
|
||||
#endif
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x03,
|
||||
0x1C, 0x01, 0x2F, 0x80, 0x00, 0x00, 0x03, 0x03, 0xF0, 0xF0, 0x18, 0x01,
|
||||
0xF0, 0xF0, 0x18, 0x01, 0x6E, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x16, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x17, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x12, 0x01, 0x3F, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x45, 0x00,
|
||||
0x41, 0x00, 0x3F, 0x80, 0x10, 0x11, 0x11, 0x38, 0x00, 0x90, 0x46, 0x00,
|
||||
0x14, 0xAE, 0x47, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x02, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x44, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xCB, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xCC, 0x02, 0x7F, 0x00,
|
||||
0x01, 0xF0, 0x07, 0x4E, 0x02, 0x08, 0x02, 0x08, 0x03, 0x18, 0x02, 0x08,
|
||||
0x04, 0x28, 0x02, 0x08, 0x05, 0x38, 0x02, 0x08, 0x06, 0x10, 0x20, 0x4C,
|
||||
0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0xBF, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, 0x02, 0x0F, 0x00,
|
||||
0x6E, 0x03, 0x00, 0x00, 0xD6, 0x02, 0x6F, 0x00, 0xA1, 0x0A, 0x00, 0x00,
|
||||
0x68, 0xC3, 0x06, 0x00, 0x64, 0xC3, 0x06, 0x00, 0x62, 0xC3, 0x06, 0x00,
|
||||
0x61, 0xC3, 0x06, 0x00, 0x6F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F,
|
||||
0xBA, 0x02, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0xBD, 0x02, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x4A, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x51, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5E, 0x02, 0x01, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x7F, 0x80, 0x00, 0x01, 0x02, 0x03,
|
||||
0x0C, 0x0D, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x0F, 0x00,
|
||||
0x01, 0x01, 0x00, 0x00, 0x6F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xA0,
|
||||
0x89, 0x02, 0x0F, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1F, 0x80,
|
||||
0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xA0,
|
||||
0xB9, 0x02, 0x0B, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x02, 0x0F, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x0F, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xBF, 0x00,
|
||||
0x4D, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x04, 0x01, 0x3F, 0x80, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x26, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x76, 0x76, 0x01, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0F, 0x00, 0x00, 0x01, 0xE4, 0x00,
|
||||
0x00, 0x01, 0x07, 0x00, 0x00, 0x3C, 0x00, 0x80, 0x30, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x00, 0x4F, 0x80, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, // Last 4 bytes: Texture format.
|
||||
0x8E, 0x00, 0x0F, 0x00, 0x01, 0x10, 0x01, 0x00, 0x80, 0x00, 0x0B, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE1, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xC8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xD0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xD8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xF8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0xC0, 0x02, 0x3F, 0x80,
|
||||
0xBF, 0x00, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x80, 0xBF, 0xC1, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0x08, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xD7, 0xA3, 0xBB,
|
||||
0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x7F, 0xB0, 0x02, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x5E, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5F, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x80, 0x27, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x53, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x32, 0x02, 0x0F, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x10, 0x3E, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x10, 0x3E, 0x00, 0x00, 0x00, 0x68, 0x3E, 0x00,
|
||||
0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00,
|
||||
0x00, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x68, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x53, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x31, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x63, 0x00, 0x0F, 0x00, 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00,
|
||||
0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00
|
||||
};
|
||||
// 240x160 with bilinear scaling, no filter.
|
||||
/*alignas(16) static const u8 gbaGpuInitList[1136] =
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x03,
|
||||
0x1C, 0x01, 0x2F, 0x80, 0x00, 0x00, 0x03, 0x03, 0xF0, 0xF0, 0x18, 0x01,
|
||||
0xF0, 0xF0, 0x18, 0x01, 0x6E, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x16, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x17, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x12, 0x01, 0x3F, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x45, 0x00,
|
||||
0x41, 0x00, 0x3F, 0x80, 0x10, 0x11, 0x11, 0x38, 0x00, 0x90, 0x46, 0x00,
|
||||
0x14, 0xAE, 0x47, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x02, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x44, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xCB, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xCC, 0x02, 0x7F, 0x00,
|
||||
0x01, 0xF0, 0x07, 0x4E, 0x02, 0x08, 0x02, 0x08, 0x03, 0x18, 0x02, 0x08,
|
||||
0x04, 0x28, 0x02, 0x08, 0x05, 0x38, 0x02, 0x08, 0x06, 0x10, 0x20, 0x4C,
|
||||
0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0xBF, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, 0x02, 0x0F, 0x00,
|
||||
0x6E, 0x03, 0x00, 0x00, 0xD6, 0x02, 0x6F, 0x00, 0xA1, 0x0A, 0x00, 0x00,
|
||||
0x68, 0xC3, 0x06, 0x00, 0x64, 0xC3, 0x06, 0x00, 0x62, 0xC3, 0x06, 0x00,
|
||||
0x61, 0xC3, 0x06, 0x00, 0x6F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F,
|
||||
0xBA, 0x02, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0xBD, 0x02, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x4A, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x51, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5E, 0x02, 0x01, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x7F, 0x80, 0x00, 0x01, 0x02, 0x03,
|
||||
0x0C, 0x0D, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x0F, 0x00,
|
||||
0x01, 0x01, 0x00, 0x00, 0x6F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xA0,
|
||||
0x89, 0x02, 0x0F, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1F, 0x80,
|
||||
0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xA0,
|
||||
0xB9, 0x02, 0x0B, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x02, 0x0F, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x0F, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xBF, 0x00,
|
||||
0x4D, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x00, 0x00, 0x04, 0x01, 0x3F, 0x80, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x26, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x76, 0x76, 0x01, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x0F, 0x00, 0x00, 0x01, 0xE4, 0x00,
|
||||
0x00, 0x01, 0x07, 0x00, 0x00, 0x3C, 0x00, 0x80, 0x30, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x81, 0x00, 0x4F, 0x80, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00,
|
||||
0x8E, 0x00, 0x0F, 0x00, 0x01, 0x10, 0x01, 0x00, 0x80, 0x00, 0x0B, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x8B, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xE1, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xC8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xD0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xD8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0xF8, 0x00, 0x4F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0xC0, 0x02, 0x3F, 0x80,
|
||||
0xBF, 0x00, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x80, 0xBF, 0xC1, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x88, 0x88, 0x08, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0xD7, 0xA3, 0xBB,
|
||||
0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0x7F, 0xB0, 0x02, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x5E, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5F, 0x02, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x80, 0x27, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x53, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00, 0x32, 0x02, 0x0F, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x80, 0x3D, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x80, 0x3D, 0x00, 0x00, 0x00, 0xE0, 0x3E, 0x00,
|
||||
0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00,
|
||||
0x00, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00,
|
||||
0x00, 0xE0, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x53, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x31, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x63, 0x00, 0x0F, 0x00, 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00,
|
||||
0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00
|
||||
};*/
|
||||
|
||||
#define GPU_RENDER_BUF_ADDR (0x18180000)
|
||||
#define GPU_TEXTURE_ADDR (0x18200000)
|
||||
#define GPU_TEXTURE2_ADDR (0x18300000)
|
||||
#define GBA_INIT_LIST_SIZE (1136)
|
||||
#define GBA_LIST2_SIZE (448)
|
||||
|
||||
|
||||
extern u8 gbaGpuInitList[GBA_INIT_LIST_SIZE];
|
||||
extern u8 gbaGpuList2[GBA_LIST2_SIZE];
|
||||
|
||||
|
||||
|
||||
void patchGbaGpuCmdList(const u8 scaleType, const bool useSecondTexture);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
// 360x240, no filter.
|
||||
alignas(16) static const u8 gbaGpuList2[448] =
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x03,
|
||||
0x1C, 0x01, 0x2F, 0x80, 0x00, 0x00, 0x03, 0x03, 0xF0, 0xF0, 0x18, 0x01,
|
||||
0xF0, 0xF0, 0x18, 0x01, 0x6E, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x16, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x17, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x12, 0x01, 0x3F, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x45, 0x00,
|
||||
0x41, 0x00, 0x3F, 0x80, 0x10, 0x11, 0x11, 0x38, 0x00, 0x90, 0x46, 0x00,
|
||||
0x14, 0xAE, 0x47, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0xC0, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x80, 0xBF, 0xC1, 0x02, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x08, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0A, 0xD7, 0xA3, 0xBB, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5E, 0x02, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x5F, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x27, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x53, 0x02, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x32, 0x02, 0x0F, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x10, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x10, 0x3E, 0x00, 0x00, 0x00, 0x68, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0xE0, 0x46, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x68, 0x3E, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x02, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x10, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x00, 0x0F, 0x00,
|
||||
0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00, 0x78, 0x56, 0x34, 0x12,
|
||||
0x10, 0x00, 0x0F, 0x00
|
||||
};
|
||||
// 240x160 with bilinear scaling, no filter.
|
||||
/*alignas(16) static const u8 gbaGpuList2[448] =
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x03,
|
||||
0x1C, 0x01, 0x2F, 0x80, 0x00, 0x00, 0x03, 0x03, 0xF0, 0xF0, 0x18, 0x01,
|
||||
0xF0, 0xF0, 0x18, 0x01, 0x6E, 0x00, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x16, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x17, 0x01, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1B, 0x01, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x12, 0x01, 0x3F, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x45, 0x00,
|
||||
0x41, 0x00, 0x3F, 0x80, 0x10, 0x11, 0x11, 0x38, 0x00, 0x90, 0x46, 0x00,
|
||||
0x14, 0xAE, 0x47, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0xC0, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x80, 0xBF, 0xC1, 0x02, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x08, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0A, 0xD7, 0xA3, 0xBB, 0x00, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x5E, 0x02, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x5F, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x27, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x53, 0x02, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x32, 0x02, 0x0F, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x80, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80,
|
||||
0x80, 0x3D, 0x00, 0x00, 0x00, 0xE0, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x3F,
|
||||
0x33, 0x02, 0x2F, 0x80, 0xE0, 0x46, 0x00, 0x00, 0x00, 0x40, 0x43, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3F, 0x33, 0x02, 0x2F, 0x80,
|
||||
0xE0, 0x46, 0x00, 0x00, 0x00, 0x7C, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x02, 0x2F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x00, 0xE0, 0x3E, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x45, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x02, 0x0F, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x10, 0x01, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x00, 0x0F, 0x00,
|
||||
0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x0F, 0x00, 0x78, 0x56, 0x34, 0x12,
|
||||
0x10, 0x00, 0x0F, 0x00
|
||||
};*/
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2018 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#define CFG11_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x40000)
|
||||
#define REG_CFG11_FIQ_MASK *(( vu8*)(CFG11_REGS_BASE + 0x104))
|
||||
#define REG_CFG11_UNK105 *(( vu8*)(CFG11_REGS_BASE + 0x105)) // Debug related? Mask?
|
||||
#define REG_CFG11_UNK108 *(( vu8*)(CFG11_REGS_BASE + 0x108)) // LGY gamecard related?
|
||||
#define REG_CFG11_CDMA_CNT *(( vu8*)(CFG11_REGS_BASE + 0x10C))
|
||||
#define REG_CFG11_UNK110 *(( vu8*)(CFG11_REGS_BASE + 0x110)) // VRAM related?
|
||||
#define REG_CFG11_GPUPROT *(( vu16*)(CFG11_REGS_BASE + 0x140))
|
||||
#define REG_CFG11_WIFI_POWER *(( vu8*)(CFG11_REGS_BASE + 0x180)) // Used for flight mode?
|
||||
#define REG_CFG11_SPI_CNT *(( vu16*)(CFG11_REGS_BASE + 0x1C0))
|
||||
#define REG_CFG11_UNK200 *(( vu32*)(CFG11_REGS_BASE + 0x200)) // GPIO3 related? 8x4 bits.
|
||||
#define REG_CFG11_GPU_N3DS_CNT *(( vu8*)(CFG11_REGS_BASE + 0x400)) // New3DS-only.
|
||||
#define REG_CFG11_CDMA_PERIPHERALS *(( vu32*)(CFG11_REGS_BASE + 0x410)) // New3DS-only.
|
||||
#define REG_CFG11_BOOTROM_OVERLAY_CNT *(( vu8*)(CFG11_REGS_BASE + 0x420)) // New3DS-only.
|
||||
#define REG_CFG11_BOOTROM_OVERLAY_VAL *(( vu32*)(CFG11_REGS_BASE + 0x424)) // New3DS-only.
|
||||
#define REG_CFG11_UNK428 *(( vu8*)(CFG11_REGS_BASE + 0x428)) // New3DS-only. 1 bit. Enable CPU core 1 access to overlay regs?
|
||||
#define REG_CFG11_SOCINFO *((const vu16*)(CFG11_REGS_BASE + 0xFFC))
|
||||
|
||||
|
||||
// REG_CFG11_FIQ_MASK
|
||||
#define FIQ_MASK_CPU0 (1u)
|
||||
#define FIQ_MASK_CPU1 (1u<<1)
|
||||
#define FIQ_MASK_CPU2 (1u<<2) // New3DS-only.
|
||||
#define FIQ_MASK_CPU3 (1u<<3) // New3DS-only.
|
||||
|
||||
// REG_CFG11_CDMA_CNT
|
||||
#define CDMA_CNT_MIC_E (1u)
|
||||
#define CDMA_CNT_NTRCARD_E (1u<<1)
|
||||
#define CDMA_CNT_CAM1_E (1u<<2)
|
||||
#define CDMA_CNT_CAM2_E (1u<<3)
|
||||
#define CDMA_CNT_SDIO2_E (1u<<4) // WiFi
|
||||
#define CDMA_CNT_SDIO3_E (1u<<5)
|
||||
|
||||
// REG_CFG11_GPUPROT
|
||||
// TODO
|
||||
|
||||
// REG_CFG11_WIFI_POWER
|
||||
#define WIFI_POWER_ON (1u)
|
||||
|
||||
// REG_CFG11_SPI_CNT
|
||||
#define SPI_CNT_SPI1_NEW_IF (1u) // New interface (NSPI).
|
||||
#define SPI_CNT_SPI2_NEW_IF (1u<<1)
|
||||
#define SPI_CNT_SPI3_NEW_IF (1u<<2)
|
||||
|
||||
// REG_CFG11_GPU_N3DS_CNT
|
||||
#define GPU_N3DS_CNT_N3DS_MODE (1u) // Enable access to mem extensions.
|
||||
#define GPU_N3DS_CNT_TEX_FIX (1u<<1) // Fixes some texture glitches in New3DS mode.
|
||||
|
||||
// REG_CFG11_CDMA_PERIPHERALS
|
||||
#define CDMA_PERIPHERALS_ALL (0x3FFFFu)
|
||||
|
||||
// REG_CFG11_BOOTROM_OVERLAY_CNT
|
||||
#define BOOTROM_OVERLAY_CNT_E (1u)
|
||||
|
||||
// REG_CFG11_SOCINFO
|
||||
#define SOCINFO_O3DS (1u) // Also set on New3DS.
|
||||
#define SOCINFO_N3DS_PROTO (1u<<1) // Never saw the daylight?
|
||||
#define SOCINFO_N3DS (1u<<2) // Set on New3DS.
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Sergi Granell (xerpi), Paul LaMendola (paulguy), derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 touchX[5];
|
||||
u16 touchY[5];
|
||||
u16 cpadY[8];
|
||||
u16 cpadX[8];
|
||||
} CdcAdcData;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize CODEC for Circle-Pad/Touchscreen/Sound.
|
||||
*/
|
||||
void CODEC_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the CODEC chip for sleep or poweroff.
|
||||
*/
|
||||
void CODEC_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief The opposite of CODEC_deinit(). Does a partial init.
|
||||
*/
|
||||
void CODEC_wakeup(void);
|
||||
|
||||
/**
|
||||
* @brief Get raw ADC data for Circle-Pad/Touchscreen.
|
||||
*
|
||||
* @param data The output data pointer. Must be 4 bytes aligned.
|
||||
*
|
||||
* @return Returns true if data was available and false otherwise.
|
||||
*/
|
||||
bool CODEC_getRawAdcData(CdcAdcData *data);
|
|
@ -0,0 +1,186 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
|
||||
#define CSND_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x3000)
|
||||
#define REG_CSND_MASTER_VOL *((vu16*)(CSND_REGS_BASE + 0x000)) // CSND master volume 0-0x8000
|
||||
#define REG_CSND_UNK_CNT *((vu16*)(CSND_REGS_BASE + 0x002))
|
||||
|
||||
// 32 sound channels. PSG on channel 8-13 and noise 14-15.
|
||||
#define REG_CSND_CH_CNT(n) *((vu16*)(CSND_REGS_BASE + 0x400 + ((n) * 32)))
|
||||
#define REG_CSND_CH_SR(n) *((vs16*)(CSND_REGS_BASE + 0x402 + ((n) * 32))) // Samplerate
|
||||
#define REG_CSND_CH_VOL_R(n) *((vu16*)(CSND_REGS_BASE + 0x404 + ((n) * 32))) // 0-0x8000
|
||||
#define REG_CSND_CH_VOL_L(n) *((vu16*)(CSND_REGS_BASE + 0x406 + ((n) * 32))) // 0-0x8000
|
||||
#define REG_CSND_CH_VOL(n) *((vu32*)(CSND_REGS_BASE + 0x404 + ((n) * 32))) // R and L combined
|
||||
#define REG_CSND_CH_CAPVOL_R(n) *((vu16*)(CSND_REGS_BASE + 0x408 + ((n) * 32))) // Unconfirmed. 0-0x8000
|
||||
#define REG_CSND_CH_CAPVOL_L(n) *((vu16*)(CSND_REGS_BASE + 0x40A + ((n) * 32))) // Unconfirmed. 0-0x8000
|
||||
#define REG_CSND_CH_CAPVOL(n) *((vu32*)(CSND_REGS_BASE + 0x408 + ((n) * 32))) // R and L combined
|
||||
#define REG_CSND_CH_ST_ADDR(n) *((vu32*)(CSND_REGS_BASE + 0x40C + ((n) * 32))) // Start address and playback position
|
||||
#define REG_CSND_CH_SIZE(n) *((vu32*)(CSND_REGS_BASE + 0x410 + ((n) * 32))) // Size in bytes
|
||||
#define REG_CSND_CH_LP_ADDR(n) *((vu32*)(CSND_REGS_BASE + 0x414 + ((n) * 32))) // Loop restart address
|
||||
#define REG_CSND_CH_ST_ADPCM(n) *((vu32*)(CSND_REGS_BASE + 0x418 + ((n) * 32))) // Start IMA-ADPCM state
|
||||
#define REG_CSND_CH_LP_ADPCM(n) *((vu32*)(CSND_REGS_BASE + 0x41C + ((n) * 32))) // Loop Restart IMA-ADPCM state
|
||||
|
||||
// 2 capture units for right and left side.
|
||||
#define REG_CSND_CAP_CNT(n) *((vu16*)(CSND_REGS_BASE + 0x800 + ((n) * 16)))
|
||||
#define REG_CSND_CAP_SR(n) *((vs16*)(CSND_REGS_BASE + 0x804 + ((n) * 16))) // Samplerate
|
||||
#define REG_CSND_CAP_SIZE(n) *((vu32*)(CSND_REGS_BASE + 0x808 + ((n) * 16))) // Capture length in bytes
|
||||
#define REG_CSND_CAP_ADDR(n) *((vu32*)(CSND_REGS_BASE + 0x80C + ((n) * 16))) // Address
|
||||
|
||||
|
||||
// REG_CSND_CH_CNT
|
||||
#define CSND_CH_DUTY(d) (d) // For PSG (channel 8-13) only. In 12.5% units. 0 = high/12.5%.
|
||||
#define CSND_CH_LINEAR_INTERP (1u<<6) // Linear interpolation
|
||||
#define CSND_CH_HOLD (1u<<7) // Hold last sample after one shot.
|
||||
#define CSND_CH_PLAYING (1u<<14)
|
||||
#define CSND_CH_START (1u<<15)
|
||||
|
||||
enum
|
||||
{
|
||||
CSND_CH_RPT_MANUAL = 0u<<10,
|
||||
CSND_CH_RPT_LOOP = 1u<<10,
|
||||
CSND_CH_RPT_ONE_SHOT = 2u<<10
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CSND_CH_FMT_PCM8 = 0u<<12, // Signed PCM8
|
||||
CSND_CH_FMT_PCM16 = 1u<<12, // Signed PCM16 little endian
|
||||
CSND_CH_FMT_IMA_ADPCM = 2u<<12,
|
||||
CSND_CH_FMT_PSG_NOISE = 3u<<12
|
||||
};
|
||||
|
||||
|
||||
// REG_CSND_CAP_CNT
|
||||
#define CSND_CAP_RPT_LOOP (0u)
|
||||
#define CSND_CAP_RPT_ONE_SHOT (1u)
|
||||
#define CSND_CAP_FMT_PCM16 (0u) // Signed PCM16 little endian
|
||||
#define CSND_CAP_FMT_PCM8 (1u<<1) // Signed PCM8
|
||||
#define CSND_CAP_UNK2 (1u<<2)
|
||||
#define CSND_CAP_START (1u<<15)
|
||||
|
||||
|
||||
// Samplerate helpers
|
||||
#define CSND_SAMPLERATE(s) (-(s16)(67027964u / (s)))
|
||||
#define CSND_PSG_FREQ(f) (CSND_SAMPLERATE(32u * (f)))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the CSND hardware.
|
||||
*/
|
||||
void CSND_init(void);
|
||||
|
||||
/**
|
||||
* @brief Calculates the left and right volumes.
|
||||
*
|
||||
* @param[in] lvol The left volume.
|
||||
* @param[in] rvol The right volume.
|
||||
*
|
||||
* @return The volume pair needed for CSND_setupCh().
|
||||
*/
|
||||
static inline u32 CSND_calcVol(float lvol, float rvol)
|
||||
{
|
||||
return (u32)(lvol * 32768.0f)<<16 | (u16)(rvol * 32768.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets up a channel for sound playback (in paused state).
|
||||
*
|
||||
* @param[in] ch The sound channel. 0-31.
|
||||
* @param[in] sampleRate The sample rate.
|
||||
* @param[in] vol The L/R volume pair.
|
||||
* @param[in] data The start address.
|
||||
* @param[in] data2 The loop restart address.
|
||||
* @param[in] size The size.
|
||||
* @param[in] flags The flags.
|
||||
*/
|
||||
void CSND_setupCh(u8 ch, s16 sampleRate, u32 vol, const u32 *const data, const u32 *const data2, u32 size, u16 flags);
|
||||
|
||||
/**
|
||||
* @brief Pauses or unpauses a sound channel.
|
||||
*
|
||||
* @param[in] ch The sound channel. 0-31.
|
||||
* @param[in] playing The play state.
|
||||
*/
|
||||
static inline void CSND_setChState(u8 ch, bool playing)
|
||||
{
|
||||
REG_CSND_CH_CNT(ch) = (REG_CSND_CH_CNT(ch) & ~CSND_CH_PLAYING) | ((u16)playing<<14);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current audio buffer position (address).
|
||||
*
|
||||
* @param[in] ch The sound channel. 0-31.
|
||||
*
|
||||
* @return The playback position (address).
|
||||
*/
|
||||
static inline u32 CSND_getChPos(u8 ch)
|
||||
{
|
||||
return REG_CSND_CH_ST_ADDR(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops a sound channel.
|
||||
*
|
||||
* @param[in] ch The sound channel. 0-31.
|
||||
*/
|
||||
static inline void CSND_stopCh(u8 ch)
|
||||
{
|
||||
REG_CSND_CH_CNT(ch) = 0; // Stop
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Captures the output of all left/right sound channels combined.
|
||||
*
|
||||
* @param[in] ch The capture side. 0 = right, 1 = left.
|
||||
* @param[in] sampleRate The sample rate.
|
||||
* @param data The output address.
|
||||
* @param[in] size The size.
|
||||
* @param[in] flags The flags.
|
||||
*/
|
||||
void CSND_startCap(u8 ch, s16 sampleRate, u32 *const data, u32 size, u16 flags);
|
||||
|
||||
/**
|
||||
* @brief Returns the current capture buffer position (address).
|
||||
*
|
||||
* @param[in] ch The capture side. 0 = right, 1 = left.
|
||||
*
|
||||
* @return The capture position (address).
|
||||
*/
|
||||
static inline u32 CSND_getCapPos(u8 ch)
|
||||
{
|
||||
return REG_CSND_CAP_ADDR(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops a capture channel.
|
||||
*
|
||||
* @param[in] ch The capture side. 0 = right, 1 = left.
|
||||
*/
|
||||
static inline void CSND_stopCap(u8 ch)
|
||||
{
|
||||
REG_CSND_CAP_CNT(ch) = 0;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define GPIO_INPUT (0u)
|
||||
#define GPIO_OUTPUT (1u)
|
||||
#define GPIO_EDGE_FALLING (0u)
|
||||
#define GPIO_EDGE_RISING (1u<<1)
|
||||
#define GPIO_IRQ_ENABLE (1u<<2)
|
||||
|
||||
|
||||
// bits 3-7 pin number, bits 0-3 reg index.
|
||||
#define MAKE_GPIO(pin, reg) ((pin)<<3 | (reg))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GPIO_1_0 = MAKE_GPIO(0u, 0u),
|
||||
GPIO_1_1 = MAKE_GPIO(1u, 0u),
|
||||
GPIO_1_2 = MAKE_GPIO(2u, 0u),
|
||||
|
||||
GPIO_2_0 = MAKE_GPIO(0u, 1u),
|
||||
GPIO_2_1 = MAKE_GPIO(1u, 1u),
|
||||
GPIO_2_2 = MAKE_GPIO(0u, 2u), // REG_GPIO2_DAT2
|
||||
|
||||
GPIO_3_0 = MAKE_GPIO(0u, 3u),
|
||||
GPIO_3_1 = MAKE_GPIO(1u, 3u),
|
||||
GPIO_3_2 = MAKE_GPIO(2u, 3u),
|
||||
GPIO_3_3 = MAKE_GPIO(3u, 3u),
|
||||
GPIO_3_4 = MAKE_GPIO(4u, 3u),
|
||||
GPIO_3_5 = MAKE_GPIO(5u, 3u),
|
||||
GPIO_3_6 = MAKE_GPIO(6u, 3u),
|
||||
GPIO_3_7 = MAKE_GPIO(7u, 3u),
|
||||
GPIO_3_8 = MAKE_GPIO(8u, 3u),
|
||||
GPIO_3_9 = MAKE_GPIO(9u, 3u),
|
||||
GPIO_3_10 = MAKE_GPIO(10u, 3u),
|
||||
GPIO_3_11 = MAKE_GPIO(11u, 3u),
|
||||
GPIO_3_12 = MAKE_GPIO(0u, 4u), // REG_GPIO3_DAT2
|
||||
|
||||
// Aliases
|
||||
GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while touchscreen pen down. Unused after CODEC init.
|
||||
GPIO_1_SHELL = GPIO_1_2, // 1 when closed.
|
||||
|
||||
GPIO_2_HEADPH_JACK = GPIO_2_0, // Used after CODEC init.
|
||||
|
||||
GPIO_3_HEADPH_JACK = GPIO_3_8, // Unused/other function after CODEC init.
|
||||
GPIO_3_MCU = GPIO_3_9
|
||||
} Gpio;
|
||||
|
||||
#undef MAKE_GPIO
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configures the specified GPIO.
|
||||
*
|
||||
* @param[in] gpio The gpio.
|
||||
* @param[in] cfg The configuration.
|
||||
*/
|
||||
void GPIO_config(Gpio gpio, u8 cfg);
|
||||
|
||||
/**
|
||||
* @brief Reads a GPIO pin.
|
||||
*
|
||||
* @param[in] gpio The gpio.
|
||||
*
|
||||
* @return The state. Either 0 or 1.
|
||||
*/
|
||||
bool GPIO_read(Gpio gpio);
|
||||
|
||||
/**
|
||||
* @brief Writes a GPIO pin.
|
||||
*
|
||||
* @param[in] gpio The gpio.
|
||||
* @param[in] val The value. Must be 0 or 1.
|
||||
*/
|
||||
void GPIO_write(Gpio gpio, bool val);
|
|
@ -0,0 +1,769 @@
|
|||
// From https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/gpu/registers.h
|
||||
|
||||
/**
|
||||
* @file registers.h
|
||||
* @description GPU registers.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
///@name Miscellaneous registers (0x000-0x03F)
|
||||
///@{
|
||||
#define GPUREG_IRQ_ACK 0x0000 ///< Acknowledge P3D IRQ.
|
||||
#define GPUREG_0001 0x0001 ///< Unknown.
|
||||
#define GPUREG_0002 0x0002 ///< Unknown.
|
||||
#define GPUREG_0003 0x0003 ///< Unknown.
|
||||
#define GPUREG_0004 0x0004 ///< Unknown.
|
||||
#define GPUREG_0005 0x0005 ///< Unknown.
|
||||
#define GPUREG_0006 0x0006 ///< Unknown.
|
||||
#define GPUREG_0007 0x0007 ///< Unknown.
|
||||
#define GPUREG_0008 0x0008 ///< Unknown.
|
||||
#define GPUREG_0009 0x0009 ///< Unknown.
|
||||
#define GPUREG_000A 0x000A ///< Unknown.
|
||||
#define GPUREG_000B 0x000B ///< Unknown.
|
||||
#define GPUREG_000C 0x000C ///< Unknown.
|
||||
#define GPUREG_000D 0x000D ///< Unknown.
|
||||
#define GPUREG_000E 0x000E ///< Unknown.
|
||||
#define GPUREG_000F 0x000F ///< Unknown.
|
||||
#define GPUREG_FINALIZE 0x0010 ///< Used to finalize GPU drawing.
|
||||
#define GPUREG_0011 0x0011 ///< Unknown.
|
||||
#define GPUREG_0012 0x0012 ///< Unknown.
|
||||
#define GPUREG_0013 0x0013 ///< Unknown.
|
||||
#define GPUREG_0014 0x0014 ///< Unknown.
|
||||
#define GPUREG_0015 0x0015 ///< Unknown.
|
||||
#define GPUREG_0016 0x0016 ///< Unknown.
|
||||
#define GPUREG_0017 0x0017 ///< Unknown.
|
||||
#define GPUREG_0018 0x0018 ///< Unknown.
|
||||
#define GPUREG_0019 0x0019 ///< Unknown.
|
||||
#define GPUREG_001A 0x001A ///< Unknown.
|
||||
#define GPUREG_001B 0x001B ///< Unknown.
|
||||
#define GPUREG_001C 0x001C ///< Unknown.
|
||||
#define GPUREG_001D 0x001D ///< Unknown.
|
||||
#define GPUREG_001E 0x001E ///< Unknown.
|
||||
#define GPUREG_001F 0x001F ///< Unknown.
|
||||
#define GPUREG_IRQ_CMP 0x0020 ///< Triggers a P3D IRQ when the value written to GPUREG_FINALIZE matches this.
|
||||
#define GPUREG_0021 0x0021 ///< Unknown.
|
||||
#define GPUREG_0022 0x0022 ///< Unknown.
|
||||
#define GPUREG_0023 0x0023 ///< Unknown.
|
||||
#define GPUREG_0024 0x0024 ///< Unknown.
|
||||
#define GPUREG_0025 0x0025 ///< Unknown.
|
||||
#define GPUREG_0026 0x0026 ///< Unknown.
|
||||
#define GPUREG_0027 0x0027 ///< Unknown.
|
||||
#define GPUREG_0028 0x0028 ///< Unknown.
|
||||
#define GPUREG_0029 0x0029 ///< Unknown.
|
||||
#define GPUREG_002A 0x002A ///< Unknown.
|
||||
#define GPUREG_002B 0x002B ///< Unknown.
|
||||
#define GPUREG_002C 0x002C ///< Unknown.
|
||||
#define GPUREG_002D 0x002D ///< Unknown.
|
||||
#define GPUREG_002E 0x002E ///< Unknown.
|
||||
#define GPUREG_002F 0x002F ///< Unknown.
|
||||
#define GPUREG_IRQ_MASK 0x0030 ///< IRQ mask. Each bit 0 = enable.
|
||||
#define GPUREG_0031 0x0031 ///< Unknown.
|
||||
#define GPUREG_0032 0x0032 ///< Unknown.
|
||||
#define GPUREG_0033 0x0033 ///< Unknown.
|
||||
#define GPUREG_IRQ_AUTOSTOP 0x0034 ///< 1 = stop cmd list processing on IRQ.
|
||||
#define GPUREG_0035 0x0035 ///< Unknown.
|
||||
#define GPUREG_0036 0x0036 ///< Unknown.
|
||||
#define GPUREG_0037 0x0037 ///< Unknown.
|
||||
#define GPUREG_0038 0x0038 ///< Unknown.
|
||||
#define GPUREG_0039 0x0039 ///< Unknown.
|
||||
#define GPUREG_003A 0x003A ///< Unknown.
|
||||
#define GPUREG_003B 0x003B ///< Unknown.
|
||||
#define GPUREG_003C 0x003C ///< Unknown.
|
||||
#define GPUREG_003D 0x003D ///< Unknown.
|
||||
#define GPUREG_003E 0x003E ///< Unknown.
|
||||
#define GPUREG_003F 0x003F ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Rasterizer registers (0x040-0x07F)
|
||||
///@{
|
||||
#define GPUREG_FACECULLING_CONFIG 0x0040 ///< Face culling configuration.
|
||||
#define GPUREG_VIEWPORT_WIDTH 0x0041 ///< Viewport width.
|
||||
#define GPUREG_VIEWPORT_INVW 0x0042 ///< Inverted viewport width.
|
||||
#define GPUREG_VIEWPORT_HEIGHT 0x0043 ///< Viewport height.
|
||||
#define GPUREG_VIEWPORT_INVH 0x0044 ///< Inverted viewport height.
|
||||
#define GPUREG_0045 0x0045 ///< Unknown
|
||||
#define GPUREG_0046 0x0046 ///< Unknown
|
||||
#define GPUREG_FRAGOP_CLIP 0x0047 ///< Unknown
|
||||
#define GPUREG_FRAGOP_CLIP_DATA0 0x0048 ///< Unknown
|
||||
#define GPUREG_FRAGOP_CLIP_DATA1 0x0049 ///< Unknown
|
||||
#define GPUREG_FRAGOP_CLIP_DATA2 0x004A ///< Unknown
|
||||
#define GPUREG_FRAGOP_CLIP_DATA3 0x004B ///< Unknown
|
||||
#define GPUREG_004C 0x004C ///< Unknown
|
||||
#define GPUREG_DEPTHMAP_SCALE 0x004D ///< Depth map scale.
|
||||
#define GPUREG_DEPTHMAP_OFFSET 0x004E ///< Depth map offset.
|
||||
#define GPUREG_SH_OUTMAP_TOTAL 0x004F ///< Shader output map total.
|
||||
#define GPUREG_SH_OUTMAP_O0 0x0050 ///< Shader output map 0.
|
||||
#define GPUREG_SH_OUTMAP_O1 0x0051 ///< Shader output map 1.
|
||||
#define GPUREG_SH_OUTMAP_O2 0x0052 ///< Shader output map 2.
|
||||
#define GPUREG_SH_OUTMAP_O3 0x0053 ///< Shader output map 3.
|
||||
#define GPUREG_SH_OUTMAP_O4 0x0054 ///< Shader output map 4.
|
||||
#define GPUREG_SH_OUTMAP_O5 0x0055 ///< Shader output map 5.
|
||||
#define GPUREG_SH_OUTMAP_O6 0x0056 ///< Shader output map 6.
|
||||
#define GPUREG_0057 0x0057 ///< Unknown
|
||||
#define GPUREG_0058 0x0058 ///< Unknown
|
||||
#define GPUREG_0059 0x0059 ///< Unknown
|
||||
#define GPUREG_005A 0x005A ///< Unknown
|
||||
#define GPUREG_005B 0x005B ///< Unknown
|
||||
#define GPUREG_005C 0x005C ///< Unknown
|
||||
#define GPUREG_005D 0x005D ///< Unknown
|
||||
#define GPUREG_005E 0x005E ///< Unknown
|
||||
#define GPUREG_005F 0x005F ///< Unknown
|
||||
#define GPUREG_0060 0x0060 ///< Unknown
|
||||
#define GPUREG_EARLYDEPTH_FUNC 0x0061 ///< Unknown
|
||||
#define GPUREG_EARLYDEPTH_TEST1 0x0062 ///< Unknown
|
||||
#define GPUREG_EARLYDEPTH_CLEAR 0x0063 ///< Unknown
|
||||
#define GPUREG_SH_OUTATTR_MODE 0x0064 ///< Shader output attributes mode.
|
||||
#define GPUREG_SCISSORTEST_MODE 0x0065 ///< Scissor test mode.
|
||||
#define GPUREG_SCISSORTEST_POS 0x0066 ///< Scissor test position.
|
||||
#define GPUREG_SCISSORTEST_DIM 0x0067 ///< Scissor text dimensions.
|
||||
#define GPUREG_VIEWPORT_XY 0x0068 ///< Viewport X and Y.
|
||||
#define GPUREG_0069 0x0069 ///< Unknown
|
||||
#define GPUREG_EARLYDEPTH_DATA 0x006A ///< Unknown
|
||||
#define GPUREG_006B 0x006B ///< Unknown
|
||||
#define GPUREG_006C 0x006C ///< Unknown
|
||||
#define GPUREG_DEPTHMAP_ENABLE 0x006D ///< Depth map enable.
|
||||
#define GPUREG_RENDERBUF_DIM 0x006E ///< Renderbuffer dimensions.
|
||||
#define GPUREG_SH_OUTATTR_CLOCK 0x006F ///< Shader output attributes clock enable.
|
||||
#define GPUREG_0070 0x0070 ///< Unknown
|
||||
#define GPUREG_0071 0x0071 ///< Unknown
|
||||
#define GPUREG_0072 0x0072 ///< Unknown
|
||||
#define GPUREG_0073 0x0073 ///< Unknown
|
||||
#define GPUREG_0074 0x0074 ///< Unknown
|
||||
#define GPUREG_0075 0x0075 ///< Unknown
|
||||
#define GPUREG_0076 0x0076 ///< Unknown
|
||||
#define GPUREG_0077 0x0077 ///< Unknown
|
||||
#define GPUREG_0078 0x0078 ///< Unknown
|
||||
#define GPUREG_0079 0x0079 ///< Unknown
|
||||
#define GPUREG_007A 0x007A ///< Unknown
|
||||
#define GPUREG_007B 0x007B ///< Unknown
|
||||
#define GPUREG_007C 0x007C ///< Unknown
|
||||
#define GPUREG_007D 0x007D ///< Unknown
|
||||
#define GPUREG_007E 0x007E ///< Unknown
|
||||
#define GPUREG_007F 0x007F ///< Unknown
|
||||
///@}
|
||||
|
||||
///@name Texturing registers (0x080-0x0FF)
|
||||
///@{
|
||||
#define GPUREG_TEXUNIT_CONFIG 0x0080 ///< Texture unit configuration.
|
||||
#define GPUREG_TEXUNIT0_BORDER_COLOR 0x0081 ///< Texture unit 0 border color.
|
||||
#define GPUREG_TEXUNIT0_DIM 0x0082 ///< Texture unit 0 dimensions.
|
||||
#define GPUREG_TEXUNIT0_PARAM 0x0083 ///< Texture unit 0 parameters.
|
||||
#define GPUREG_TEXUNIT0_LOD 0x0084 ///< Texture unit 0 LOD.
|
||||
#define GPUREG_TEXUNIT0_ADDR1 0x0085 ///< Texture unit 0 address.
|
||||
#define GPUREG_TEXUNIT0_ADDR2 0x0086 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_ADDR3 0x0087 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_ADDR4 0x0088 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_ADDR5 0x0089 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_ADDR6 0x008A ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_SHADOW 0x008B ///< Unknown.
|
||||
#define GPUREG_008C 0x008C ///< Unknown.
|
||||
#define GPUREG_008D 0x008D ///< Unknown.
|
||||
#define GPUREG_TEXUNIT0_TYPE 0x008E ///< Texture unit 0 type.
|
||||
#define GPUREG_LIGHTING_ENABLE0 0x008F ///< Lighting toggle.
|
||||
#define GPUREG_0090 0x0090 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT1_BORDER_COLOR 0x0091 ///< Texture unit 1 border color.
|
||||
#define GPUREG_TEXUNIT1_DIM 0x0092 ///< Texture unit 1 dimensions.
|
||||
#define GPUREG_TEXUNIT1_PARAM 0x0093 ///< Texture unit 1 parameters.
|
||||
#define GPUREG_TEXUNIT1_LOD 0x0094 ///< Texture unit 1 LOD.
|
||||
#define GPUREG_TEXUNIT1_ADDR 0x0095 ///< Texture unit 1 address.
|
||||
#define GPUREG_TEXUNIT1_TYPE 0x0096 ///< Texture unit 1 type.
|
||||
#define GPUREG_0097 0x0097 ///< Unknown.
|
||||
#define GPUREG_0098 0x0098 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT2_BORDER_COLOR 0x0099 ///< Texture unit 2 border color.
|
||||
#define GPUREG_TEXUNIT2_DIM 0x009A ///< Texture unit 2 dimensions.
|
||||
#define GPUREG_TEXUNIT2_PARAM 0x009B ///< Texture unit 2 parameters.
|
||||
#define GPUREG_TEXUNIT2_LOD 0x009C ///< Texture unit 2 LOD.
|
||||
#define GPUREG_TEXUNIT2_ADDR 0x009D ///< Texture unit 2 address.
|
||||
#define GPUREG_TEXUNIT2_TYPE 0x009E ///< Texture unit 2 type.
|
||||
#define GPUREG_009F 0x009F ///< Unknown.
|
||||
#define GPUREG_00A0 0x00A0 ///< Unknown.
|
||||
#define GPUREG_00A1 0x00A1 ///< Unknown.
|
||||
#define GPUREG_00A2 0x00A2 ///< Unknown.
|
||||
#define GPUREG_00A3 0x00A3 ///< Unknown.
|
||||
#define GPUREG_00A4 0x00A4 ///< Unknown.
|
||||
#define GPUREG_00A5 0x00A5 ///< Unknown.
|
||||
#define GPUREG_00A6 0x00A6 ///< Unknown.
|
||||
#define GPUREG_00A7 0x00A7 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX0 0x00A8 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX1 0x00A9 ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX2 0x00AA ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX3 0x00AB ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX4 0x00A ///< Unknown.
|
||||
#define GPUREG_TEXUNIT3_PROCTEX5 0x00D ///< Unknown.
|
||||
#define GPUREG_00AE 0x00AE ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT 0x00AF ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA0 0x00B0 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA1 0x00B1 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA2 0x00B2 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA3 0x00B3 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA4 0x00B4 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA5 0x00B5 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA6 0x00B6 ///< Unknown.
|
||||
#define GPUREG_PROCTEX_LUT_DATA7 0x00B7 ///< Unknown.
|
||||
#define GPUREG_00B8 0x00B8 ///< Unknown.
|
||||
#define GPUREG_00B9 0x00B9 ///< Unknown.
|
||||
#define GPUREG_00BA 0x00BA ///< Unknown.
|
||||
#define GPUREG_00BB 0x00BB ///< Unknown.
|
||||
#define GPUREG_00BC 0x00BC ///< Unknown.
|
||||
#define GPUREG_00BD 0x00BD ///< Unknown.
|
||||
#define GPUREG_00BE 0x00BE ///< Unknown.
|
||||
#define GPUREG_00BF 0x00BF ///< Unknown.
|
||||
#define GPUREG_TEXENV0_SOURCE 0x00C0 ///< Texture env 0 source.
|
||||
#define GPUREG_TEXENV0_OPERAND 0x00C1 ///< Texture env 0 operand.
|
||||
#define GPUREG_TEXENV0_COMBINER 0x00C2 ///< Texture env 0 combiner.
|
||||
#define GPUREG_TEXENV0_COLOR 0x00C3 ///< Texture env 0 color.
|
||||
#define GPUREG_TEXENV0_SCALE 0x00C4 ///< Texture env 0 scale.
|
||||
#define GPUREG_00C5 0x00C5 ///< Unknown.
|
||||
#define GPUREG_00C6 0x00C6 ///< Unknown.
|
||||
#define GPUREG_00C7 0x00C7 ///< Unknown.
|
||||
#define GPUREG_TEXENV1_SOURCE 0x00C8 ///< Texture env 1 source.
|
||||
#define GPUREG_TEXENV1_OPERAND 0x00C9 ///< Texture env 1 operand.
|
||||
#define GPUREG_TEXENV1_COMBINER 0x00CA ///< Texture env 1 combiner.
|
||||
#define GPUREG_TEXENV1_COLOR 0x00CB ///< Texture env 1 color.
|
||||
#define GPUREG_TEXENV1_SCALE 0x00CC ///< Texture env 1 scale.
|
||||
#define GPUREG_00CD 0x00CD ///< Unknown.
|
||||
#define GPUREG_00CE 0x00CE ///< Unknown.
|
||||
#define GPUREG_00CF 0x00CF ///< Unknown.
|
||||
#define GPUREG_TEXENV2_SOURCE 0x00D0 ///< Texture env 2 source.
|
||||
#define GPUREG_TEXENV2_OPERAND 0x00D1 ///< Texture env 2 operand.
|
||||
#define GPUREG_TEXENV2_COMBINER 0x00D2 ///< Texture env 2 combiner.
|
||||
#define GPUREG_TEXENV2_COLOR 0x00D3 ///< Texture env 2 color.
|
||||
#define GPUREG_TEXENV2_SCALE 0x00D4 ///< Texture env 2 scale.
|
||||
#define GPUREG_00D5 0x00D5 ///< Unknown.
|
||||
#define GPUREG_00D6 0x00D6 ///< Unknown.
|
||||
#define GPUREG_00D7 0x00D7 ///< Unknown.
|
||||
#define GPUREG_TEXENV3_SOURCE 0x00D8 ///< Texture env 3 source.
|
||||
#define GPUREG_TEXENV3_OPERAND 0x00D9 ///< Texture env 3 operand.
|
||||
#define GPUREG_TEXENV3_COMBINER 0x00DA ///< Texture env 3 combiner.
|
||||
#define GPUREG_TEXENV3_COLOR 0x00DB ///< Texture env 3 color.
|
||||
#define GPUREG_TEXENV3_SCALE 0x00DC ///< Texture env 3 scale.
|
||||
#define GPUREG_00DD 0x00DD ///< Unknown.
|
||||
#define GPUREG_00DE 0x00DE ///< Unknown.
|
||||
#define GPUREG_00DF 0x00DF ///< Unknown.
|
||||
#define GPUREG_TEXENV_UPDATE_BUFFER 0x00E0 ///< Texture env buffer update flag.
|
||||
#define GPUREG_FOG_COLOR 0x00E1 ///< Unknown.
|
||||
#define GPUREG_00E2 0x00E2 ///< Unknown.
|
||||
#define GPUREG_00E3 0x00E3 ///< Unknown.
|
||||
#define GPUREG_GAS_ATTENUATION 0x00E4 ///< Unknown.
|
||||
#define GPUREG_GAS_ACCMAX 0x00E5 ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_INDEX 0x00E6 ///< Unknown.
|
||||
#define GPUREG_00E7 0x00E7 ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA0 0x00E8 ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA1 0x00E9 ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA2 0x00EA ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA3 0x00EB ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA4 0x00EC ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA5 0x00ED ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA6 0x00EE ///< Unknown.
|
||||
#define GPUREG_FOG_LUT_DATA7 0x00EF ///< Unknown.
|
||||
#define GPUREG_TEXENV4_SOURCE 0x00F0 ///< Texture env 4 source.
|
||||
#define GPUREG_TEXENV4_OPERAND 0x00F1 ///< Texture env 4 operand.
|
||||
#define GPUREG_TEXENV4_COMBINER 0x00F2 ///< Texture env 4 combiner.
|
||||
#define GPUREG_TEXENV4_COLOR 0x00F3 ///< Texture env 4 color.
|
||||
#define GPUREG_TEXENV4_SCALE 0x00F4 ///< Texture env 4 scale.
|
||||
#define GPUREG_00F5 0x00F5 ///< Unknown.
|
||||
#define GPUREG_00F6 0x00F6 ///< Unknown.
|
||||
#define GPUREG_00F7 0x00F7 ///< Unknown.
|
||||
#define GPUREG_TEXENV5_SOURCE 0x00F8 ///< Texture env 5 source.
|
||||
#define GPUREG_TEXENV5_OPERAND 0x00F9 ///< Texture env 5 operand.
|
||||
#define GPUREG_TEXENV5_COMBINER 0x00FA ///< Texture env 5 combiner.
|
||||
#define GPUREG_TEXENV5_COLOR 0x00FB ///< Texture env 5 color.
|
||||
#define GPUREG_TEXENV5_SCALE 0x00FC ///< Texture env 5 scale.
|
||||
#define GPUREG_TEXENV_BUFFER_COLOR 0x00FD ///< Texture env buffer color.
|
||||
#define GPUREG_00FE 0x00FE ///< Unknown.
|
||||
#define GPUREG_00FF 0x00FF ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Framebuffer registers (0x100-0x13F)
|
||||
///@{
|
||||
#define GPUREG_COLOR_OPERATION 0x0100 ///< Configures fragment operation and blend mode.
|
||||
#define GPUREG_BLEND_FUNC 0x0101 ///< Blend function configuration.
|
||||
#define GPUREG_LOGIC_OP 0x0102 ///< Logical operator configuration.
|
||||
#define GPUREG_BLEND_COLOR 0x0103 ///< Blend color.
|
||||
#define GPUREG_FRAGOP_ALPHA_TEST 0x0104 ///< Alpha test configuration.
|
||||
#define GPUREG_STENCIL_TEST 0x0105 ///< Stencil test configuration.
|
||||
#define GPUREG_STENCIL_OP 0x0106 ///< Stencil test operation.
|
||||
#define GPUREG_DEPTH_COLOR_MASK 0x0107 ///< Depth test and color mask configuration.
|
||||
#define GPUREG_0108 0x0108 ///< Unknown.
|
||||
#define GPUREG_0109 0x0109 ///< Unknown.
|
||||
#define GPUREG_010A 0x010A ///< Unknown.
|
||||
#define GPUREG_010B 0x010B ///< Unknown.
|
||||
#define GPUREG_010C 0x010C ///< Unknown.
|
||||
#define GPUREG_010D 0x010D ///< Unknown.
|
||||
#define GPUREG_010E 0x010E ///< Unknown.
|
||||
#define GPUREG_010F 0x010F ///< Unknown.
|
||||
#define GPUREG_FRAMEBUFFER_INVALIDATE 0x0110 ///< Invalidates the frame buffer.
|
||||
#define GPUREG_FRAMEBUFFER_FLUSH 0x0111 ///< Flushes the frame buffer.
|
||||
#define GPUREG_COLORBUFFER_READ 0x0112 ///< Reads from the color buffer.
|
||||
#define GPUREG_COLORBUFFER_WRITE 0x0113 ///< Writes to the color buffer.
|
||||
#define GPUREG_DEPTHBUFFER_READ 0x0114 ///< Reads from the depth buffer.
|
||||
#define GPUREG_DEPTHBUFFER_WRITE 0x0115 ///< Writes to the depth buffer.
|
||||
#define GPUREG_DEPTHBUFFER_FORMAT 0x0116 ///< Depth buffer format.
|
||||
#define GPUREG_COLORBUFFER_FORMAT 0x0117 ///< Color buffer format.
|
||||
#define GPUREG_EARLYDEPTH_TEST2 0x0118 ///< Unknown.
|
||||
#define GPUREG_0119 0x0119 ///< Unknown.
|
||||
#define GPUREG_011A 0x011A ///< Unknown.
|
||||
#define GPUREG_FRAMEBUFFER_BLOCK32 0x011B ///< Frame buffer block 32.
|
||||
#define GPUREG_DEPTHBUFFER_LOC 0x011C ///< Depth buffer location.
|
||||
#define GPUREG_COLORBUFFER_LOC 0x011D ///< Color buffer location.
|
||||
#define GPUREG_FRAMEBUFFER_DIM 0x011E ///< Frame buffer dimensions.
|
||||
#define GPUREG_011F 0x011F ///< Unknown.
|
||||
#define GPUREG_GAS_LIGHT_XY 0x0120 ///< Unknown.
|
||||
#define GPUREG_GAS_LIGHT_Z 0x0121 ///< Unknown.
|
||||
#define GPUREG_GAS_LIGHT_Z_COLOR 0x0122 ///< Unknown.
|
||||
#define GPUREG_GAS_LUT_INDEX 0x0123 ///< Unknown.
|
||||
#define GPUREG_GAS_LUT_DATA 0x0124 ///< Unknown.
|
||||
#define GPUREG_GAS_ACCMAX_FEEDBACK 0x0125 ///< Unknown.
|
||||
#define GPUREG_GAS_DELTAZ_DEPTH 0x0126 ///< Unknown.
|
||||
#define GPUREG_0127 0x0127 ///< Unknown.
|
||||
#define GPUREG_0128 0x0128 ///< Unknown.
|
||||
#define GPUREG_0129 0x0129 ///< Unknown.
|
||||
#define GPUREG_012A 0x012A ///< Unknown.
|
||||
#define GPUREG_012B 0x012B ///< Unknown.
|
||||
#define GPUREG_012C 0x012C ///< Unknown.
|
||||
#define GPUREG_012D 0x012D ///< Unknown.
|
||||
#define GPUREG_012E 0x012E ///< Unknown.
|
||||
#define GPUREG_012F 0x012F ///< Unknown.
|
||||
#define GPUREG_FRAGOP_SHADOW 0x0130 ///< Unknown.
|
||||
#define GPUREG_0131 0x0131 ///< Unknown.
|
||||
#define GPUREG_0132 0x0132 ///< Unknown.
|
||||
#define GPUREG_0133 0x0133 ///< Unknown.
|
||||
#define GPUREG_0134 0x0134 ///< Unknown.
|
||||
#define GPUREG_0135 0x0135 ///< Unknown.
|
||||
#define GPUREG_0136 0x0136 ///< Unknown.
|
||||
#define GPUREG_0137 0x0137 ///< Unknown.
|
||||
#define GPUREG_0138 0x0138 ///< Unknown.
|
||||
#define GPUREG_0139 0x0139 ///< Unknown.
|
||||
#define GPUREG_013A 0x013A ///< Unknown.
|
||||
#define GPUREG_013B 0x013B ///< Unknown.
|
||||
#define GPUREG_013C 0x013C ///< Unknown.
|
||||
#define GPUREG_013D 0x013D ///< Unknown.
|
||||
#define GPUREG_013E 0x013E ///< Unknown.
|
||||
#define GPUREG_013F 0x013F ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Fragment lighting registers (0x140-0x1FF)
|
||||
///@{
|
||||
#define GPUREG_LIGHT0_SPECULAR0 0x0140 ///< Light 0 specular lighting.
|
||||
#define GPUREG_LIGHT0_SPECULAR1 0x0141 ///< Light 0 specular lighting.
|
||||
#define GPUREG_LIGHT0_DIFFUSE 0x0142 ///< Light 0 diffuse lighting.
|
||||
#define GPUREG_LIGHT0_AMBIENT 0x0143 ///< Light 0 ambient lighting.
|
||||
#define GPUREG_LIGHT0_XY 0x0144 ///< Light 0 X and Y.
|
||||
#define GPUREG_LIGHT0_Z 0x0145 ///< Light 0 Z.
|
||||
#define GPUREG_LIGHT0_SPOTDIR_XY 0x0146 ///< Light 0 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT0_SPOTDIR_Z 0x0147 ///< Light 0 spotlight direction Z.
|
||||
#define GPUREG_0148 0x0148 ///< Unknown.
|
||||
#define GPUREG_LIGHT0_CONFIG 0x0149 ///< Light 0 configuration.
|
||||
#define GPUREG_LIGHT0_ATTENUATION_BIAS 0x014A ///< Light 0 attenuation bias.
|
||||
#define GPUREG_LIGHT0_ATTENUATION_SCALE 0x014B ///< Light 0 attenuation scale.
|
||||
#define GPUREG_014C 0x014C ///< Unknown.
|
||||
#define GPUREG_014D 0x014D ///< Unknown.
|
||||
#define GPUREG_014E 0x014E ///< Unknown.
|
||||
#define GPUREG_014F 0x014F ///< Unknown.
|
||||
#define GPUREG_LIGHT1_SPECULAR0 0x0150 ///< Light 1 specular lighting.
|
||||
#define GPUREG_LIGHT1_SPECULAR1 0x0151 ///< Light 1 specular lighting.
|
||||
#define GPUREG_LIGHT1_DIFFUSE 0x0152 ///< Light 1 diffuse lighting.
|
||||
#define GPUREG_LIGHT1_AMBIENT 0x0153 ///< Light 1 ambient lighting.
|
||||
#define GPUREG_LIGHT1_XY 0x0154 ///< Light 1 X and Y.
|
||||
#define GPUREG_LIGHT1_Z 0x0155 ///< Light 1 Z.
|
||||
#define GPUREG_LIGHT1_SPOTDIR_XY 0x0156 ///< Light 1 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT1_SPOTDIR_Z 0x0157 ///< Light 1 spotlight direction Z.
|
||||
#define GPUREG_0158 0x0158 ///< Unknown.
|
||||
#define GPUREG_LIGHT1_CONFIG 0x0159 ///< Light 1 configuration.
|
||||
#define GPUREG_LIGHT1_ATTENUATION_BIAS 0x015A ///< Light 1 attenuation bias.
|
||||
#define GPUREG_LIGHT1_ATTENUATION_SCALE 0x015B ///< Light 1 attenuation scale.
|
||||
#define GPUREG_015C 0x015C ///< Unknown.
|
||||
#define GPUREG_015D 0x015D ///< Unknown.
|
||||
#define GPUREG_015E 0x015E ///< Unknown.
|
||||
#define GPUREG_015F 0x015F ///< Unknown.
|
||||
#define GPUREG_LIGHT2_SPECULAR0 0x0160 ///< Light 2 specular lighting.
|
||||
#define GPUREG_LIGHT2_SPECULAR1 0x0161 ///< Light 2 specular lighting.
|
||||
#define GPUREG_LIGHT2_DIFFUSE 0x0162 ///< Light 2 diffuse lighting.
|
||||
#define GPUREG_LIGHT2_AMBIENT 0x0163 ///< Light 2 ambient lighting.
|
||||
#define GPUREG_LIGHT2_XY 0x0164 ///< Light 2 X and Y.
|
||||
#define GPUREG_LIGHT2_Z 0x0165 ///< Light 2 Z.
|
||||
#define GPUREG_LIGHT2_SPOTDIR_XY 0x0166 ///< Light 2 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT2_SPOTDIR_Z 0x0167 ///< Light 2 spotlight direction Z.
|
||||
#define GPUREG_0168 0x0168 ///< Unknown.
|
||||
#define GPUREG_LIGHT2_CONFIG 0x0169 ///< Light 2 configuration.
|
||||
#define GPUREG_LIGHT2_ATTENUATION_BIAS 0x016A ///< Light 2 attenuation bias.
|
||||
#define GPUREG_LIGHT2_ATTENUATION_SCALE 0x016B ///< Light 2 attenuation scale.
|
||||
#define GPUREG_016C 0x016C ///< Unknown.
|
||||
#define GPUREG_016D 0x016D ///< Unknown.
|
||||
#define GPUREG_016E 0x016E ///< Unknown.
|
||||
#define GPUREG_016F 0x016F ///< Unknown.
|
||||
#define GPUREG_LIGHT3_SPECULAR0 0x0170 ///< Light 3 specular lighting.
|
||||
#define GPUREG_LIGHT3_SPECULAR1 0x0171 ///< Light 3 specular lighting.
|
||||
#define GPUREG_LIGHT3_DIFFUSE 0x0172 ///< Light 3 diffuse lighting.
|
||||
#define GPUREG_LIGHT3_AMBIENT 0x0173 ///< Light 3 ambient lighting.
|
||||
#define GPUREG_LIGHT3_XY 0x0174 ///< Light 3 X and Y.
|
||||
#define GPUREG_LIGHT3_Z 0x0175 ///< Light 3 Z.
|
||||
#define GPUREG_LIGHT3_SPOTDIR_XY 0x0176 ///< Light 3 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT3_SPOTDIR_Z 0x0177 ///< Light 3 spotlight direction Z.
|
||||
#define GPUREG_0178 0x0178 ///< Unknown.
|
||||
#define GPUREG_LIGHT3_CONFIG 0x0179 ///< Light 3 configuration.
|
||||
#define GPUREG_LIGHT3_ATTENUATION_BIAS 0x017A ///< Light 3 attenuation bias.
|
||||
#define GPUREG_LIGHT3_ATTENUATION_SCALE 0x017B ///< Light 3 attenuation scale.
|
||||
#define GPUREG_017C 0x017C ///< Unknown.
|
||||
#define GPUREG_017D 0x017D ///< Unknown.
|
||||
#define GPUREG_017E 0x017E ///< Unknown.
|
||||
#define GPUREG_017F 0x017F ///< Unknown.
|
||||
#define GPUREG_LIGHT4_SPECULAR0 0x0180 ///< Light 4 specular lighting.
|
||||
#define GPUREG_LIGHT4_SPECULAR1 0x0181 ///< Light 4 specular lighting.
|
||||
#define GPUREG_LIGHT4_DIFFUSE 0x0182 ///< Light 4 diffuse lighting.
|
||||
#define GPUREG_LIGHT4_AMBIENT 0x0183 ///< Light 4 ambient lighting.
|
||||
#define GPUREG_LIGHT4_XY 0x0184 ///< Light 4 X and Y.
|
||||
#define GPUREG_LIGHT4_Z 0x0185 ///< Light 4 Z.
|
||||
#define GPUREG_LIGHT4_SPOTDIR_XY 0x0186 ///< Light 4 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT4_SPOTDIR_Z 0x0187 ///< Light 4 spotlight direction Z.
|
||||
#define GPUREG_0188 0x0188 ///< Unknown.
|
||||
#define GPUREG_LIGHT4_CONFIG 0x0189 ///< Light 4 configuration.
|
||||
#define GPUREG_LIGHT4_ATTENUATION_BIAS 0x018A ///< Light 4 attenuation bias.
|
||||
#define GPUREG_LIGHT4_ATTENUATION_SCALE 0x018B ///< Light 4 attenuation scale.
|
||||
#define GPUREG_018C 0x018C ///< Unknown.
|
||||
#define GPUREG_018D 0x018D ///< Unknown.
|
||||
#define GPUREG_018E 0x018E ///< Unknown.
|
||||
#define GPUREG_018F 0x018F ///< Unknown.
|
||||
#define GPUREG_LIGHT5_SPECULAR0 0x0190 ///< Light 5 specular lighting.
|
||||
#define GPUREG_LIGHT5_SPECULAR1 0x0191 ///< Light 5 specular lighting.
|
||||
#define GPUREG_LIGHT5_DIFFUSE 0x0192 ///< Light 5 diffuse lighting.
|
||||
#define GPUREG_LIGHT5_AMBIENT 0x0193 ///< Light 5 ambient lighting.
|
||||
#define GPUREG_LIGHT5_XY 0x0194 ///< Light 5 X and Y.
|
||||
#define GPUREG_LIGHT5_Z 0x0195 ///< Light 5 Z.
|
||||
#define GPUREG_LIGHT5_SPOTDIR_XY 0x0196 ///< Light 5 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT5_SPOTDIR_Z 0x0197 ///< Light 5 spotlight direction Z.
|
||||
#define GPUREG_0198 0x0198 ///< Unknown.
|
||||
#define GPUREG_LIGHT5_CONFIG 0x0199 ///< Light 5 configuration.
|
||||
#define GPUREG_LIGHT5_ATTENUATION_BIAS 0x019A ///< Light 5 attenuation bias.
|
||||
#define GPUREG_LIGHT5_ATTENUATION_SCALE 0x019B ///< Light 5 attenuation scale.
|
||||
#define GPUREG_019C 0x019C ///< Unknown.
|
||||
#define GPUREG_019D 0x019D ///< Unknown.
|
||||
#define GPUREG_019E 0x019E ///< Unknown.
|
||||
#define GPUREG_019F 0x019F ///< Unknown.
|
||||
#define GPUREG_LIGHT6_SPECULAR0 0x01A0 ///< Light 6 specular lighting.
|
||||
#define GPUREG_LIGHT6_SPECULAR1 0x01A1 ///< Light 6 specular lighting.
|
||||
#define GPUREG_LIGHT6_DIFFUSE 0x01A2 ///< Light 6 diffuse lighting.
|
||||
#define GPUREG_LIGHT6_AMBIENT 0x01A3 ///< Light 6 ambient lighting.
|
||||
#define GPUREG_LIGHT6_XY 0x01A4 ///< Light 6 X and Y.
|
||||
#define GPUREG_LIGHT6_Z 0x01A5 ///< Light 6 Z.
|
||||
#define GPUREG_LIGHT6_SPOTDIR_XY 0x01A6 ///< Light 6 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT6_SPOTDIR_Z 0x01A7 ///< Light 6 spotlight direction Z.
|
||||
#define GPUREG_01A8 0x01A8 ///< Unknown.
|
||||
#define GPUREG_LIGHT6_CONFIG 0x01A9 ///< Light 6 configuration.
|
||||
#define GPUREG_LIGHT6_ATTENUATION_BIAS 0x01AA ///< Light 6 attenuation bias.
|
||||
#define GPUREG_LIGHT6_ATTENUATION_SCALE 0x01AB ///< Light 6 attenuation scale.
|
||||
#define GPUREG_01AC 0x01AC ///< Unknown.
|
||||
#define GPUREG_01AD 0x01AD ///< Unknown.
|
||||
#define GPUREG_01AE 0x01AE ///< Unknown.
|
||||
#define GPUREG_01AF 0x01AF ///< Unknown.
|
||||
#define GPUREG_LIGHT7_SPECULAR0 0x01B0 ///< Light 7 specular lighting.
|
||||
#define GPUREG_LIGHT7_SPECULAR1 0x01B1 ///< Light 7 specular lighting.
|
||||
#define GPUREG_LIGHT7_DIFFUSE 0x01B2 ///< Light 7 diffuse lighting.
|
||||
#define GPUREG_LIGHT7_AMBIENT 0x01B3 ///< Light 7 ambient lighting.
|
||||
#define GPUREG_LIGHT7_XY 0x01B4 ///< Light 7 X and Y.
|
||||
#define GPUREG_LIGHT7_Z 0x01B5 ///< Light 7 Z.
|
||||
#define GPUREG_LIGHT7_SPOTDIR_XY 0x01B6 ///< Light 7 spotlight direction X and Y.
|
||||
#define GPUREG_LIGHT7_SPOTDIR_Z 0x01B7 ///< Light 7 spotlight direction Z.
|
||||
#define GPUREG_01B8 0x01B8 ///< Unknown.
|
||||
#define GPUREG_LIGHT7_CONFIG 0x01B9 ///< Light 7 configuration.
|
||||
#define GPUREG_LIGHT7_ATTENUATION_BIAS 0x01BA ///< Light 7 attenuation bias.
|
||||
#define GPUREG_LIGHT7_ATTENUATION_SCALE 0x01BB ///< Light 7 attenuation scale.
|
||||
#define GPUREG_01BC 0x01BC ///< Unknown.
|
||||
#define GPUREG_01BD 0x01BD ///< Unknown.
|
||||
#define GPUREG_01BE 0x01BE ///< Unknown.
|
||||
#define GPUREG_01BF 0x01BF ///< Unknown.
|
||||
#define GPUREG_LIGHTING_AMBIENT 0x01C0 ///< Ambient lighting.
|
||||
#define GPUREG_01C1 0x01C1 ///< Unknown.
|
||||
#define GPUREG_LIGHTING_NUM_LIGHTS 0x01C2 ///< Number of lights.
|
||||
#define GPUREG_LIGHTING_CONFIG0 0x01C3 ///< Lighting configuration.
|
||||
#define GPUREG_LIGHTING_CONFIG1 0x01C4 ///< Lighting configuration.
|
||||
#define GPUREG_LIGHTING_LUT_INDEX 0x01C5 ///< LUT index.
|
||||
#define GPUREG_LIGHTING_ENABLE1 0x01C6 ///< Lighting toggle.
|
||||
#define GPUREG_01C7 0x01C7 ///< Unknown.
|
||||
#define GPUREG_LIGHTING_LUT_DATA0 0x01C8 ///< LUT data 0.
|
||||
#define GPUREG_LIGHTING_LUT_DATA1 0x01C9 ///< LUT data 1.
|
||||
#define GPUREG_LIGHTING_LUT_DATA2 0x01CA ///< LUT data 2.
|
||||
#define GPUREG_LIGHTING_LUT_DATA3 0x01CB ///< LUT data 3.
|
||||
#define GPUREG_LIGHTING_LUT_DATA4 0x01CC ///< LUT data 4.
|
||||
#define GPUREG_LIGHTING_LUT_DATA5 0x01CD ///< LUT data 5.
|
||||
#define GPUREG_LIGHTING_LUT_DATA6 0x01CE ///< LUT data 6.
|
||||
#define GPUREG_LIGHTING_LUT_DATA7 0x01CF ///< LUT data 7.
|
||||
#define GPUREG_LIGHTING_LUTINPUT_ABS 0x01D0 ///< LUT input abs.
|
||||
#define GPUREG_LIGHTING_LUTINPUT_SELECT 0x01D1 ///< LUT input selector.
|
||||
#define GPUREG_LIGHTING_LUTINPUT_SCALE 0x01D2 ///< LUT input scale.
|
||||
#define GPUREG_01D3 0x01D3 ///< Unknown.
|
||||
#define GPUREG_01D4 0x01D4 ///< Unknown.
|
||||
#define GPUREG_01D5 0x01D5 ///< Unknown.
|
||||
#define GPUREG_01D6 0x01D6 ///< Unknown.
|
||||
#define GPUREG_01D7 0x01D7 ///< Unknown.
|
||||
#define GPUREG_01D8 0x01D8 ///< Unknown.
|
||||
#define GPUREG_LIGHTING_LIGHT_PERMUTATION 0x01D9 ///< Light permutation.
|
||||
#define GPUREG_01DA 0x01DA ///< Unknown.
|
||||
#define GPUREG_01DB 0x01DB ///< Unknown.
|
||||
#define GPUREG_01DC 0x01DC ///< Unknown.
|
||||
#define GPUREG_01DD 0x01DD ///< Unknown.
|
||||
#define GPUREG_01DE 0x01DE ///< Unknown.
|
||||
#define GPUREG_01DF 0x01DF ///< Unknown.
|
||||
#define GPUREG_01E0 0x01E0 ///< Unknown.
|
||||
#define GPUREG_01E1 0x01E1 ///< Unknown.
|
||||
#define GPUREG_01E2 0x01E2 ///< Unknown.
|
||||
#define GPUREG_01E3 0x01E3 ///< Unknown.
|
||||
#define GPUREG_01E4 0x01E4 ///< Unknown.
|
||||
#define GPUREG_01E5 0x01E5 ///< Unknown.
|
||||
#define GPUREG_01E6 0x01E6 ///< Unknown.
|
||||
#define GPUREG_01E7 0x01E7 ///< Unknown.
|
||||
#define GPUREG_01E8 0x01E8 ///< Unknown.
|
||||
#define GPUREG_01E9 0x01E9 ///< Unknown.
|
||||
#define GPUREG_01EA 0x01EA ///< Unknown.
|
||||
#define GPUREG_01EB 0x01EB ///< Unknown.
|
||||
#define GPUREG_01EC 0x01EC ///< Unknown.
|
||||
#define GPUREG_01ED 0x01ED ///< Unknown.
|
||||
#define GPUREG_01EE 0x01EE ///< Unknown.
|
||||
#define GPUREG_01EF 0x01EF ///< Unknown.
|
||||
#define GPUREG_01F0 0x01F0 ///< Unknown.
|
||||
#define GPUREG_01F1 0x01F1 ///< Unknown.
|
||||
#define GPUREG_01F2 0x01F2 ///< Unknown.
|
||||
#define GPUREG_01F3 0x01F3 ///< Unknown.
|
||||
#define GPUREG_01F4 0x01F4 ///< Unknown.
|
||||
#define GPUREG_01F5 0x01F5 ///< Unknown.
|
||||
#define GPUREG_01F6 0x01F6 ///< Unknown.
|
||||
#define GPUREG_01F7 0x01F7 ///< Unknown.
|
||||
#define GPUREG_01F8 0x01F8 ///< Unknown.
|
||||
#define GPUREG_01F9 0x01F9 ///< Unknown.
|
||||
#define GPUREG_01FA 0x01FA ///< Unknown.
|
||||
#define GPUREG_01FB 0x01FB ///< Unknown.
|
||||
#define GPUREG_01FC 0x01FC ///< Unknown.
|
||||
#define GPUREG_01FD 0x01FD ///< Unknown.
|
||||
#define GPUREG_01FE 0x01FE ///< Unknown.
|
||||
#define GPUREG_01FF 0x01FF ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Geometry pipeline registers (0x200-0x27F)
|
||||
///@{
|
||||
#define GPUREG_ATTRIBBUFFERS_LOC 0x0200 ///< Attribute buffers location.
|
||||
#define GPUREG_ATTRIBBUFFERS_FORMAT_LOW 0x0201 ///< Attribute buffers format low.
|
||||
#define GPUREG_ATTRIBBUFFERS_FORMAT_HIGH 0x0202 ///< Attribute buffers format high.
|
||||
#define GPUREG_ATTRIBBUFFER0_OFFSET 0x0203 ///< Attribute buffers 0 offset.
|
||||
#define GPUREG_ATTRIBBUFFER0_CONFIG1 0x0204 ///< Attribute buffers 0 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER0_CONFIG2 0x0205 ///< Attribute buffers 0 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER1_OFFSET 0x0206 ///< Attribute buffers 1 offset.
|
||||
#define GPUREG_ATTRIBBUFFER1_CONFIG1 0x0207 ///< Attribute buffers 1 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER1_CONFIG2 0x0208 ///< Attribute buffers 1 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER2_OFFSET 0x0209 ///< Attribute buffers 2 offset.
|
||||
#define GPUREG_ATTRIBBUFFER2_CONFIG1 0x020A ///< Attribute buffers 2 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER2_CONFIG2 0x020B ///< Attribute buffers 2 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER3_OFFSET 0x020C ///< Attribute buffers 3 offset.
|
||||
#define GPUREG_ATTRIBBUFFER3_CONFIG1 0x020D ///< Attribute buffers 3 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER3_CONFIG2 0x020E ///< Attribute buffers 3 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER4_OFFSET 0x020F ///< Attribute buffers 4 offset.
|
||||
#define GPUREG_ATTRIBBUFFER4_CONFIG1 0x0210 ///< Attribute buffers 4 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER4_CONFIG2 0x0211 ///< Attribute buffers 4 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER5_OFFSET 0x0212 ///< Attribute buffers 5 offset.
|
||||
#define GPUREG_ATTRIBBUFFER5_CONFIG1 0x0213 ///< Attribute buffers 5 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER5_CONFIG2 0x0214 ///< Attribute buffers 5 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER6_OFFSET 0x0215 ///< Attribute buffers 6 offset.
|
||||
#define GPUREG_ATTRIBBUFFER6_CONFIG1 0x0216 ///< Attribute buffers 6 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER6_CONFIG2 0x0217 ///< Attribute buffers 6 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER7_OFFSET 0x0218 ///< Attribute buffers 7 offset.
|
||||
#define GPUREG_ATTRIBBUFFER7_CONFIG1 0x0219 ///< Attribute buffers 7 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER7_CONFIG2 0x021A ///< Attribute buffers 7 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER8_OFFSET 0x021B ///< Attribute buffers 8 offset.
|
||||
#define GPUREG_ATTRIBBUFFER8_CONFIG1 0x021C ///< Attribute buffers 8 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER8_CONFIG2 0x021D ///< Attribute buffers 8 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER9_OFFSET 0x021E ///< Attribute buffers 9 offset.
|
||||
#define GPUREG_ATTRIBBUFFER9_CONFIG1 0x021F ///< Attribute buffers 9 configuration.
|
||||
#define GPUREG_ATTRIBBUFFER9_CONFIG2 0x0220 ///< Attribute buffers 9 configuration.
|
||||
#define GPUREG_ATTRIBBUFFERA_OFFSET 0x0221 ///< Attribute buffers A offset.
|
||||
#define GPUREG_ATTRIBBUFFERA_CONFIG1 0x0222 ///< Attribute buffers A configuration.
|
||||
#define GPUREG_ATTRIBBUFFERA_CONFIG2 0x0223 ///< Attribute buffers A configuration.
|
||||
#define GPUREG_ATTRIBBUFFERB_OFFSET 0x0224 ///< Attribute buffers B offset.
|
||||
#define GPUREG_ATTRIBBUFFERB_CONFIG1 0x0225 ///< Attribute buffers B configuration.
|
||||
#define GPUREG_ATTRIBBUFFERB_CONFIG2 0x0226 ///< Attribute buffers B configuration.
|
||||
#define GPUREG_INDEXBUFFER_CONFIG 0x0227 ///< Index buffer configuration.
|
||||
#define GPUREG_NUMVERTICES 0x0228 ///< Number of vertices.
|
||||
#define GPUREG_GEOSTAGE_CONFIG 0x0229 ///< Geometry stage configuration.
|
||||
#define GPUREG_VERTEX_OFFSET 0x022A ///< Vertex offset.
|
||||
#define GPUREG_022B 0x022B ///< Unknown.
|
||||
#define GPUREG_022C 0x022C ///< Unknown.
|
||||
#define GPUREG_POST_VERTEX_CACHE_NUM 0x022D ///< Unknown.
|
||||
#define GPUREG_DRAWARRAYS 0x022E ///< Draw arrays trigger.
|
||||
#define GPUREG_DRAWELEMENTS 0x022F ///< Draw arrays elements.
|
||||
#define GPUREG_0230 0x0230 ///< Unknown.
|
||||
#define GPUREG_VTX_FUNC 0x0231 ///< Unknown.
|
||||
#define GPUREG_FIXEDATTRIB_INDEX 0x0232 ///< Fixed attribute index.
|
||||
#define GPUREG_FIXEDATTRIB_DATA0 0x0233 ///< Fixed attribute data 0.
|
||||
#define GPUREG_FIXEDATTRIB_DATA1 0x0234 ///< Fixed attribute data 1.
|
||||
#define GPUREG_FIXEDATTRIB_DATA2 0x0235 ///< Fixed attribute data 2.
|
||||
#define GPUREG_0236 0x0236 ///< Unknown.
|
||||
#define GPUREG_0237 0x0237 ///< Unknown.
|
||||
#define GPUREG_CMDBUF_SIZE0 0x0238 ///< Command buffer size 0.
|
||||
#define GPUREG_CMDBUF_SIZE1 0x0239 ///< Command buffer size 1.
|
||||
#define GPUREG_CMDBUF_ADDR0 0x023A ///< Command buffer address 0.
|
||||
#define GPUREG_CMDBUF_ADDR1 0x023B ///< Command buffer address 1.
|
||||
#define GPUREG_CMDBUF_JUMP0 0x023C ///< Command buffer jump 0.
|
||||
#define GPUREG_CMDBUF_JUMP1 0x023D ///< Command buffer jump 1.
|
||||
#define GPUREG_023E 0x023E ///< Unknown.
|
||||
#define GPUREG_023F 0x023F ///< Unknown.
|
||||
#define GPUREG_0240 0x0240 ///< Unknown.
|
||||
#define GPUREG_0241 0x0241 ///< Unknown.
|
||||
#define GPUREG_VSH_NUM_ATTR 0x0242 ///< Unknown.
|
||||
#define GPUREG_0243 0x0243 ///< Unknown.
|
||||
#define GPUREG_VSH_COM_MODE 0x0244 ///< Unknown.
|
||||
#define GPUREG_START_DRAW_FUNC0 0x0245 ///< Unknown.
|
||||
#define GPUREG_0246 0x0246 ///< Unknown.
|
||||
#define GPUREG_0247 0x0247 ///< Unknown.
|
||||
#define GPUREG_0248 0x0248 ///< Unknown.
|
||||
#define GPUREG_0249 0x0249 ///< Unknown.
|
||||
#define GPUREG_VSH_OUTMAP_TOTAL1 0x024A ///< Unknown.
|
||||
#define GPUREG_024B 0x024B ///< Unknown.
|
||||
#define GPUREG_024C 0x024C ///< Unknown.
|
||||
#define GPUREG_024D 0x024D ///< Unknown.
|
||||
#define GPUREG_024E 0x024E ///< Unknown.
|
||||
#define GPUREG_024F 0x024F ///< Unknown.
|
||||
#define GPUREG_0250 0x0250 ///< Unknown.
|
||||
#define GPUREG_VSH_OUTMAP_TOTAL2 0x0251 ///< Unknown.
|
||||
#define GPUREG_GSH_MISC0 0x0252 ///< Unknown.
|
||||
#define GPUREG_GEOSTAGE_CONFIG2 0x0253 ///< Unknown.
|
||||
#define GPUREG_GSH_MISC1 0x0254 ///< Unknown.
|
||||
#define GPUREG_0255 0x0255 ///< Unknown.
|
||||
#define GPUREG_0256 0x0256 ///< Unknown.
|
||||
#define GPUREG_0257 0x0257 ///< Unknown.
|
||||
#define GPUREG_0258 0x0258 ///< Unknown.
|
||||
#define GPUREG_0259 0x0259 ///< Unknown.
|
||||
#define GPUREG_025A 0x025A ///< Unknown.
|
||||
#define GPUREG_025B 0x025B ///< Unknown.
|
||||
#define GPUREG_025C 0x025C ///< Unknown.
|
||||
#define GPUREG_025D 0x025D ///< Unknown.
|
||||
#define GPUREG_PRIMITIVE_CONFIG 0x025E ///< Primitive configuration.
|
||||
#define GPUREG_RESTART_PRIMITIVE 0x025F ///< Restart primitive flag.
|
||||
#define GPUREG_0260 0x0260 ///< Unknown.
|
||||
#define GPUREG_0261 0x0261 ///< Unknown.
|
||||
#define GPUREG_0262 0x0262 ///< Unknown.
|
||||
#define GPUREG_0263 0x0263 ///< Unknown.
|
||||
#define GPUREG_0264 0x0264 ///< Unknown.
|
||||
#define GPUREG_0265 0x0265 ///< Unknown.
|
||||
#define GPUREG_0266 0x0266 ///< Unknown.
|
||||
#define GPUREG_0267 0x0267 ///< Unknown.
|
||||
#define GPUREG_0268 0x0268 ///< Unknown.
|
||||
#define GPUREG_0269 0x0269 ///< Unknown.
|
||||
#define GPUREG_026A 0x026A ///< Unknown.
|
||||
#define GPUREG_026B 0x026B ///< Unknown.
|
||||
#define GPUREG_026C 0x026C ///< Unknown.
|
||||
#define GPUREG_026D 0x026D ///< Unknown.
|
||||
#define GPUREG_026E 0x026E ///< Unknown.
|
||||
#define GPUREG_026F 0x026F ///< Unknown.
|
||||
#define GPUREG_0270 0x0270 ///< Unknown.
|
||||
#define GPUREG_0271 0x0271 ///< Unknown.
|
||||
#define GPUREG_0272 0x0272 ///< Unknown.
|
||||
#define GPUREG_0273 0x0273 ///< Unknown.
|
||||
#define GPUREG_0274 0x0274 ///< Unknown.
|
||||
#define GPUREG_0275 0x0275 ///< Unknown.
|
||||
#define GPUREG_0276 0x0276 ///< Unknown.
|
||||
#define GPUREG_0277 0x0277 ///< Unknown.
|
||||
#define GPUREG_0278 0x0278 ///< Unknown.
|
||||
#define GPUREG_0279 0x0279 ///< Unknown.
|
||||
#define GPUREG_027A 0x027A ///< Unknown.
|
||||
#define GPUREG_027B 0x027B ///< Unknown.
|
||||
#define GPUREG_027C 0x027C ///< Unknown.
|
||||
#define GPUREG_027D 0x027D ///< Unknown.
|
||||
#define GPUREG_027E 0x027E ///< Unknown.
|
||||
#define GPUREG_027F 0x027F ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Geometry shader registers (0x280-0x2AF)
|
||||
///@{
|
||||
#define GPUREG_GSH_BOOLUNIFORM 0x0280 ///< Geometry shader bool uniforms.
|
||||
#define GPUREG_GSH_INTUNIFORM_I0 0x0281 ///< Geometry shader integer uniform 0.
|
||||
#define GPUREG_GSH_INTUNIFORM_I1 0x0282 ///< Geometry shader integer uniform 1.
|
||||
#define GPUREG_GSH_INTUNIFORM_I2 0x0283 ///< Geometry shader integer uniform 2.
|
||||
#define GPUREG_GSH_INTUNIFORM_I3 0x0284 ///< Geometry shader integer uniform 3.
|
||||
#define GPUREG_0285 0x0285 ///< Unknown.
|
||||
#define GPUREG_0286 0x0286 ///< Unknown.
|
||||
#define GPUREG_0287 0x0287 ///< Unknown.
|
||||
#define GPUREG_0288 0x0288 ///< Unknown.
|
||||
#define GPUREG_GSH_INPUTBUFFER_CONFIG 0x0289 ///< Geometry shader input buffer configuration.
|
||||
#define GPUREG_GSH_ENTRYPOINT 0x028A ///< Geometry shader entry point.
|
||||
#define GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW 0x028B ///< Geometry shader attribute permutations low.
|
||||
#define GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH 0x028C ///< Geometry shader attribute permutations high.
|
||||
#define GPUREG_GSH_OUTMAP_MASK 0x028D ///< Geometry shader output map mask.
|
||||
#define GPUREG_028E 0x028E ///< Unknown.
|
||||
#define GPUREG_GSH_CODETRANSFER_END 0x028F ///< Geometry shader code transfer end trigger.
|
||||
#define GPUREG_GSH_FLOATUNIFORM_CONFIG 0x0290 ///< Geometry shader float uniform configuration.
|
||||
#define GPUREG_GSH_FLOATUNIFORM_DATA 0x0291 ///< Geometry shader float uniform data.
|
||||
#define GPUREG_0299 0x0299 ///< Unknown.
|
||||
#define GPUREG_029A 0x029A ///< Unknown.
|
||||
#define GPUREG_GSH_CODETRANSFER_CONFIG 0x029B ///< Geometry shader code transfer configuration.
|
||||
#define GPUREG_GSH_CODETRANSFER_DATA 0x029C ///< Geometry shader code transfer data.
|
||||
#define GPUREG_02A4 0x02A4 ///< Unknown.
|
||||
#define GPUREG_GSH_OPDESCS_CONFIG 0x02A5 ///< Geometry shader operand description configuration.
|
||||
#define GPUREG_GSH_OPDESCS_DATA 0x02A6 ///< Geometry shader operand description data.
|
||||
#define GPUREG_02AE 0x02AE ///< Unknown.
|
||||
#define GPUREG_02AF 0x02AF ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Vertex shader registers (0x2B0-0x2DF)
|
||||
///@{
|
||||
#define GPUREG_VSH_BOOLUNIFORM 0x02B0 ///< Vertex shader bool uniforms.
|
||||
#define GPUREG_VSH_INTUNIFORM_I0 0x02B1 ///< Vertex shader integer uniform 0.
|
||||
#define GPUREG_VSH_INTUNIFORM_I1 0x02B2 ///< Vertex shader integer uniform 1.
|
||||
#define GPUREG_VSH_INTUNIFORM_I2 0x02B3 ///< Vertex shader integer uniform 2.
|
||||
#define GPUREG_VSH_INTUNIFORM_I3 0x02B4 ///< Vertex shader integer uniform 3.
|
||||
#define GPUREG_02B5 0x02B5 ///< Unknown.
|
||||
#define GPUREG_02B6 0x02B6 ///< Unknown.
|
||||
#define GPUREG_02B7 0x02B7 ///< Unknown.
|
||||
#define GPUREG_02B8 0x02B8 ///< Unknown.
|
||||
#define GPUREG_VSH_INPUTBUFFER_CONFIG 0x02B9 ///< Vertex shader input buffer configuration.
|
||||
#define GPUREG_VSH_ENTRYPOINT 0x02BA ///< Vertex shader entry point.
|
||||
#define GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW 0x02BB ///< Vertex shader attribute permutations low.
|
||||
#define GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH 0x02BC ///< Vertex shader attribute permutations high.
|
||||
#define GPUREG_VSH_OUTMAP_MASK 0x02BD ///< Vertex shader output map mask.
|
||||
#define GPUREG_02BE 0x02BE ///< Unknown.
|
||||
#define GPUREG_VSH_CODETRANSFER_END 0x02BF ///< Vertex shader code transfer end trigger.
|
||||
#define GPUREG_VSH_FLOATUNIFORM_CONFIG 0x02C0 ///< Vertex shader float uniform configuration.
|
||||
#define GPUREG_VSH_FLOATUNIFORM_DATA 0x02C1 ///< Vertex shader float uniform data.
|
||||
#define GPUREG_02C9 0x02C9 ///< Unknown.
|
||||
#define GPUREG_02CA 0x02CA ///< Unknown.
|
||||
#define GPUREG_VSH_CODETRANSFER_CONFIG 0x02CB ///< Vertex shader code transfer configuration.
|
||||
#define GPUREG_VSH_CODETRANSFER_DATA 0x02CC ///< Vertex shader code transfer data.
|
||||
#define GPUREG_02D4 0x02D4 ///< Unknown.
|
||||
#define GPUREG_VSH_OPDESCS_CONFIG 0x02D5 ///< Vertex shader operand description configuration.
|
||||
#define GPUREG_VSH_OPDESCS_DATA 0x02D6 ///< Vertex shader operand description data.
|
||||
#define GPUREG_02DE 0x02DE ///< Unknown.
|
||||
#define GPUREG_02DF 0x02DF ///< Unknown.
|
||||
///@}
|
||||
|
||||
///@name Unknown registers (0x2E0-0x2FF)
|
||||
///@{
|
||||
#define GPUREG_02E0 0x02E0 ///< Unknown.
|
||||
#define GPUREG_02E1 0x02E1 ///< Unknown.
|
||||
#define GPUREG_02E2 0x02E2 ///< Unknown.
|
||||
#define GPUREG_02E3 0x02E3 ///< Unknown.
|
||||
#define GPUREG_02E4 0x02E4 ///< Unknown.
|
||||
#define GPUREG_02E5 0x02E5 ///< Unknown.
|
||||
#define GPUREG_02E6 0x02E6 ///< Unknown.
|
||||
#define GPUREG_02E7 0x02E7 ///< Unknown.
|
||||
#define GPUREG_02E8 0x02E8 ///< Unknown.
|
||||
#define GPUREG_02E9 0x02E9 ///< Unknown.
|
||||
#define GPUREG_02EA 0x02EA ///< Unknown.
|
||||
#define GPUREG_02EB 0x02EB ///< Unknown.
|
||||
#define GPUREG_02EC 0x02EC ///< Unknown.
|
||||
#define GPUREG_02ED 0x02ED ///< Unknown.
|
||||
#define GPUREG_02EE 0x02EE ///< Unknown.
|
||||
#define GPUREG_02EF 0x02EF ///< Unknown.
|
||||
#define GPUREG_02F0 0x02F0 ///< Unknown.
|
||||
#define GPUREG_02F1 0x02F1 ///< Unknown.
|
||||
#define GPUREG_02F2 0x02F2 ///< Unknown.
|
||||
#define GPUREG_02F3 0x02F3 ///< Unknown.
|
||||
#define GPUREG_02F4 0x02F4 ///< Unknown.
|
||||
#define GPUREG_02F5 0x02F5 ///< Unknown.
|
||||
#define GPUREG_02F6 0x02F6 ///< Unknown.
|
||||
#define GPUREG_02F7 0x02F7 ///< Unknown.
|
||||
#define GPUREG_02F8 0x02F8 ///< Unknown.
|
||||
#define GPUREG_02F9 0x02F9 ///< Unknown.
|
||||
#define GPUREG_02FA 0x02FA ///< Unknown.
|
||||
#define GPUREG_02FB 0x02FB ///< Unknown.
|
||||
#define GPUREG_02FC 0x02FC ///< Unknown.
|
||||
#define GPUREG_02FD 0x02FD ///< Unknown.
|
||||
#define GPUREG_02FE 0x02FE ///< Unknown.
|
||||
#define GPUREG_02FF 0x02FF ///< Unknown.
|
||||
///@}
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
|
||||
#define GX_REGS_BASE (IO_MEM_ARM11_ONLY + 0x200000)
|
||||
#define REG_GX_GPU_CLK *((vu32*)(GX_REGS_BASE + 0x0004)) // ?
|
||||
|
||||
// PSC (memory fill) regs.
|
||||
#define REG_GX_PSC_FILL0_S_ADDR *((vu32*)(GX_REGS_BASE + 0x0010)) // Start address
|
||||
#define REG_GX_PSC_FILL0_E_ADDR *((vu32*)(GX_REGS_BASE + 0x0014)) // End address
|
||||
#define REG_GX_PSC_FILL0_VAL *((vu32*)(GX_REGS_BASE + 0x0018)) // Fill value
|
||||
#define REG_GX_PSC_FILL0_CNT *((vu32*)(GX_REGS_BASE + 0x001C))
|
||||
|
||||
#define REG_GX_PSC_FILL1_S_ADDR *((vu32*)(GX_REGS_BASE + 0x0020))
|
||||
#define REG_GX_PSC_FILL1_E_ADDR *((vu32*)(GX_REGS_BASE + 0x0024))
|
||||
#define REG_GX_PSC_FILL1_VAL *((vu32*)(GX_REGS_BASE + 0x0028))
|
||||
#define REG_GX_PSC_FILL1_CNT *((vu32*)(GX_REGS_BASE + 0x002C))
|
||||
|
||||
#define REG_GX_PSC_VRAM *((vu32*)(GX_REGS_BASE + 0x0030)) // gsp mudule only changes bit 8-11.
|
||||
#define REG_GX_PSC_STAT *((vu32*)(GX_REGS_BASE + 0x0034))
|
||||
|
||||
// PDC0/1 regs see lcd.h.
|
||||
|
||||
// PPF (transfer engine) regs.
|
||||
#define REG_GX_PPF_IN_ADDR *((vu32*)(GX_REGS_BASE + 0x0C00))
|
||||
#define REG_GX_PPF_OUT_ADDR *((vu32*)(GX_REGS_BASE + 0x0C04))
|
||||
#define REG_GX_PPF_DT_OUTDIM *((vu32*)(GX_REGS_BASE + 0x0C08)) // Display transfer output dimensions.
|
||||
#define REG_GX_PPF_DT_INDIM *((vu32*)(GX_REGS_BASE + 0x0C0C)) // Display transfer input dimensions.
|
||||
#define REG_GX_PPF_FlAGS *((vu32*)(GX_REGS_BASE + 0x0C10))
|
||||
#define REG_GX_PPF_UNK14 *((vu32*)(GX_REGS_BASE + 0x0C14)) // Transfer interval?
|
||||
#define REG_GX_PPF_CNT *((vu32*)(GX_REGS_BASE + 0x0C18))
|
||||
#define REG_GX_PPF_IRQ_POS *((vu32*)(GX_REGS_BASE + 0x0C1C)) // ?
|
||||
#define REG_GX_PPF_LEN *((vu32*)(GX_REGS_BASE + 0x0C20)) // Texture copy size in bytes.
|
||||
#define REG_GX_PPF_TC_INDIM *((vu32*)(GX_REGS_BASE + 0x0C24)) // Texture copy input width and gap in 16 byte units.
|
||||
#define REG_GX_PPF_TC_OUTDIM *((vu32*)(GX_REGS_BASE + 0x0C28)) // Texture copy output width and gap in 16 byte units.
|
||||
|
||||
// P3D (GPU internal) regs. See gpu_regs.h.
|
||||
#define REG_GX_P3D(reg) *((vu32*)(GX_REGS_BASE + 0x1000 + ((reg) * 4)))
|
|
@ -0,0 +1,81 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2018 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// HASH //
|
||||
//////////////////////////////////
|
||||
|
||||
#define HASH_ENABLE (1u) // Also used as busy flag
|
||||
#define HASH_FINAL_ROUND (1u<<1)
|
||||
#define HASH_IN_DMA_ENABLE (1u<<2) // Without this NDMA startup is never fires
|
||||
#define HASH_INPUT_BIG (1u<<3)
|
||||
#define HASH_INPUT_LITTLE (0u)
|
||||
#define HASH_OUTPUT_BIG (HASH_INPUT_BIG)
|
||||
#define HASH_OUTPUT_LITTLE (HASH_INPUT_LITTLE)
|
||||
#define HASH_MODE_256 (0u)
|
||||
#define HASH_MODE_224 (1u<<4)
|
||||
#define HASH_MODE_1 (2u<<4)
|
||||
#define HASH_MODE_MASK (HASH_MODE_1 | HASH_MODE_224 | HASH_MODE_256)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets input mode, endianess and starts the hash operation.
|
||||
*
|
||||
* @param[in] params Mode and input endianess bitmask.
|
||||
*/
|
||||
void HASH_start(u8 params);
|
||||
|
||||
/**
|
||||
* @brief Hashes the data pointed to.
|
||||
*
|
||||
* @param[in] data Pointer to data to hash.
|
||||
* @param[in] size Size of the data to hash.
|
||||
*/
|
||||
void HASH_update(const u32 *data, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Generates the final hash.
|
||||
*
|
||||
* @param hash Pointer to memory to copy the hash to.
|
||||
* @param[in] endianess Endianess bitmask for the hash.
|
||||
*/
|
||||
void HASH_finish(u32 *const hash, u8 endianess);
|
||||
|
||||
/**
|
||||
* @brief Returns the current HASH engine state.
|
||||
*
|
||||
* @param out Pointer to memory to copy the state to.
|
||||
*/
|
||||
void HASH_getState(u32 *const out);
|
||||
|
||||
/**
|
||||
* @brief Hashes a single block of data and outputs the hash.
|
||||
*
|
||||
* @param[in] data Pointer to data to hash.
|
||||
* @param[in] size Size of the data to hash.
|
||||
* @param hash Pointer to memory to copy the hash to.
|
||||
* @param[in] params Mode and input endianess bitmask.
|
||||
* @param[in] hashEndianess Endianess bitmask for the hash.
|
||||
*/
|
||||
void hash(const u32 *data, u32 size, u32 *const hash, u8 params, u8 hashEndianess);
|
|
@ -0,0 +1,105 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on code from https://github.com/smealum/ctrulib
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#define HID_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x46000)
|
||||
#define REG_HID_PAD (*((vu16*)(HID_REGS_BASE + 0x0)) ^ 0xFFFFu)
|
||||
#define REG_HID_PADCNT *((vu16*)(HID_REGS_BASE + 0x2))
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
KEY_A = 1u<<0, // A
|
||||
KEY_B = 1u<<1, // B
|
||||
KEY_SELECT = 1u<<2, // Select
|
||||
KEY_START = 1u<<3, // Start
|
||||
KEY_DRIGHT = 1u<<4, // D-Pad Right
|
||||
KEY_DLEFT = 1u<<5, // D-Pad Left
|
||||
KEY_DUP = 1u<<6, // D-Pad Up
|
||||
KEY_DDOWN = 1u<<7, // D-Pad Down
|
||||
KEY_R = 1u<<8, // R
|
||||
KEY_L = 1u<<9, // L
|
||||
KEY_X = 1u<<10, // X
|
||||
KEY_Y = 1u<<11, // Y
|
||||
KEY_ZL = 1u<<14, // ZL (New 3DS only)
|
||||
KEY_ZR = 1u<<15, // ZR (New 3DS only)
|
||||
KEY_TOUCH = 1u<<20, // Touch (Not actually provided by HID)
|
||||
KEY_CSTICK_RIGHT = 1u<<24, // C-Stick Right (New 3DS only)
|
||||
KEY_CSTICK_LEFT = 1u<<25, // C-Stick Left (New 3DS only)
|
||||
KEY_CSTICK_UP = 1u<<26, // C-Stick Up (New 3DS only)
|
||||
KEY_CSTICK_DOWN = 1u<<27, // C-Stick Down (New 3DS only)
|
||||
KEY_CPAD_RIGHT = 1u<<28, // Circle Pad Right
|
||||
KEY_CPAD_LEFT = 1u<<29, // Circle Pad Left
|
||||
KEY_CPAD_UP = 1u<<30, // Circle Pad Up
|
||||
KEY_CPAD_DOWN = 1u<<31, // Circle Pad Down
|
||||
|
||||
// Generic catch-all directions
|
||||
KEY_UP = KEY_DUP | KEY_CPAD_UP, // D-Pad Up or Circle Pad Up
|
||||
KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN, // D-Pad Down or Circle Pad Down
|
||||
KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT, // D-Pad Left or Circle Pad Left
|
||||
KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT, // D-Pad Right or Circle Pad Right
|
||||
|
||||
// Masks
|
||||
KEY_DPAD_MASK = KEY_DDOWN | KEY_DUP | KEY_DLEFT | KEY_DRIGHT,
|
||||
KEY_CSTICK_MASK = KEY_CSTICK_DOWN | KEY_CSTICK_UP | KEY_CSTICK_LEFT | KEY_CSTICK_RIGHT,
|
||||
KEY_CPAD_MASK = KEY_CPAD_DOWN | KEY_CPAD_UP | KEY_CPAD_LEFT | KEY_CPAD_RIGHT
|
||||
};
|
||||
|
||||
// Extra keys use with hidGetExtraKeys()
|
||||
enum
|
||||
{
|
||||
KEY_POWER = 1u<<0,
|
||||
KEY_POWER_HELD = 1u<<1,
|
||||
KEY_HOME = 1u<<2, // Auto clears on release
|
||||
KEY_WIFI = 1u<<3,
|
||||
KEY_SHELL = 1u<<4, // Auto clears on open
|
||||
KEY_BAT_CHARGING = 1u<<5, // Auto clears when charging stops
|
||||
KEY_VOL_SLIDER = 1u<<6
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 x;
|
||||
u16 y;
|
||||
} TouchPos;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s16 x;
|
||||
s16 y;
|
||||
} CpadPos;
|
||||
|
||||
|
||||
|
||||
void hidInit(void);
|
||||
void hidScanInput(void);
|
||||
u32 hidKeysHeld(void);
|
||||
u32 hidKeysDown(void);
|
||||
u32 hidKeysUp(void);
|
||||
const TouchPos* hidGetTouchPosPtr(void);
|
||||
const CpadPos* hidGetCpadPosPtr(void);
|
||||
u32 hidGetExtraKeys(u32 clearMask);
|
|
@ -0,0 +1,145 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define I2C1_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x61000)
|
||||
#define REG_I2C1_DATA *((vu8* )(I2C1_REGS_BASE + 0x0))
|
||||
#define REG_I2C1_CNT *((vu8* )(I2C1_REGS_BASE + 0x1))
|
||||
#define REG_I2C1_CNTEX *((vu16*)(I2C1_REGS_BASE + 0x2))
|
||||
#define REG_I2C1_SCL *((vu16*)(I2C1_REGS_BASE + 0x4))
|
||||
|
||||
#define I2C2_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x44000)
|
||||
#define REG_I2C2_DATA *((vu8* )(I2C2_REGS_BASE + 0x0))
|
||||
#define REG_I2C2_CNT *((vu8* )(I2C2_REGS_BASE + 0x1))
|
||||
#define REG_I2C2_CNTEX *((vu16*)(I2C2_REGS_BASE + 0x2))
|
||||
#define REG_I2C2_SCL *((vu16*)(I2C2_REGS_BASE + 0x4))
|
||||
|
||||
#define I2C3_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x48000)
|
||||
#define REG_I2C3_DATA *((vu8* )(I2C3_REGS_BASE + 0x0))
|
||||
#define REG_I2C3_CNT *((vu8* )(I2C3_REGS_BASE + 0x1))
|
||||
#define REG_I2C3_CNTEX *((vu16*)(I2C3_REGS_BASE + 0x2))
|
||||
#define REG_I2C3_SCL *((vu16*)(I2C3_REGS_BASE + 0x4))
|
||||
|
||||
|
||||
// REG_I2C_CNT
|
||||
#define I2C_STOP (1u)
|
||||
#define I2C_START (1u<<1)
|
||||
#define I2C_ERROR (1u<<2)
|
||||
#define I2C_ACK (1u<<4)
|
||||
#define I2C_DIR_WRITE (0u)
|
||||
#define I2C_DIR_READ (1u<<5)
|
||||
#define I2C_IRQ_ENABLE (1u<<6)
|
||||
#define I2C_ENABLE (1u<<7)
|
||||
|
||||
// REG_I2C_CNTEX
|
||||
#define I2C_SCL_STATE (1u) // Read-only SCL line state?
|
||||
#define I2C_CLK_STRETCH (1u<<1) // Enables clock stretching
|
||||
#define I2C_UNK_CNTEX15 (1u<<15) // "LGCY" Legacy related?
|
||||
|
||||
// REG_I2C_SCL
|
||||
#define I2C_DELAYS(high, low) ((high)<<8 | (low)) // "PRD" TODO: How long and when does it delay?
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
I2C_DEV_TWL_MCU = 0u, // DSi mode MCU
|
||||
I2C_DEV_CAMERA1 = 1u, // Internal self-facing camera
|
||||
I2C_DEV_CAMERA2 = 2u, // External right camera
|
||||
I2C_DEV_CTR_MCU = 3u,
|
||||
I2C_DEV_CAMERA3 = 4u, // External left camera
|
||||
I2C_DEV_LCD0 = 5u, // Upper LCD
|
||||
I2C_DEV_LCD1 = 6u, // Lower LCD
|
||||
I2C_DEV_UNK7 = 7u, // Debug?
|
||||
I2C_DEV_UNK8 = 8u, // Debug?
|
||||
I2C_DEV_UNK9 = 9u, // HID debug?
|
||||
I2C_DEV_GYRO_OLD = 10u, // Old 3DS only?
|
||||
I2C_DEV_GYRO_NEW = 11u, // New 3DS only?
|
||||
I2C_DEV_UNK12 = 12u, // HID "DebugPad"?
|
||||
I2C_DEV_IR = 13u, // Infrared (IrDA)
|
||||
I2C_DEV_EEPROM = 14u, // Dev unit only?
|
||||
I2C_DEV_NFC = 15u,
|
||||
I2C_DEV_QTM = 16u, // IO expander chip (New 3DS only)
|
||||
I2C_DEV_N3DS_HID = 17u // C-Stick and ZL/ZR buttons
|
||||
} I2cDevice;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the I2C buses. Call this only once.
|
||||
*/
|
||||
void I2C_init(void);
|
||||
|
||||
/**
|
||||
* @brief Reads data from a I2C register to a buffer.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param out The output buffer pointer.
|
||||
* @param[in] size The read size.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Writes a buffer to a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param[in] in The input buffer pointer.
|
||||
* @param[in] size The write size.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Reads a byte from a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
*
|
||||
* @return Returns the value read on success otherwise 0xFF.
|
||||
*/
|
||||
u8 I2C_readReg(I2cDevice devId, u8 regAddr);
|
||||
|
||||
/**
|
||||
* @brief Writes a byte to a I2C register.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param[in] data The data to write.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);
|
||||
|
||||
/**
|
||||
* @brief Writes a byte to a I2C register without interrupts.
|
||||
*
|
||||
* @param[in] devId The device ID. Use the enum above.
|
||||
* @param[in] regAddr The register address.
|
||||
* @param[in] data The data to write.
|
||||
*
|
||||
* @return Returns true on success and false on failure.
|
||||
*/
|
||||
bool I2C_writeRegIntSafe(I2cDevice devId, u8 regAddr, u8 data);
|
|
@ -0,0 +1,236 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
#include "arm.h"
|
||||
|
||||
|
||||
// Most register names from: https://github.com/torvalds/linux/blob/master/include/linux/irqchip/arm-gic.h
|
||||
#define GIC_CPU_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x100)
|
||||
#define REG_GIC_CPU_CTRL *(( vu32*)(GIC_CPU_REGS_BASE + 0x00)) // Control Register.
|
||||
#define REG_GIC_CPU_PRIMASK *(( vu32*)(GIC_CPU_REGS_BASE + 0x04)) // Priority Mask Register.
|
||||
#define REG_GIC_CPU_BINPOINT *(( vu32*)(GIC_CPU_REGS_BASE + 0x08)) // Binary Point Register.
|
||||
#define REG_GIC_CPU_INTACK *((const vu32*)(GIC_CPU_REGS_BASE + 0x0C)) // Interrupt Acknowledge Register.
|
||||
#define REG_GIC_CPU_EOI *(( vu32*)(GIC_CPU_REGS_BASE + 0x10)) // End of Interrupt Register.
|
||||
#define REG_GIC_CPU_RUNNINGPRI *((const vu32*)(GIC_CPU_REGS_BASE + 0x14)) // Running Priority Register.
|
||||
#define REG_GIC_CPU_HIGHPRI *((const vu32*)(GIC_CPU_REGS_BASE + 0x18)) // Highest Pending Interrupt Register.
|
||||
|
||||
#define GIC_DIST_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x1000)
|
||||
#define REG_GIC_DIST_CTRL *(( vu32*)(GIC_DIST_REGS_BASE + 0x000)) // Interrupt Distributor Control Register.
|
||||
#define REG_GIC_DIST_CTR *((const vu32*)(GIC_DIST_REGS_BASE + 0x004)) // Interrupt Controller Type Register.
|
||||
#define REGs_GIC_DIST_ENABLE_SET (( vu32*)(GIC_DIST_REGS_BASE + 0x100)) // Interrupt Enable set Registers.
|
||||
#define REGs_GIC_DIST_ENABLE_CLEAR (( vu32*)(GIC_DIST_REGS_BASE + 0x180)) // Interrupt Enable clear Registers.
|
||||
#define REGs_GIC_DIST_PENDING_SET (( vu32*)(GIC_DIST_REGS_BASE + 0x200)) // Interrupt Pending set Registers.
|
||||
#define REGs_GIC_DIST_PENDING_CLEAR (( vu32*)(GIC_DIST_REGS_BASE + 0x280)) // Interrupt Pending clear Registers.
|
||||
#define REGs_GIC_DIST_ACTIVE_SET ((const vu32*)(GIC_DIST_REGS_BASE + 0x300)) // Interrupt Active Bit Registers.
|
||||
#define REGs_GIC_DIST_PRI (( vu32*)(GIC_DIST_REGS_BASE + 0x400)) // Interrupt Priority Registers.
|
||||
#define REGs_GIC_DIST_TARGET (( vu32*)(GIC_DIST_REGS_BASE + 0x800)) // Interrupt CPU targets Registers.
|
||||
#define REGs_GIC_DIST_CONFIG (( vu32*)(GIC_DIST_REGS_BASE + 0xC00)) // Interrupt Configuration Registers.
|
||||
#define REGs_GIC_DIST_LINE_LEVEL ((const vu32*)(GIC_DIST_REGS_BASE + 0xD00)) // Interrupt Line Level Registers.
|
||||
#define REG_GIC_DIST_SOFTINT *(( vu32*)(GIC_DIST_REGS_BASE + 0xF00)) // Software Interrupt Register.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT0 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE0)) // Periphal Identification Register 0.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT1 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE4)) // Periphal Identification Register 1.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT2 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFE8)) // Periphal Identification Register 2.
|
||||
#define REG_GIC_DIST_PERIPH_IDENT3 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFEC)) // Periphal Identification Register 3.
|
||||
#define REG_GIC_DIST_PRIMECELL0 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF0)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL1 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF4)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL2 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFF8)) // PrimeCell Identification Register 0.
|
||||
#define REG_GIC_DIST_PRIMECELL3 *((const vu32*)(GIC_DIST_REGS_BASE + 0xFFC)) // PrimeCell Identification Register 0.
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IRQ_IPI0 = 0u,
|
||||
IRQ_IPI1 = 1u,
|
||||
IRQ_IPI2 = 2u,
|
||||
IRQ_IPI3 = 3u,
|
||||
IRQ_IPI4 = 4u,
|
||||
IRQ_IPI5 = 5u,
|
||||
IRQ_IPI6 = 6u,
|
||||
IRQ_IPI7 = 7u,
|
||||
IRQ_IPI8 = 8u,
|
||||
IRQ_IPI9 = 9u,
|
||||
IRQ_IPI10 = 10u,
|
||||
IRQ_IPI11 = 11u,
|
||||
IRQ_IPI12 = 12u,
|
||||
IRQ_IPI13 = 13u,
|
||||
IRQ_IPI14 = 14u,
|
||||
IRQ_IPI15 = 15u,
|
||||
IRQ_TIMER = 29u, // MPCore timer.
|
||||
IRQ_WATCHDOG = 30u, // MPCore watchdog.
|
||||
IRQ_SPI2 = 36u, // SPI bus 2 interrupt status update.
|
||||
IRQ_UART = 37u, // New3DS-only UART?
|
||||
IRQ_PSC0 = 40u,
|
||||
IRQ_PSC1 = 41u,
|
||||
IRQ_PDC0 = 42u, // PDC0 topscreen H-/VBlank and errors.
|
||||
IRQ_PDC1 = 43u, // PDC1 bottom screen H-/VBlank and errors.
|
||||
IRQ_PPF = 44u,
|
||||
IRQ_P3D = 45u,
|
||||
IRQ_CDMA_EVENT0 = 48u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT1 = 49u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT2 = 50u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT3 = 51u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT4 = 52u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT5 = 53u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT6 = 54u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT7 = 55u, // Old3DS CDMA.
|
||||
IRQ_CDMA_EVENT8 = 56u, // Old3DS CDMA.
|
||||
IRQ_CDMA_FAULT = 57u, // Old3DS CDMA.
|
||||
IRQ_CDMA2_EVENT = 58u, // New3DS-only CDMA event 0-31.
|
||||
IRQ_CDMA2_FAULT = 59u, // New3DS-only CDMA.
|
||||
IRQ_SDIO2 = 64u, // SDIO2 controller (WiFi).
|
||||
IRQ_SDIO2_IRQ = 65u, // SDIO2 IRQ pin (WiFi).
|
||||
IRQ_SDIO3 = 66u, // SDIO3 controller.
|
||||
IRQ_SDIO3_IRQ = 67u, // SDIO3 IRQ pin.
|
||||
IRQ_NTRCARD = 68u, // NTRCARD controller.
|
||||
IRQ_L2B1 = 69u, // New3DS-only first L2B converter.
|
||||
IRQ_L2B2 = 70u, // New3DS-only second L2B converter.
|
||||
IRQ_CAM1 = 72u, // Camera 1 (DSi).
|
||||
IRQ_CAM2 = 73u, // Camera 2 (left eye).
|
||||
IRQ_DSP = 74u,
|
||||
IRQ_Y2R1 = 75u,
|
||||
IRQ_LGYFB_BOT = 76u, // Legacy framebuffer bottom screen.
|
||||
IRQ_LGYFB_TOP = 77u, // Legacy framebuffer top screen.
|
||||
IRQ_Y2R2 = 78u, // New3DS-only.
|
||||
IRQ_G1 = 79u, // New3DS-only Hantro G1 decoder.
|
||||
IRQ_PXI_SYNC = 80u,
|
||||
IRQ_PXI_SYNC2 = 81u,
|
||||
IRQ_PXI_NOT_FULL = 82u,
|
||||
IRQ_PXI_NOT_EMPTY = 83u,
|
||||
IRQ_I2C1 = 84u,
|
||||
IRQ_I2C2 = 85u,
|
||||
IRQ_SPI3 = 86u, // SPI bus 3 interrupt status update.
|
||||
IRQ_SPI1 = 87u, // SPI bus 1 interrupt status update.
|
||||
IRQ_PDN = 88u,
|
||||
IRQ_LGY_SLEEP = 89u, // Triggers if legacy mode enters sleep.
|
||||
IRQ_MIC = 90u,
|
||||
IRQ_HID_PADCNT = 91u,
|
||||
IRQ_I2C3 = 92u,
|
||||
IRQ_DS_WIFI = 95u,
|
||||
IRQ_GPIO_1_2_HIGH = 96u,
|
||||
IRQ_GPIO_1_2_LOW = 98u,
|
||||
IRQ_GPIO_1_1 = 99u,
|
||||
IRQ_GPIO_2_0 = 100u,
|
||||
IRQ_GPIO_2_2 = 102u,
|
||||
IRQ_GPIO_3_0 = 104u,
|
||||
IRQ_GPIO_3_1 = 105u,
|
||||
IRQ_GPIO_3_2 = 106u,
|
||||
IRQ_GPIO_3_3 = 107u,
|
||||
IRQ_GPIO_3_4 = 108u,
|
||||
IRQ_GPIO_3_5 = 109u,
|
||||
IRQ_GPIO_3_6 = 110u,
|
||||
IRQ_GPIO_3_7 = 111u,
|
||||
IRQ_GPIO_3_8 = 112u,
|
||||
IRQ_GPIO_3_9 = 113u,
|
||||
IRQ_GPIO_3_10 = 114u,
|
||||
IRQ_GPIO_3_11 = 115u,
|
||||
IRQ_GAMECARD_OFF = 116u, // Gamecard poweroff.
|
||||
IRQ_GAMECARD_INS = 117u, // Gamecard inserted.
|
||||
IRQ_L2C = 118u, // New3DS-only L2C-310 Level 2 Cache Controller.
|
||||
IRQ_UNK119 = 119u,
|
||||
IRQ_PERF_MONITOR0 = 120u, // Core 0 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR1 = 121u, // Core 1 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR2 = 122u, // Unconfirmed. Core 2 performance monitor. Triggers on any counter overflow.
|
||||
IRQ_PERF_MONITOR3 = 123u, // Unconfirmed. Core 3 performance monitor. Triggers on any counter overflow.
|
||||
|
||||
// Aliases
|
||||
IRQ_SHELL_OPENED = IRQ_GPIO_1_2_HIGH,
|
||||
IRQ_SHELL_CLOSED = IRQ_GPIO_1_2_LOW, // Triggers on GPIO_1_2 low.
|
||||
IRQ_TOUCHSCREEN = IRQ_GPIO_1_1, // Triggers on touchscreen pen down.
|
||||
IRQ_HEADPH_JACK = IRQ_GPIO_2_0, // Headphone jack. Triggers on both plugging in and out?
|
||||
IRQ_CTR_MCU = IRQ_GPIO_3_9 // Various MCU events trigger this. See MCU interrupt mask.
|
||||
} Interrupt;
|
||||
|
||||
|
||||
// IRQ interrupt service routine type.
|
||||
// intSource: bit 10-12 CPU source ID (0 except for interrupt ID 0-15),
|
||||
// bit 0-9 interrupt ID
|
||||
typedef void (*IrqIsr)(u32 intSource);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the generic interrupt controller.
|
||||
*/
|
||||
void IRQ_init(void);
|
||||
|
||||
/**
|
||||
* @brief Registers a interrupt service routine and enables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
* @param[in] prio The priority. 0 = highest, 14 = lowest, 15 = disabled.
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core.
|
||||
* 0 means current CPU.
|
||||
* @param[in] isr The interrupt service routine to call.
|
||||
*/
|
||||
void IRQ_registerIsr(Interrupt id, u8 prio, u8 cpuMask, IrqIsr isr);
|
||||
|
||||
/**
|
||||
* @brief Reenables a previously disabled but registered interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
*/
|
||||
void IRQ_enable(Interrupt id);
|
||||
|
||||
/**
|
||||
* @brief Disables a previously registered interrupt temporarily.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
*/
|
||||
void IRQ_disable(Interrupt id);
|
||||
|
||||
/**
|
||||
* @brief Triggers a software interrupt for the specified CPUs.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <16.
|
||||
* @param[in] cpuMask The CPU mask. Each of the 4 bits stands for 1 core.
|
||||
*/
|
||||
void IRQ_softwareInterrupt(Interrupt id, u8 cpuMask);
|
||||
|
||||
/**
|
||||
* @brief Sets the priority of an interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
* @param[in] prio The priority. 0 = highest, 14 = lowest, 15 = disabled
|
||||
*/
|
||||
void IRQ_setPriority(Interrupt id, u8 prio);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the interrupt service routine and disables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <128.
|
||||
*/
|
||||
void IRQ_unregisterIsr(Interrupt id);
|
||||
|
||||
|
||||
#if !__thumb__
|
||||
static inline u32 enterCriticalSection(void)
|
||||
{
|
||||
const u32 tmp = __getCpsr();
|
||||
__cpsid(i);
|
||||
return tmp & PSR_I;
|
||||
}
|
||||
|
||||
static inline void leaveCriticalSection(u32 oldState)
|
||||
{
|
||||
__setCpsr_c((__getCpsr() & ~PSR_I) | oldState);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,133 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
#include "arm11/hardware/gx.h"
|
||||
|
||||
|
||||
|
||||
// LCD/ABL regs.
|
||||
#define LCD_REGS_BASE (IO_MEM_ARM11_ONLY + 0x2000)
|
||||
#define REG_LCD_PARALLAX_CNT *((vu32*)(LCD_REGS_BASE + 0x000)) // Controls PWM for the parallax barrier?
|
||||
#define REG_LCD_PARALLAX_PWM *((vu32*)(LCD_REGS_BASE + 0x004)) // Frequency/other PWM stuff maybe?
|
||||
#define REG_LCD_UNK00C *((vu32*)(LCD_REGS_BASE + 0x00C)) // Wtf is "FIX"?
|
||||
#define REG_LCD_RST *((vu32*)(LCD_REGS_BASE + 0x014)) // Reset active low.
|
||||
|
||||
#define REG_LCD_ABL0_CNT *((vu32*)(LCD_REGS_BASE + 0x200)) // Bit 0 enables ABL aka power saving mode.
|
||||
#define REG_LCD_ABL0_FILL *((vu32*)(LCD_REGS_BASE + 0x204))
|
||||
#define REG_LCD_ABL0_LIGHT *((vu32*)(LCD_REGS_BASE + 0x240))
|
||||
#define REG_LCD_ABL0_LIGHT_PWM *((vu32*)(LCD_REGS_BASE + 0x244))
|
||||
|
||||
#define REG_LCD_ABL1_CNT *((vu32*)(LCD_REGS_BASE + 0xA00)) // Bit 0 enables ABL aka power saving mode.
|
||||
#define REG_LCD_ABL1_FILL *((vu32*)(LCD_REGS_BASE + 0xA04))
|
||||
#define REG_LCD_ABL1_LIGHT *((vu32*)(LCD_REGS_BASE + 0xA40))
|
||||
#define REG_LCD_ABL1_LIGHT_PWM *((vu32*)(LCD_REGS_BASE + 0xA44))
|
||||
|
||||
|
||||
// Technically these regs belong in gx.h but they are used for LCD configuration so...
|
||||
// Pitfall warning: The 3DS LCDs are physically rotated 90° CCW.
|
||||
|
||||
// PDC0 (top screen display controller) regs.
|
||||
#define REG_LCD_PDC0_HTOTAL *((vu32*)(GX_REGS_BASE + 0x400))
|
||||
#define REG_LCD_PDC0_VTOTAL *((vu32*)(GX_REGS_BASE + 0x424))
|
||||
#define REG_LCD_PDC0_HPOS *((const vu32*)(GX_REGS_BASE + 0x450))
|
||||
#define REG_LCD_PDC0_VPOS *((const vu32*)(GX_REGS_BASE + 0x454))
|
||||
#define REG_LCD_PDC0_FB_A1 *((vu32*)(GX_REGS_BASE + 0x468))
|
||||
#define REG_LCD_PDC0_FB_A2 *((vu32*)(GX_REGS_BASE + 0x46C))
|
||||
#define REG_LCD_PDC0_FMT *((vu32*)(GX_REGS_BASE + 0x470))
|
||||
#define REG_LCD_PDC0_CNT *((vu32*)(GX_REGS_BASE + 0x474))
|
||||
#define REG_LCD_PDC0_SWAP *((vu32*)(GX_REGS_BASE + 0x478))
|
||||
#define REG_LCD_PDC0_STAT *((const vu32*)(GX_REGS_BASE + 0x47C))
|
||||
#define REG_LCD_PDC0_GTBL_IDX *((vu32*)(GX_REGS_BASE + 0x480)) // Gamma table index.
|
||||
#define REG_LCD_PDC0_GTBL_FIFO *((vu32*)(GX_REGS_BASE + 0x484)) // Gamma table FIFO.
|
||||
#define REG_LCD_PDC0_STRIDE *((vu32*)(GX_REGS_BASE + 0x490))
|
||||
#define REG_LCD_PDC0_FB_B1 *((vu32*)(GX_REGS_BASE + 0x494))
|
||||
#define REG_LCD_PDC0_FB_B2 *((vu32*)(GX_REGS_BASE + 0x498))
|
||||
|
||||
// PDC1 (bottom screen display controller) regs.
|
||||
#define REG_LCD_PDC1_HTOTAL *((vu32*)(GX_REGS_BASE + 0x500))
|
||||
#define REG_LCD_PDC1_VTOTAL *((vu32*)(GX_REGS_BASE + 0x524))
|
||||
#define REG_LCD_PDC1_HPOS *((const vu32*)(GX_REGS_BASE + 0x550))
|
||||
#define REG_LCD_PDC1_VPOS *((const vu32*)(GX_REGS_BASE + 0x554))
|
||||
#define REG_LCD_PDC1_FB_A1 *((vu32*)(GX_REGS_BASE + 0x568))
|
||||
#define REG_LCD_PDC1_FB_A2 *((vu32*)(GX_REGS_BASE + 0x56C))
|
||||
#define REG_LCD_PDC1_FMT *((vu32*)(GX_REGS_BASE + 0x570))
|
||||
#define REG_LCD_PDC1_CNT *((vu32*)(GX_REGS_BASE + 0x574))
|
||||
#define REG_LCD_PDC1_SWAP *((vu32*)(GX_REGS_BASE + 0x578))
|
||||
#define REG_LCD_PDC1_STAT *((const vu32*)(GX_REGS_BASE + 0x57C))
|
||||
#define REG_LCD_PDC1_GTBL_IDX *((vu32*)(GX_REGS_BASE + 0x580)) // Gamma table index.
|
||||
#define REG_LCD_PDC1_GTBL_FIFO *((vu32*)(GX_REGS_BASE + 0x584)) // Gamma table FIFO.
|
||||
#define REG_LCD_PDC1_STRIDE *((vu32*)(GX_REGS_BASE + 0x590))
|
||||
#define REG_LCD_PDC1_FB_B1 *((vu32*)(GX_REGS_BASE + 0x594))
|
||||
#define REG_LCD_PDC1_FB_B2 *((vu32*)(GX_REGS_BASE + 0x598))
|
||||
|
||||
|
||||
// REG_LCD_PDC_CNT
|
||||
#define PDC_CNT_E (1u)
|
||||
#define PDC_CNT_I_MASK_H (1u<<8) // Disables H(Blank?) IRQs.
|
||||
#define PDC_CNT_I_MASK_V (1u<<9) // Disables VBlank IRQs.
|
||||
#define PDC_CNT_I_MASK_ERR (1u<<10) // Disables error IRQs. What kind of errors?
|
||||
#define PDC_CNT_I_MASK_ALL (PDC_CNT_I_MASK_ERR | PDC_CNT_I_MASK_V | PDC_CNT_I_MASK_H)
|
||||
#define PDC_CNT_OUT_E (1u<<16) // Output enable?
|
||||
|
||||
// REG_LCD_PDC_SWAP
|
||||
// Masks
|
||||
#define PDC_SWAP_NEXT (1u) // Next framebuffer.
|
||||
#define PDC_SWAP_CUR (1u<<4) // Currently displaying framebuffer?
|
||||
// Bits
|
||||
#define PDC_SWAP_RST_FIFO (1u<<8) // Which FIFO?
|
||||
#define PDC_SWAP_I_H (1u<<16) // H(Blank?) IRQ bit.
|
||||
#define PDC_SWAP_I_V (1u<<17) // VBlank IRQ bit.
|
||||
#define PDC_SWAP_I_ERR (1u<<18) // Error IRQ bit?
|
||||
#define PDC_SWAP_I_ALL (PDC_SWAP_I_ERR | PDC_SWAP_I_V | PDC_SWAP_I_H)
|
||||
|
||||
|
||||
// LCD I2C regs.
|
||||
typedef enum
|
||||
{
|
||||
LCD_I2C_REG_POWER = 0x01u,
|
||||
LCD_I2C_REG_UNK11 = 0x11u,
|
||||
LCD_I2C_REG_READ_ADDR = 0x40u,
|
||||
LCD_I2C_REG_HS_SERIAL = 0x50u, // Highspeed serial for upper LCD only.
|
||||
LCD_I2C_REG_UNK54 = 0x54u, // Checksum on/off?
|
||||
LCD_I2C_REG_UNK55 = 0x55u, // Checksum status?
|
||||
LCD_I2C_REG_STATUS = 0x60u, // Initially 0x01.
|
||||
LCD_I2C_REG_BL_STATUS = 0x62u, // Backlight status.
|
||||
LCD_I2C_REG_RST_STATUS = 0xFEu, // Reset status. Initially 0x00.
|
||||
LCD_I2C_REG_REVISION = 0xFFu, // Revision/vendor infos.
|
||||
} LcdI2cReg;
|
||||
|
||||
// LCD_I2C_REG_POWER
|
||||
#define LCD_REG_POWER_BLACK (0x11u) // Force blackscreen.
|
||||
#define LCD_REG_POWER_ON (0x10u) // Normal operation.
|
||||
#define LCD_REG_POWER_OFF (0x00u) // LCD powered off.
|
||||
|
||||
// LCD_I2C_REG_UNK11
|
||||
#define LCD_REG_UNK11_UNK10 (0x10u) // Written on init.
|
||||
|
||||
// LCD_I2C_REG_HS_SERIAL
|
||||
#define LCD_REG_HS_SERIAL_ON (0x01u) // Enable highspeed serial.
|
||||
|
||||
// LCD_I2C_REG_UNK54
|
||||
|
||||
// LCD_I2C_REG_UNK55
|
||||
|
||||
// LCD_I2C_REG_STATUS
|
||||
#define LCD_REG_STATUS_OK (0x00u)
|
||||
#define LCD_REG_STATUS_ERR (0x01u)
|
||||
|
||||
// LCD_I2C_REG_BL_STATUS
|
||||
#define LCD_REG_BL_STATUS_OFF (0x00u)
|
||||
#define LCD_REG_BL_STATUS_ON (0x01u)
|
||||
|
||||
// LCD_I2C_REG_RST_STATUS
|
||||
#define LCD_REG_RST_STATUS_NONE (0xAAu)
|
||||
#define LCD_REG_RST_STATUS_RST (0x00u)
|
||||
|
||||
|
||||
|
||||
u8 LCDI2C_readReg(u8 lcd, LcdI2cReg reg);
|
||||
void LCDI2C_writeReg(u8 lcd, LcdI2cReg reg, u8 data);
|
||||
void LCDI2C_init(void);
|
||||
void LCDI2C_waitBacklightsOn(void);
|
||||
u16 LCDI2C_getRevisions(void);
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "kevent.h"
|
||||
|
||||
|
||||
// REG_LGYFB_CNT
|
||||
#define LGYFB_ENABLE (1u)
|
||||
#define LGYFB_VSCALE_E (1u<<1)
|
||||
#define LGYFB_HSCALE_E (1u<<2)
|
||||
#define LGYFB_SPATIAL_DITHER_E (1u<<4) // Unset behaves like weight 0xCCCC in both pattern regs.
|
||||
#define LGYFB_TEMPORAL_DITHER_E (1u<<5) // Unset behaves like weight 0xCCCC in both pattern regs.
|
||||
#define LGYFB_OUT_FMT_8888 (0u)
|
||||
#define LGYFB_OUT_FMT_8880 (1u<<8)
|
||||
#define LGYFB_OUT_FMT_5551 (2u<<8)
|
||||
#define LGYFB_OUT_FMT_5650 (3u<<8)
|
||||
#define LGYFB_ROT_NONE (0u)
|
||||
#define LGYFB_ROT_90CW (1u<<10)
|
||||
#define LGYFB_ROT_180CW (2u<<10)
|
||||
#define LGYFB_ROT_270CW (3u<<10)
|
||||
#define LGYFB_OUT_SWIZZLE (1u<<12)
|
||||
#define LGYFB_DMA_E (1u<<15)
|
||||
#define LGYFB_IN_FMT (1u<<16) // Use input format but this bit does nothing?
|
||||
|
||||
// REG_LGYFB_SIZE width and hight
|
||||
#define LGYFB_SIZE(w, h) (((h) - 1)<<16 | ((w) - 1))
|
||||
|
||||
// REG_LGYFB_STAT and REG_LGYFB_IRQ
|
||||
#define LGYFB_IRQ_DMA_REQ (1u)
|
||||
#define LGYFB_IRQ_BUF_ERR (1u<<1) // FIFO overrun?
|
||||
#define LGYFB_IRQ_VBLANK (1u<<2)
|
||||
#define LGYFB_IRQ_MASK (LGYFB_IRQ_VBLANK | LGYFB_IRQ_BUF_ERR | LGYFB_IRQ_DMA_REQ)
|
||||
#define LGYFB_OUT_LINE(reg) ((reg)>>16) // STAT only
|
||||
|
||||
|
||||
|
||||
void LGYFB_init(KEvent *frameReadyEvent);
|
||||
void LGYFB_deinit(void);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void LGYFB_dbgDumpFrame(void);
|
||||
#endif
|
|
@ -0,0 +1,132 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "arm11/hardware/i2c.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MCU_REG_VERS_HIGH = 0x00u,
|
||||
MCU_REG_VERS_LOW = 0x01u,
|
||||
MCU_REG_3D_SLIDER = 0x08u,
|
||||
MCU_REG_VOL_SLIDER = 0x09u, // 0-0x3F
|
||||
MCU_REG_BATTERY = 0x0Bu,
|
||||
MCU_REG_EX_HW_STATE = 0x0Fu,
|
||||
MCU_REG_EVENTS = 0x10u,
|
||||
MCU_REG_EVENT_MASK = 0x18u,
|
||||
MCU_REG_POWER = 0x20u,
|
||||
MCU_REG_LCDs = 0x22u,
|
||||
MCU_REG_POWER_LED = 0x29u,
|
||||
MCU_REG_WIFI_LED = 0x2Au,
|
||||
MCU_REG_CAM_LED = 0x2Bu,
|
||||
MCU_REG_3D_LED = 0x2Cu,
|
||||
MCU_REG_RTC_TIME = 0x30u,
|
||||
MCU_REG_RAW_STATE = 0x7Fu
|
||||
} McuReg;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWLED_AUTO = 0u,
|
||||
//PWLED_BLUE = 1u, // wtf is "forced default blue"?
|
||||
PWLED_SLEEP = 2u,
|
||||
PWLED_OFF = 3u,
|
||||
PWLED_RED = 4u,
|
||||
PWLED_BLUE = 5u,
|
||||
PWLED_BLINK_RED = 6u
|
||||
} PwLedState;
|
||||
|
||||
|
||||
|
||||
u8 MCU_readReg(McuReg reg);
|
||||
|
||||
bool MCU_writeReg(McuReg reg, u8 data);
|
||||
|
||||
bool MCU_readRegBuf(McuReg reg, u8 *out, u32 size);
|
||||
|
||||
bool MCU_writeRegBuf(McuReg reg, const u8 *const in, u32 size);
|
||||
|
||||
void MCU_init(void);
|
||||
|
||||
bool MCU_setEventMask(u32 mask);
|
||||
|
||||
u32 MCU_getEvents(u32 mask);
|
||||
|
||||
u32 MCU_waitEvents(u32 mask);
|
||||
|
||||
|
||||
static inline u8 MCU_getBatteryLevel(void)
|
||||
{
|
||||
u8 state;
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_BATTERY, &state, 1)) return 0;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static inline u8 MCU_getExternalHwState(void)
|
||||
{
|
||||
return MCU_readReg(MCU_REG_EX_HW_STATE);
|
||||
}
|
||||
|
||||
static inline void MCU_powerOffSys(void)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, MCU_REG_POWER, 1u);
|
||||
}
|
||||
|
||||
static inline void MCU_rebootSys(void)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, MCU_REG_POWER, 1u<<2);
|
||||
}
|
||||
|
||||
static inline void MCU_controlLCDPower(u8 bits)
|
||||
{
|
||||
MCU_writeReg(MCU_REG_LCDs, bits);
|
||||
}
|
||||
|
||||
static inline bool MCU_setPowerLedState(PwLedState state)
|
||||
{
|
||||
return MCU_writeReg(MCU_REG_POWER_LED, state);
|
||||
}
|
||||
|
||||
static inline bool MCU_getRTCTime(u8 rtc[7])
|
||||
{
|
||||
if(!rtc) return true;
|
||||
|
||||
return MCU_readRegBuf(MCU_REG_RTC_TIME, rtc, 7);
|
||||
}
|
||||
|
||||
static inline u8 MCU_getSystemModel(void)
|
||||
{
|
||||
u8 buf[10];
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_RAW_STATE, buf, sizeof(buf))) return 0xFF;
|
||||
|
||||
return buf[9];
|
||||
}
|
||||
|
||||
static inline u8 MCU_getHidHeld(void)
|
||||
{
|
||||
u8 data[19];
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_RAW_STATE, data, sizeof(data))) return 0xFF;
|
||||
|
||||
return data[18];
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2020 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#define PDN_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x41000)
|
||||
#define REG_PDN_CNT *((vu16*)(PDN_REGS_BASE + 0x000))
|
||||
#define REG_PDN_WAKE_ENABLE *((vu32*)(PDN_REGS_BASE + 0x008))
|
||||
#define REG_PDN_WAKE_REASON *((vu32*)(PDN_REGS_BASE + 0x00C)) // Write 1 to acknowledge and 0 to clear?
|
||||
#define REG_PDN_GPU_CNT *((vu32*)(PDN_REGS_BASE + 0x200))
|
||||
#define REG_PDN_VRAM_CNT *((vu8* )(PDN_REGS_BASE + 0x204)) // This reg doesn't seem to exist on retail hardware.
|
||||
#define REG_PDN_LCD_CNT *((vu8* )(PDN_REGS_BASE + 0x208)) // This reg doesn't seem to exist on retail hardware.
|
||||
#define REG_PDN_FCRAM_CNT *((vu8* )(PDN_REGS_BASE + 0x210))
|
||||
#define REG_PDN_I2S_CNT *((vu8* )(PDN_REGS_BASE + 0x220))
|
||||
#define REG_PDN_CAM_CNT *((vu8* )(PDN_REGS_BASE + 0x224))
|
||||
#define REG_PDN_DSP_CNT *((vu8* )(PDN_REGS_BASE + 0x230))
|
||||
#define REG_PDN_G1_CNT *((vu8* )(PDN_REGS_BASE + 0x240)) // Hantro G1 decoder.
|
||||
#define REG_PDN_MPCORE_SOCMODE *((vu16*)(PDN_REGS_BASE + 0x300))
|
||||
#define REG_PDN_MPCORE_CNT *((vu16*)(PDN_REGS_BASE + 0x304)) // Is this reg actually only vu8?
|
||||
#define REGs_PDN_MPCORE_BOOTCNT ((vu8* )(PDN_REGS_BASE + 0x310))
|
||||
|
||||
|
||||
// REG_PDN_CNT
|
||||
#define PDN_CNT_SLEEP (1u) // Set this bit to enter sleep mode.
|
||||
#define PDN_CNT_VRAM_OFF (1u<<15) // Set when VRAM is powered off.
|
||||
|
||||
// REG_PDN_WAKE_ENABLE and REG_PDN_WAKE_REASON
|
||||
enum
|
||||
{
|
||||
PDN_WAKE_PADCNT = 1u,
|
||||
PDN_WAKE_SHELL_OPENED = 1u<<3,
|
||||
PDN_WAKE_HEADPH_NOT_PLUGGED_IN = 1u<<4, // Really?
|
||||
PDN_WAKE_UNK6 = 1u<<6, // DSi mode related.
|
||||
PDN_WAKE_SDIO1 = 1u<<7,
|
||||
PDN_WAKE_SDIO2 = 1u<<8,
|
||||
PDN_WAKE_SDIO3 = 1u<<16,
|
||||
// 17-28 maybe GPIO3 0-11?
|
||||
PDN_WAKE_GAMECARD_INSERT = 1u<<29, // ?
|
||||
PDN_WAKE_TOUCHPEN_DOWN = 1u<<30,
|
||||
PDN_WAKE_UNK31 = 1u<<31 // Also shell related?
|
||||
};
|
||||
|
||||
// REG_PDN_GPU_CNT
|
||||
// Note: The resets are active low.
|
||||
enum
|
||||
{
|
||||
PDN_GPU_CNT_RST_REGS = 1u, // And more?
|
||||
PDN_GPU_CNT_RST_PSC = 1u<<1, // ?
|
||||
PDN_GPU_CNT_RST_GEOSHADER = 1u<<2, // ?
|
||||
PDN_GPU_CNT_RST_RASTERIZER = 1u<<3, // ?
|
||||
PDN_GPU_CNT_RST_PPF = 1u<<4,
|
||||
PDN_GPU_CNT_RST_PDC = 1u<<5, // ?
|
||||
PDN_GPU_CNT_RST_PDC2 = 1u<<6, // Maybe pixel pipeline or so?
|
||||
|
||||
PDN_GPU_CNT_RST_ALL = (PDN_GPU_CNT_RST_PDC2<<1) - 1
|
||||
};
|
||||
|
||||
#define PDN_GPU_CNT_CLK_E (1u<<16)
|
||||
|
||||
// REG_PDN_VRAM_CNT
|
||||
#define PDN_VRAM_CNT_CLK_E (1u)
|
||||
|
||||
// REG_PDN_LCD_CNT
|
||||
#define PDN_LCD_CNT_PWR_MGR_OFF (1u) // Power management off?
|
||||
|
||||
// REG_PDN_FCRAM_CNT
|
||||
// Note: Reset is active low.
|
||||
#define PDN_FCRAM_CNT_RST (1u)
|
||||
#define PDN_FCRAM_CNT_CLK_E (1u<<1)
|
||||
#define PDN_FCRAM_CNT_CLK_E_ACK (1u<<2) // Gets set or unset depending on CLK_E.
|
||||
|
||||
// REG_PDN_I2S_CNT
|
||||
#define PDN_I2S_CNT_I2S_CLK1_E (1u) // ? Unused?
|
||||
#define PDN_I2S_CNT_I2S_CLK2_E (1u<<1)
|
||||
|
||||
// REG_PDN_CAM_CNT
|
||||
#define PDN_CAM_CNT_CLK_E (1u)
|
||||
|
||||
// REG_PDN_DSP_CNT
|
||||
// Note: Reset is active low.
|
||||
#define PDN_DSP_CNT_RST (1u)
|
||||
#define PDN_DSP_CNT_CLK_E (1u<<1)
|
||||
|
||||
// REG_PDN_G1_CNT
|
||||
// TODO: Active low or high?
|
||||
#define PDN_G1_CNT_RST (1u)
|
||||
|
||||
// REG_PDN_MPCORE_SOCMODE
|
||||
typedef enum
|
||||
{
|
||||
SOCMODE_O3DS_268MHz = 0u,
|
||||
SOCMODE_N3DS_268MHz = 1u, // Also enables FCRAM extension.
|
||||
SOCMODE_N3DS_PROTO_268MHz = 2u, // Also enables FCRAM extension?
|
||||
SOCMODE_N3DS_PROTO_536MHz = 3u, // Also enables FCRAM extension?
|
||||
SOCMODE_N3DS_804MHz = 5u, // Also enables FCRAM extension.
|
||||
|
||||
SOCMODE_MASK = 7u
|
||||
} PdnSocmode;
|
||||
|
||||
#define PDN_MPCORE_SOCMODE_ACK (1u<<15)
|
||||
|
||||
// REG_PDN_MPCORE_CNT
|
||||
#define PDN_MPCORE_CNT_MEM_EXT_E (1u) // Does it actually affect all mem extensions or just QTM?
|
||||
#define PDN_MPCORE_CNT_L2C_E (1u<<8)
|
||||
|
||||
// REGs_PDN_MPCORE_BOOTCNT
|
||||
// Note: Reset is active low.
|
||||
#define MPCORE_BOOTCNT_RST (1u) // Core 2/3 only. Reset and instruction overlay enable.
|
||||
#define MPCORE_BOOTCNT_D_OVERL_E (1u<<1) // Core 2/3 only. Data overlay enable. Also used to signal a core booted.
|
||||
#define MPCORE_BOOTCNT_RST_STAT (1u<<4)
|
||||
#define MPCORE_BOOTCNT_UNK (1u<<5)
|
||||
|
||||
|
||||
|
||||
void PDN_core123Init(void);
|
||||
void PDN_setSocmode(PdnSocmode socmode);
|
||||
void PDN_poweroffCore23(void);
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Refer to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360f/index.html
|
||||
// (comprocessor regs c15) for documentation.
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
static inline void startProfiling(u16 pmnEvents, u8 intMask, bool ccntDiv64, u8 reset)
|
||||
{
|
||||
const u32 tmp = pmnEvents<<12 | 7u<<8 | intMask<<4 | ccntDiv64<<3 | reset<<1 | 1u;
|
||||
__asm__ volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (tmp) : "memory");
|
||||
}
|
||||
|
||||
static inline void stopProfiling(void)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (7u<<8) : "memory");
|
||||
}
|
||||
|
||||
static inline void setCcnt(u32 val)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val) : "memory");
|
||||
}
|
||||
|
||||
static inline void setPmn0(u32 val)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val) : "memory");
|
||||
}
|
||||
|
||||
static inline void setPmn1(u32 val)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val) : "memory");
|
||||
}
|
||||
|
||||
static inline u32 getCcnt(void)
|
||||
{
|
||||
u32 tmp;
|
||||
__asm__ volatile("mrc p15, 0, %0, c15, c12, 1" : "=r" (tmp) : : "memory");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline u32 getPmn0(void)
|
||||
{
|
||||
u32 tmp;
|
||||
__asm__ volatile("mrc p15, 0, %0, c15, c12, 2" : "=r" (tmp) : : "memory");
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline u32 getPmn1(void)
|
||||
{
|
||||
u32 tmp;
|
||||
__asm__ volatile("mrc p15, 0, %0, c15, c12, 3" : "=r" (tmp) : : "memory");
|
||||
return tmp;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#define SCU_REGS_BASE (MPCORE_PRIV_REG_BASE)
|
||||
#define REG_SCU_CNT *((vu32*)(SCU_REGS_BASE + 0x00))
|
||||
#define REG_SCU_CONFIG *((vu32*)(SCU_REGS_BASE + 0x04))
|
||||
#define REG_SCU_CPU_STAT *((vu32*)(SCU_REGS_BASE + 0x08))
|
||||
#define REG_SCU_INVAL_TAG *((vu32*)(SCU_REGS_BASE + 0x0C))
|
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
// REG_NSPI_CNT
|
||||
#define NSPI_BUS_1BIT (0u)
|
||||
#define NSPI_BUS_4BIT (1u<<12)
|
||||
#define NSPI_DIR_READ (0u)
|
||||
#define NSPI_DIR_WRITE (1u<<13)
|
||||
#define NSPI_ENABLE (1u<<15)
|
||||
|
||||
// REG_NSPI_CS
|
||||
#define NSPI_DESELECT (0u)
|
||||
|
||||
// NSPI_FIFO_STAT
|
||||
#define NSPI_FIFO_BUSY (1u)
|
||||
|
||||
// REG_NSPI_AUTOPOLL
|
||||
#define NSPI_AUTOPOLL_START (1u<<31)
|
||||
|
||||
// REG_NSPI_INT_MASK Bit set = disabled.
|
||||
// REG_NSPI_INT_STAT Status and aknowledge.
|
||||
#define NSPI_INT_TRANSF_END (1u) // Also fires on each auto poll try.
|
||||
#define NSPI_INT_AP_SUCCESS (1u<<1) // Auto poll
|
||||
#define NSPI_INT_AP_TIMEOUT (1u<<2) // Auto poll
|
||||
|
||||
|
||||
// Old interface clocks.
|
||||
enum
|
||||
{
|
||||
SPI_CLK_4MHz = 0u,
|
||||
SPI_CLK_2MHz = 1u,
|
||||
SPI_CLK_1MHz = 2u,
|
||||
SPI_CLK_512KHz = 3u,
|
||||
SPI_CLK_8MHz = 4u // Only in DSi/3DS mode.
|
||||
};
|
||||
|
||||
// New interface clocks.
|
||||
enum
|
||||
{
|
||||
NSPI_CLK_512KHz = 0u,
|
||||
NSPI_CLK_1MHz = 1u,
|
||||
NSPI_CLK_2MHz = 2u,
|
||||
NSPI_CLK_4MHz = 3u,
|
||||
NSPI_CLK_8MHz = 4u,
|
||||
NSPI_CLK_16MHz = 5u
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NSPI_DEV_POWERMAN = 0u, // Unused DS(i) mode power management
|
||||
NSPI_DEV_NVRAM = 1u, // WiFi SPI flash
|
||||
NSPI_DEV_TWL_CODEC = 2u,
|
||||
NSPI_DEV_CTR_CODEC = 3u,
|
||||
NSPI_DEV_UNUSED5 = 4u, // Unused "CS2".
|
||||
NSPI_DEV_UNUSED6 = 5u, // Unused "CS3".
|
||||
NSPI_DEV_UNUSED7 = 6u // Debugger?
|
||||
} SpiDevice;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the SPI buses. Call this only once.
|
||||
*/
|
||||
void NSPI_init(void);
|
||||
|
||||
/**
|
||||
* @brief Automatically polls a bit of the command response. Use with the macro below.
|
||||
*
|
||||
* @param[in] dev The device ID. See table above.
|
||||
* @param[in] params The parameters. Use the macro below.
|
||||
*
|
||||
* @return Returns false on failure/timeout and true on success.
|
||||
*/
|
||||
bool _NSPI_autoPollBit(SpiDevice dev, u32 params);
|
||||
|
||||
/**
|
||||
* @brief Writes and/or reads data to/from a SPI device.
|
||||
*
|
||||
* @param[in] dev The device ID. See table above.
|
||||
* @param[in] in Input data pointer for write.
|
||||
* @param out Output data pointer for read.
|
||||
* @param[in] inSize Input size. Must be <= 0x1FFFFF.
|
||||
* @param[in] outSize Output size. Must be <= 0x1FFFFF.
|
||||
* @param[in] done Set to true if this is the last transfer (chip select).
|
||||
*/
|
||||
void NSPI_writeRead(SpiDevice dev, const u32 *in, u32 *out, u32 inSize, u32 outSize, bool done);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Automatically polls a bit of the command response.
|
||||
*
|
||||
* @param[in] dev The device ID. See table above.
|
||||
* @param[in] cmd The command.
|
||||
* @param[in] timeout The timeout. Must be 0-15. Tries = 31<<NspiClk + timeout.
|
||||
* @param[in] off The bit offset. Must be 0-7.
|
||||
* @param[in] bitSet Poll for a set ur unset bit.
|
||||
*
|
||||
* @return Returns false on failure/timeout and true on success.
|
||||
*/
|
||||
#define NSPI_autoPollBit(dev, cmd, timeout, off, bitSet) _NSPI_autoPollBit(dev, (bitSet)<<30 | (off)<<24 | (timeout)<<16 | (cmd))
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define SPIFLASH_CMD_RDSR (0x05)
|
||||
#define SPIFLASH_CMD_READ (0x03)
|
||||
|
||||
|
||||
|
||||
// true if spiflash is installed, false otherwise
|
||||
bool spiflash_get_status(void);
|
||||
void spiflash_read(u32 offset, u32 size, u32 *buf);
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define TIMER_BASE_FREQ (268111856.f)
|
||||
|
||||
#define TIMER_ENABLE (1u)
|
||||
#define TIMER_SINGLE_SHOT (0u)
|
||||
#define TIMER_AUTO_RELOAD (1u<<1)
|
||||
#define TIMER_IRQ_ENABLE (1u<<2)
|
||||
|
||||
// p is the prescaler value and n the frequence
|
||||
#define TIMER_FREQ(p, f) (TIMER_BASE_FREQ / 2 / (p) / (f))
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Resets/initializes the timer hardware. Should not be called manually.
|
||||
*/
|
||||
void TIMER_init(void);
|
||||
|
||||
/**
|
||||
* @brief Starts the timer.
|
||||
*
|
||||
* @param[in] prescaler The prescaler value.
|
||||
* @param[in] ticks The initial number of ticks. This is also the
|
||||
* reload value in auto reload mode.
|
||||
* @param[in] autoReload Set to true for auto reload. false for single shot.
|
||||
* @param[in] enableIrq Timer fires IRQs on underflow if true.
|
||||
*/
|
||||
void TIMER_start(u8 prescaler, u32 ticks, bool autoReload, bool enableIrq);
|
||||
|
||||
/**
|
||||
* @brief Returns the current number of ticks of the timer.
|
||||
*
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
u32 TIMER_getTicks(void);
|
||||
|
||||
/**
|
||||
* @brief Stops the timer and returns the current number of ticks.
|
||||
*
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
u32 TIMER_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Halts the CPU for the specified number of ticks.
|
||||
* Use the function below for a milliseconds version.
|
||||
*
|
||||
* @param[in] ticks The number of ticks to sleep.
|
||||
*/
|
||||
void TIMER_sleepTicks(u32 ticks);
|
||||
|
||||
|
||||
// Sleeps ms milliseconds. ms can be up to 32000.
|
||||
static inline void TIMER_sleepMs(u32 ms)
|
||||
{
|
||||
TIMER_sleepTicks(TIMER_FREQ(1, 1000) * ms);
|
||||
}
|
|
@ -1,38 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2021 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "error_codes.h"
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result oafParseConfigEarly(void);
|
||||
void changeBacklight(s16 amount);
|
||||
Result oafInitAndRun(void);
|
||||
void oafUpdate(void);
|
||||
void oafFinish(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
noreturn void power_off(void);
|
||||
noreturn void power_reboot(void);
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
static inline void spinlockLock(u32 *lock)
|
||||
{
|
||||
u32 tmp;
|
||||
__asm__ volatile("1: ldrex %0, [%1]\n"
|
||||
" teq %0, #0\n"
|
||||
" wfene\n"
|
||||
" strexeq %0, %2, [%1]\n"
|
||||
" teqeq %0, #0\n"
|
||||
" bne 1b\n"
|
||||
" mcr p15, 0, %0, c7, c10, 5" // DMB
|
||||
: "=&r" (tmp) : "r" (lock), "r" (1) : "cc", "memory");
|
||||
}
|
||||
|
||||
static inline void spinlockUnlock(u32 *lock)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c7, c10, 5\n" // DMB
|
||||
"str %0, [%1]\n"
|
||||
"mcr p15, 0, %0, c7, c10, 4\n" // DSB
|
||||
"sev"
|
||||
: : "r" (0), "r" (lock) : "memory");
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,9 +19,8 @@
|
|||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
|
||||
KHandle OAF_videoInit(void);
|
||||
void OAF_videoExit(void);
|
||||
noreturn void _start(void);
|
||||
void deinitCpu(void);
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* @file rbtree.h
|
||||
* @brief Red-black trees.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/// Retrieves an rbtree item.
|
||||
#define rbtree_item(ptr, type, member) \
|
||||
((type*)(((char*)ptr) - offsetof(type, member)))
|
||||
|
||||
typedef struct rbtree rbtree_t; ///< rbtree type.
|
||||
typedef struct rbtree_node rbtree_node_t; ///< rbtree node type.
|
||||
|
||||
typedef void (*rbtree_node_destructor_t)(rbtree_node_t *Node); ///< rbtree node destructor.
|
||||
typedef int (*rbtree_node_comparator_t)(const rbtree_node_t *lhs,
|
||||
const rbtree_node_t *rhs); ///< rbtree node comparator.
|
||||
|
||||
/// An rbtree node.
|
||||
struct rbtree_node
|
||||
{
|
||||
uintptr_t parent_color; ///< Parent color.
|
||||
rbtree_node_t *child[2]; ///< Node children.
|
||||
};
|
||||
|
||||
/// An rbtree.
|
||||
struct rbtree
|
||||
{
|
||||
rbtree_node_t *root; ///< Root node.
|
||||
rbtree_node_comparator_t comparator; ///< Node comparator.
|
||||
size_t size; ///< Size.
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param comparator Comparator to use.
|
||||
*/
|
||||
void
|
||||
rbtree_init(rbtree_t *tree,
|
||||
rbtree_node_comparator_t comparator);
|
||||
|
||||
/**
|
||||
* @brief Gets whether an rbtree is empty
|
||||
* @param tree Pointer to the tree.
|
||||
* @return A non-zero value if the tree is not empty.
|
||||
*/
|
||||
int
|
||||
rbtree_empty(const rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Gets the size of an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
*/
|
||||
size_t
|
||||
rbtree_size(const rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Inserts a node into an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param node Pointer to the node.
|
||||
* @return The inserted node.
|
||||
*/
|
||||
__attribute__((warn_unused_result))
|
||||
rbtree_node_t*
|
||||
rbtree_insert(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
|
||||
/**
|
||||
* @brief Inserts multiple nodes into an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param node Pointer to the nodes.
|
||||
*/
|
||||
void
|
||||
rbtree_insert_multi(rbtree_t *tree,
|
||||
rbtree_node_t *node);
|
||||
|
||||
/**
|
||||
* @brief Finds a node within an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param node Pointer to the node.
|
||||
* @return The located node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_find(const rbtree_t *tree,
|
||||
const rbtree_node_t *node);
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum node of an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @return The minimum node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_min(const rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Gets the maximum node of an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @return The maximum node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_max(const rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Gets the next node from an rbtree node.
|
||||
* @param node Pointer to the node.
|
||||
* @return The next node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_node_next(const rbtree_node_t *node);
|
||||
|
||||
/**
|
||||
* @brief Gets the previous node from an rbtree node.
|
||||
* @param node Pointer to the node.
|
||||
* @return The previous node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_node_prev(const rbtree_node_t *node);
|
||||
|
||||
/**
|
||||
* @brief Removes a node from an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param node Pointer to the node.
|
||||
* @param destructor Destructor to use when removing the node.
|
||||
* @return The removed node.
|
||||
*/
|
||||
rbtree_node_t*
|
||||
rbtree_remove(rbtree_t *tree,
|
||||
rbtree_node_t *node,
|
||||
rbtree_node_destructor_t destructor);
|
||||
|
||||
/**
|
||||
* @brief Clears an rbtree.
|
||||
* @param tree Pointer to the tree.
|
||||
* @param destructor Destructor to use when clearing the tree's nodes.
|
||||
*/
|
||||
void
|
||||
rbtree_clear(rbtree_t *tree,
|
||||
rbtree_node_destructor_t destructor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
noreturn void _a7_overlay_stub(void);
|
||||
extern const u32 _a7_overlay_stub_size[];
|
||||
|
||||
noreturn void _a7_stub_start(void);
|
||||
extern u16 _a7_stub9_swi[]; // Final ARM9 mem location.
|
||||
extern const u32 _a7_stub_size[];
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,13 +22,6 @@
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void makeOpenBusPaddingFast(u32 *romEnd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
noreturn void panic();
|
||||
noreturn void panicMsg(const char *msg);
|
||||
//void dumpMem(u8 *mem, u32 size, char *filepath);
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2018 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#define CFG9_REGS_BASE (IO_MEM_ARM9_ONLY)
|
||||
#define REG_CFG9_SYSPROT9 *((vu8* )(CFG9_REGS_BASE + 0x00000))
|
||||
#define REG_CFG9_SYSPROT11 *((vu8* )(CFG9_REGS_BASE + 0x00001))
|
||||
#define REG_CFG9_SOCINFO *((vu16*)(CFG9_REGS_BASE + 0x00FFC))
|
||||
#define REG_CFG9_BOOTENV *((vu32*)(CFG9_REGS_BASE + 0x10000))
|
||||
#define REG_CFG9_UNITINFO *((vu8* )(CFG9_REGS_BASE + 0x10010))
|
|
@ -0,0 +1,338 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// AES //
|
||||
//////////////////////////////////
|
||||
|
||||
#define AES_MAX_BLOCKS (0xFFFE) // Aligned for 32 bytes transfers
|
||||
|
||||
#define AES_WRITE_FIFO_COUNT (REG_AESCNT & 0x1F)
|
||||
#define AES_READ_FIFO_COUNT (REG_AESCNT & 0x3E0)
|
||||
|
||||
#define AES_FLUSH_READ_FIFO (1u<<10)
|
||||
#define AES_FLUSH_WRITE_FIFO (1u<<11)
|
||||
#define AES_MAC_SIZE(n) ((((n) - 2) / 2)<<16)
|
||||
#define AES_PASS_PAYLOARD (1u<<19) // Passes the associated data to REG_AESRDFIFO
|
||||
#define AES_MAC_SRC_REG (1u<<20)
|
||||
#define AES_IS_MAC_VALID ((bool)(REG_AESCNT>>21 & 1u))
|
||||
|
||||
#define AES_OUTPUT_BIG (1u)
|
||||
#define AES_OUTPUT_LITTLE (0u)
|
||||
#define AES_INPUT_BIG (1u)
|
||||
#define AES_INPUT_LITTLE (0u)
|
||||
#define AES_OUTPUT_NORMAL (4u)
|
||||
#define AES_OUTPUT_REVERSED (0u)
|
||||
#define AES_INPUT_NORMAL (4u)
|
||||
#define AES_INPUT_REVERSED (0u)
|
||||
|
||||
#define AES_UPDATE_KEYSLOT (1u<<26)
|
||||
#define AES_IRQ_ENABLE (1u<<30)
|
||||
#define AES_ENABLE (1u<<31)
|
||||
|
||||
#define AES_MODE_CCM_DECRYPT (0u)
|
||||
#define AES_MODE_CCM_ENCRYPT (1u<<27)
|
||||
#define AES_MODE_CTR (2u<<27)
|
||||
#define AES_MODE_CBC_DECRYPT (4u<<27)
|
||||
#define AES_MODE_CBC_ENCRYPT (5u<<27)
|
||||
#define AES_MODE_ECB_DECRYPT (6u<<27)
|
||||
#define AES_MODE_ECB_ENCRYPT (7u<<27)
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AES_KEY_NORMAL = 0u,
|
||||
AES_KEY_X = 1u,
|
||||
AES_KEY_Y = 2u
|
||||
} AesKeyType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 ctrIvNonceParams;
|
||||
u32 ctrIvNonce[4];
|
||||
u32 aesParams;
|
||||
} AES_ctx;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the AES hardware and the NDMA channels used by it.
|
||||
*/
|
||||
void AES_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinits AES to workaround a K9L bug.
|
||||
*/
|
||||
void AES_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Sets a AES key in the specified keyslot.
|
||||
*
|
||||
* @param[in] keyslot The keyslot this key will be set for.
|
||||
* @param[in] type The key type. Can be AES_KEY_NORMAL/X/Y.
|
||||
* @param[in] orderEndianess Word order and endianess bitmask.
|
||||
* @param[in] twlScrambler Set to true to use the TWL keyscrambler for keyslots > 0x03.
|
||||
* @param[in] key Pointer to 128-bit AES key data.
|
||||
*/
|
||||
void AES_setKey(u8 keyslot, AesKeyType type, u8 orderEndianess, bool twlScrambler, const u32 key[4]);
|
||||
|
||||
/**
|
||||
* @brief Selects the given keyslot for all following crypto operations.
|
||||
*
|
||||
* @param[in] keyslot The keyslot to select.
|
||||
*/
|
||||
void AES_selectKeyslot(u8 keyslot);
|
||||
|
||||
/**
|
||||
* @brief Copies the given nonce into internal state.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] orderEndianess Word order and endianess bitmask.
|
||||
* @param[in] nonce Pointer to the nonce data.
|
||||
*/
|
||||
void AES_setNonce(AES_ctx *const ctx, u8 orderEndianess, const u32 nonce[3]);
|
||||
|
||||
/**
|
||||
* @brief Copies the given counter/initialization vector into internal state.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] orderEndianess Word order and endianess bitmask.
|
||||
* @param[in] ctrIv Pointer to the counter/initialization vector data.
|
||||
*/
|
||||
void AES_setCtrIv(AES_ctx *const ctx, u8 orderEndianess, const u32 ctrIv[4]);
|
||||
|
||||
/**
|
||||
* @brief Increments the internal counter with the given value (CTR mode).
|
||||
*
|
||||
* @param ctr Pointer to the counter data.
|
||||
* @param[in] val Value to increment the counter with.
|
||||
*/
|
||||
void AES_addCounter(u32 ctr[4], u32 val);
|
||||
|
||||
/**
|
||||
* @brief Sets params in the AES context for all following crypto operations.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] inEndianessOrder Input endianess and word order bitmask.
|
||||
* @param[in] outEndianessOrder Output endianess and word order bitmask.
|
||||
*/
|
||||
void AES_setCryptParams(AES_ctx *const ctx, u8 inEndianessOrder, u8 outEndianessOrder);
|
||||
|
||||
/**
|
||||
* @brief En-/decrypts data with AES CTR.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] in In data pointer. Can be the same as out.
|
||||
* @param out Out data pointer. Can be the same as in.
|
||||
* @param[in] blocks Number of blocks to process. 1 block is 16 bytes.
|
||||
* @param[in] dma Set to true to enable DMA.
|
||||
*/
|
||||
void AES_ctr(AES_ctx *const ctx, const u32 *in, u32 *out, u32 blocks, bool dma);
|
||||
|
||||
/**
|
||||
* @brief En-/decrypts data with AES CBC.
|
||||
* @brief Note: With DMA the output buffer must be invalidated
|
||||
* @brief after this function, not before.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] in In data pointer. Can be the same as out.
|
||||
* @param out Out data pointer. Can be the same as in.
|
||||
* @param[in] blocks Number of blocks to process. 1 block is 16 bytes.
|
||||
* @param[in] enc Set to true to encrypt and false to decrypt.
|
||||
* @param[in] dma Set to true to enable DMA.
|
||||
*/
|
||||
//void AES_cbc(AES_ctx *const ctx, const u32 *in, u32 *out, u32 blocks, bool enc, bool dma);
|
||||
|
||||
/**
|
||||
* @brief En-/decrypts data with AES ECB.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] in In data pointer. Can be the same as out.
|
||||
* @param out Out data pointer. Can be the same as in.
|
||||
* @param[in] blocks Number of blocks to process. 1 block is 16 bytes.
|
||||
* @param[in] enc Set to true to encrypt and false to decrypt.
|
||||
* @param[in] dma Set to true to enable DMA.
|
||||
*/
|
||||
void AES_ecb(AES_ctx *const ctx, const u32 *in, u32 *out, u32 blocks, bool enc, bool dma);
|
||||
|
||||
/**
|
||||
* @brief En-/decrypts data with AES CCM.
|
||||
* @brief Note: The AES hardware implements this in a non-standard way
|
||||
* @brief limiting it to 1 nonce for 1 MB.
|
||||
*
|
||||
* @param ctx Pointer to AES_ctx (AES context).
|
||||
* @param[in] in In data pointer. Can be the same as out.
|
||||
* @param out Out data pointer. Can be the same as in.
|
||||
* @param[in] macSize The AES MAC size in bytes.
|
||||
* @param mac Pointer to in/out AES MAC. The MAC must/will be padded
|
||||
* with zeros (non-standard).
|
||||
* @param[in] blocks Number of blocks to process. 1 block is 16 bytes.
|
||||
* @param[in] enc Set to true to encrypt and false to decrypt.
|
||||
*
|
||||
* @return Returns true in decryption mode if the AES MAC is valid. Otherwise true.
|
||||
*/
|
||||
bool AES_ccm(const AES_ctx *const ctx, const u32 *const in, u32 *const out, u32 macSize,
|
||||
u32 mac[4], u16 blocks, bool enc);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// SHA //
|
||||
//////////////////////////////////
|
||||
|
||||
#define SHA_ENABLE (1u) // Also used as busy flag
|
||||
#define SHA_FINAL_ROUND (1u<<1)
|
||||
#define SHA_IN_DMA_ENABLE (1u<<2) // Without this NDMA startup is never fires
|
||||
#define SHA_INPUT_BIG (1u<<3)
|
||||
#define SHA_INPUT_LITTLE (0u)
|
||||
#define SHA_OUTPUT_BIG (SHA_INPUT_BIG)
|
||||
#define SHA_OUTPUT_LITTLE (SHA_INPUT_LITTLE)
|
||||
#define SHA_MODE_256 (0u)
|
||||
#define SHA_MODE_224 (1u<<4)
|
||||
#define SHA_MODE_1 (2u<<4)
|
||||
#define SHA_MODE_MASK (SHA_MODE_1 | SHA_MODE_224 | SHA_MODE_256)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets input mode, endianess and starts the hash operation.
|
||||
*
|
||||
* @param[in] params Mode and input endianess bitmask.
|
||||
*/
|
||||
void SHA_start(u8 params);
|
||||
|
||||
/**
|
||||
* @brief Hashes the data pointed to.
|
||||
*
|
||||
* @param[in] data Pointer to data to hash.
|
||||
* @param[in] size Size of the data to hash.
|
||||
*/
|
||||
void SHA_update(const u32 *data, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Generates the final hash.
|
||||
*
|
||||
* @param hash Pointer to memory to copy the hash to.
|
||||
* @param[in] endianess Endianess bitmask for the hash.
|
||||
*/
|
||||
void SHA_finish(u32 *const hash, u8 endianess);
|
||||
|
||||
/**
|
||||
* @brief Returns the current SHA engine state.
|
||||
*
|
||||
* @param out Pointer to memory to copy the state to.
|
||||
*/
|
||||
void SHA_getState(u32 *const out);
|
||||
|
||||
/**
|
||||
* @brief Hashes a single block of data and outputs the hash.
|
||||
*
|
||||
* @param[in] data Pointer to data to hash.
|
||||
* @param[in] size Size of the data to hash.
|
||||
* @param hash Pointer to memory to copy the hash to.
|
||||
* @param[in] params Mode and input endianess bitmask.
|
||||
* @param[in] hashEndianess Endianess bitmask for the hash.
|
||||
*/
|
||||
void sha(const u32 *data, u32 size, u32 *const hash, u8 params, u8 hashEndianess);
|
||||
|
||||
/**
|
||||
* @brief Hashes a single block of data with DMA and outputs the hash.
|
||||
* @brief Note: Not recommended. It's way slower than CPU based SHA.
|
||||
*
|
||||
* @param[in] data Pointer to data to hash.
|
||||
* @param[in] size Size of the data to hash. Must be 64 bytes aligned.
|
||||
* @param hash Pointer to memory to copy the hash to.
|
||||
* @param[in] params Mode and input endianess bitmask.
|
||||
* @param[in] hashEndianess Endianess bitmask for the hash.
|
||||
*/
|
||||
//void sha_dma(const u32 *data, u32 size, u32 *const hash, u8 params, u8 hashEndianess);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// RSA //
|
||||
//////////////////////////////////
|
||||
|
||||
// REG_RSA_CNT
|
||||
#define RSA_CNT_ENABLE (1u)
|
||||
#define RSA_CNT_IRQ_ENABLE (1u<<1)
|
||||
#define RSA_CNT_KEYSLOT_SHIFT (4u)
|
||||
#define RSA_CNT_KEYSLOT_MASK (3u<<RSA_CNT_KEYSLOT_SHIFT)
|
||||
#define RSA_CNT_INPUT_BIG (1u<<8)
|
||||
#define RSA_CNT_INPUT_LITTLE (0u)
|
||||
#define RSA_CNT_INPUT_NORMAL (1u<<9)
|
||||
#define RSA_CNT_INPUT_REVERSED (0u)
|
||||
#define RSA_CNT_INPUT_MASK (RSA_CNT_INPUT_NORMAL | RSA_CNT_INPUT_BIG)
|
||||
|
||||
// REG_RSA_SLOTCNT
|
||||
#define RSA_SLOTCNT_SET (1u)
|
||||
#define RSA_SLOTCNT_WR_PROT (1u<<1)
|
||||
#define RSA_SLOTCNT_BIT31 (1u<<31)
|
||||
|
||||
// REG_RSA_SLOTSIZE
|
||||
#define RSA_SLOTSIZE_2048 (0x40u)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the RSA hardware.
|
||||
*/
|
||||
void RSA_init(void);
|
||||
|
||||
/**
|
||||
* @brief Selects the given keyslot for all following RSA operations.
|
||||
*
|
||||
* @param[in] keyslot The keyslot to select.
|
||||
*/
|
||||
void RSA_selectKeyslot(u8 keyslot);
|
||||
|
||||
/**
|
||||
* @brief Sets a RSA modulus + exponent in the specified keyslot.
|
||||
*
|
||||
* @param[in] keyslot The keyslot this key will be set for.
|
||||
* @param[in] mod Pointer to 2048-bit RSA modulus data.
|
||||
* @param[in] exp The exponent to set.
|
||||
*
|
||||
* @return Returns true on success, false otherwise.
|
||||
*/
|
||||
bool RSA_setKey2048(u8 keyslot, const u32 *const mod, u32 exp);
|
||||
|
||||
/**
|
||||
* @brief Decrypts a RSA 2048 signature.
|
||||
*
|
||||
* @param decSig Pointer to decrypted destination signature.
|
||||
* @param[in] encSig Pointer to encrypted source signature.
|
||||
*
|
||||
* @return Returns true on success, false otherwise.
|
||||
*/
|
||||
bool RSA_decrypt2048(u32 *const decSig, const u32 *const encSig);
|
||||
|
||||
/**
|
||||
* @brief Verifies a RSA 2048 SHA 256 signature.
|
||||
* @brief Note: This function skips the ASN.1 data and is therefore not safe.
|
||||
*
|
||||
* @param[in] encSig Pointer to encrypted source signature.
|
||||
* @param[in] data Pointer to the data to hash.
|
||||
* @param[in] size The hash data size.
|
||||
*
|
||||
* @return Returns true if the signature is valid, false otherwise.
|
||||
*/
|
||||
bool RSA_verify2048(const u32 *const encSig, const u32 *const data, u32 size);
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This code is part of ctrulib (https://github.com/smealum/ctrulib)
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define HID_KEY_MASK_ALL ((KEY_Y << 1) - 1)
|
||||
#define HID_VERBOSE_MODE_BUTTONS (KEY_SELECT | KEY_START)
|
||||
|
||||
enum
|
||||
{
|
||||
KEY_A = 1u,
|
||||
KEY_B = 1u<<1,
|
||||
KEY_SELECT = 1u<<2,
|
||||
KEY_START = 1u<<3,
|
||||
KEY_DRIGHT = 1u<<4,
|
||||
KEY_DLEFT = 1u<<5,
|
||||
KEY_DUP = 1u<<6,
|
||||
KEY_DDOWN = 1u<<7,
|
||||
KEY_R = 1u<<8,
|
||||
KEY_L = 1u<<9,
|
||||
KEY_X = 1u<<10,
|
||||
KEY_Y = 1u<<11
|
||||
};
|
||||
|
||||
|
||||
|
||||
void hidScanInput(void);
|
||||
u32 hidKeysHeld(void);
|
||||
u32 hidKeysDown(void);
|
||||
u32 hidKeysUp(void);
|
|
@ -0,0 +1,99 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "arm.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IRQ_DMAC_1_0 = 0u, // DMAC_1 = NDMA
|
||||
IRQ_DMAC_1_1 = 1u,
|
||||
IRQ_DMAC_1_2 = 2u,
|
||||
IRQ_DMAC_1_3 = 3u,
|
||||
IRQ_DMAC_1_4 = 4u,
|
||||
IRQ_DMAC_1_5 = 5u,
|
||||
IRQ_DMAC_1_6 = 6u,
|
||||
IRQ_DMAC_1_7 = 7u,
|
||||
IRQ_TIMER_0 = 8u,
|
||||
IRQ_TIMER_1 = 9u,
|
||||
IRQ_TIMER_2 = 10u,
|
||||
IRQ_TIMER_3 = 11u,
|
||||
IRQ_PXI_SYNC = 12u,
|
||||
IRQ_PXI_NOT_FULL = 13u,
|
||||
IRQ_PXI_NOT_EMPTY = 14u,
|
||||
IRQ_AES = 15u,
|
||||
IRQ_SDIO_1 = 16u,
|
||||
IRQ_SDIO_1_ASYNC = 17u,
|
||||
IRQ_SDIO_3 = 18u,
|
||||
IRQ_SDIO_3_ASYNC = 19u,
|
||||
IRQ_DEBUG_RECV = 20u,
|
||||
IRQ_DEBUG_SEND = 21u,
|
||||
IRQ_RSA = 22u,
|
||||
IRQ_CTR_CARD_1 = 23u, // SPICARD and CTRCARD too?
|
||||
IRQ_CTR_CARD_2 = 24u,
|
||||
IRQ_CGC = 25u,
|
||||
IRQ_CGC_DET = 26u,
|
||||
IRQ_DS_CARD = 27u,
|
||||
IRQ_DMAC_2 = 28u,
|
||||
IRQ_DMAC_2_ABORT = 29u
|
||||
} Interrupt;
|
||||
|
||||
|
||||
// IRQ interrupt service routine type.
|
||||
// id: contains the interrupt ID
|
||||
typedef void (*IrqIsr)(u32 id);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes interrupts.
|
||||
*/
|
||||
void IRQ_init(void);
|
||||
|
||||
/**
|
||||
* @brief Registers a interrupt service routine and enables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <32.
|
||||
* @param[in] isr The interrupt service routine to call.
|
||||
*/
|
||||
void IRQ_registerIsr(Interrupt id, IrqIsr isr);
|
||||
|
||||
/**
|
||||
* @brief Unregisters the interrupt service routine and disables the specified interrupt.
|
||||
*
|
||||
* @param[in] id The interrupt ID. Must be <32.
|
||||
*/
|
||||
void IRQ_unregisterIsr(Interrupt id);
|
||||
|
||||
|
||||
#if !__thumb__
|
||||
static inline u32 enterCriticalSection(void)
|
||||
{
|
||||
u32 tmp;
|
||||
__setCpsr_c((tmp = __getCpsr()) | PSR_I);
|
||||
return tmp & PSR_I;
|
||||
}
|
||||
|
||||
static inline void leaveCriticalSection(u32 oldState)
|
||||
{
|
||||
__setCpsr_c((__getCpsr() & ~PSR_I) | oldState);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,189 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mem_map.h"
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
#define NDMA_REGS_BASE (IO_MEM_ARM9_ONLY + 0x2000)
|
||||
#define REG_NDMA_GLOBAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x00))
|
||||
|
||||
#define REG_NDMA0_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x04))
|
||||
#define REG_NDMA0_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x08))
|
||||
#define REG_NDMA0_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x0C)) // Total repeat length in words
|
||||
#define REG_NDMA0_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x10)) // Logical block size in words
|
||||
#define REG_NDMA0_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0x14)) // Timing/interval settings
|
||||
#define REG_NDMA0_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0x18))
|
||||
#define REG_NDMA0_CNT *((vu32*)(NDMA_REGS_BASE + 0x1C))
|
||||
|
||||
#define REG_NDMA1_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x20))
|
||||
#define REG_NDMA1_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x24))
|
||||
#define REG_NDMA1_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x28))
|
||||
#define REG_NDMA1_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x2C))
|
||||
#define REG_NDMA1_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0x30))
|
||||
#define REG_NDMA1_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0x34))
|
||||
#define REG_NDMA1_CNT *((vu32*)(NDMA_REGS_BASE + 0x38))
|
||||
|
||||
#define REG_NDMA2_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x3C))
|
||||
#define REG_NDMA2_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x40))
|
||||
#define REG_NDMA2_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x44))
|
||||
#define REG_NDMA2_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x48))
|
||||
#define REG_NDMA2_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0x4C))
|
||||
#define REG_NDMA2_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0x50))
|
||||
#define REG_NDMA2_CNT *((vu32*)(NDMA_REGS_BASE + 0x54))
|
||||
|
||||
#define REG_NDMA3_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x58))
|
||||
#define REG_NDMA3_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x5C))
|
||||
#define REG_NDMA3_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x60))
|
||||
#define REG_NDMA3_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x64))
|
||||
#define REG_NDMA3_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0x68))
|
||||
#define REG_NDMA3_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0x6C))
|
||||
#define REG_NDMA3_CNT *((vu32*)(NDMA_REGS_BASE + 0x70))
|
||||
|
||||
#define REG_NDMA4_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x74))
|
||||
#define REG_NDMA4_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x78))
|
||||
#define REG_NDMA4_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x7C))
|
||||
#define REG_NDMA4_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x80))
|
||||
#define REG_NDMA4_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0x84))
|
||||
#define REG_NDMA4_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0x88))
|
||||
#define REG_NDMA4_CNT *((vu32*)(NDMA_REGS_BASE + 0x8C))
|
||||
|
||||
#define REG_NDMA5_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0x90))
|
||||
#define REG_NDMA5_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0x94))
|
||||
#define REG_NDMA5_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0x98))
|
||||
#define REG_NDMA5_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0x9C))
|
||||
#define REG_NDMA5_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0xA0))
|
||||
#define REG_NDMA5_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0xA4))
|
||||
#define REG_NDMA5_CNT *((vu32*)(NDMA_REGS_BASE + 0xA8))
|
||||
|
||||
#define REG_NDMA6_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0xAC))
|
||||
#define REG_NDMA6_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0xB0))
|
||||
#define REG_NDMA6_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0xB4))
|
||||
#define REG_NDMA6_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0xB8))
|
||||
#define REG_NDMA6_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0xBC))
|
||||
#define REG_NDMA6_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0xC0))
|
||||
#define REG_NDMA6_CNT *((vu32*)(NDMA_REGS_BASE + 0xC4))
|
||||
|
||||
#define REG_NDMA7_SRC_ADDR *((vu32*)(NDMA_REGS_BASE + 0xC8))
|
||||
#define REG_NDMA7_DST_ADDR *((vu32*)(NDMA_REGS_BASE + 0xCC))
|
||||
#define REG_NDMA7_TOTAL_CNT *((vu32*)(NDMA_REGS_BASE + 0xD0))
|
||||
#define REG_NDMA7_LOG_BLK_CNT *((vu32*)(NDMA_REGS_BASE + 0xD4))
|
||||
#define REG_NDMA7_INT_CNT *((vu32*)(NDMA_REGS_BASE + 0xD8))
|
||||
#define REG_NDMA7_FILL_DATA *((vu32*)(NDMA_REGS_BASE + 0xDC))
|
||||
#define REG_NDMA7_CNT *((vu32*)(NDMA_REGS_BASE + 0xE0))
|
||||
|
||||
#define REG_NDMA_SRC_ADDR(n) *((vu32*)(NDMA_REGS_BASE + 0x04 + ((n) * 28)))
|
||||
#define REG_NDMA_DST_ADDR(n) *((vu32*)(NDMA_REGS_BASE + 0x08 + ((n) * 28)))
|
||||
#define REG_NDMA_TOTAL_CNT(n) *((vu32*)(NDMA_REGS_BASE + 0x0C + ((n) * 28)))
|
||||
#define REG_NDMA_LOG_BLK_CNT(n) *((vu32*)(NDMA_REGS_BASE + 0x10 + ((n) * 28)))
|
||||
#define REG_NDMA_INT_CNT(n) *((vu32*)(NDMA_REGS_BASE + 0x14 + ((n) * 28)))
|
||||
#define REG_NDMA_FILL_DATA(n) *((vu32*)(NDMA_REGS_BASE + 0x18 + ((n) * 28)))
|
||||
#define REG_NDMA_CNT(n) *((vu32*)(NDMA_REGS_BASE + 0x1C + ((n) * 28)))
|
||||
|
||||
|
||||
// REG_NDMA_GLOBAL_CNT
|
||||
#define NDMA_ROUND_ROBIN(n) (intLog2(n)<<16 | 1u<<31 | 1u) // n = number of CPU cycles
|
||||
#define NDMA_HIGHEST_PRIO (1u)
|
||||
|
||||
// REG_NDMA_INT_CNT
|
||||
#define NDMA_INT_SYS_FREQ (0u)
|
||||
|
||||
// REG_NDMA_CNT
|
||||
#define NDMA_DST_UPDATE_INC (0u)
|
||||
#define NDMA_DST_UPDATE_DEC (1u<<10)
|
||||
#define NDMA_DST_UPDATE_FIXED (2u<<10)
|
||||
#define NDMA_DST_ADDR_RELOAD (1u<<12) // Reloads on logical block end
|
||||
#define NDMA_SRC_UPDATE_INC (0u)
|
||||
#define NDMA_SRC_UPDATE_DEC (1u<<13)
|
||||
#define NDMA_SRC_UPDATE_FIXED (2u<<13)
|
||||
#define NDMA_SRC_UPDATE_FILL (3u<<13)
|
||||
#define NDMA_SRC_ADDR_RELOAD (1u<<15)
|
||||
// The block length is 2^n words (Example: 2^15 = 32768 words = 0x20000 bytes)
|
||||
#define NDMA_BURST_WORDS(n) (intLog2(n)<<16)
|
||||
#define NDMA_IMMEDIATE_MODE (16u<<24)
|
||||
#define NDMA_TOTAL_CNT_MODE (0u)
|
||||
#define NDMA_REPEATING_MODE (1u<<29)
|
||||
#define NDMA_IRQ_ENABLE (1u<<30)
|
||||
#define NDMA_ENABLE (1u<<31)
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
NDMA_STARTUP_TIMER0 = 0u<<24,
|
||||
NDMA_STARTUP_TIMER1 = 1u<<24,
|
||||
NDMA_STARTUP_TIMER2 = 2u<<24,
|
||||
NDMA_STARTUP_TIMER3 = 3u<<24,
|
||||
NDMA_STARTUP_CTRCARD0 = 4u<<24, // Fires with SPICARD aswell but seems to be broken.
|
||||
NDMA_STARTUP_CTRCARD1 = 5u<<24, // Fires with SPICARD aswell but seems to be broken.
|
||||
NDMA_STARTUP_MMC1 = 6u<<24,
|
||||
NDMA_STARTUP_MMC2 = 7u<<24, // Guess based on DSi documentation
|
||||
NDMA_STARTUP_AES_IN = 8u<<24, // AES write fifo
|
||||
NDMA_STARTUP_AES_OUT = 9u<<24, // AES read fifo
|
||||
NDMA_STARTUP_SHA_IN = 10u<<24,
|
||||
NDMA_STARTUP_SHA_OUT = 11u<<24, // For chaining
|
||||
NDMA_STARTUP_UNK_12 = 12u<<24,
|
||||
NDMA_STARTUP_UNK_13 = 13u<<24,
|
||||
NDMA_STARTUP_UNK_14 = 14u<<24,
|
||||
NDMA_STARTUP_MMC_AES_SHA = 15u<<24 // Unconfirmed
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes all NDMA channels.
|
||||
*/
|
||||
void NDMA_init(void);
|
||||
|
||||
/**
|
||||
* @brief Asynchronous copying of data using the NDMA engine.
|
||||
*
|
||||
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
||||
* @param source Pointer to source data. Must be 4 bytes aligned.
|
||||
* @param[in] size The size of the data. Must be multiple of 4.
|
||||
*/
|
||||
void NDMA_copyAsync(u32 *dest, const u32 *source, u32 num);
|
||||
|
||||
/**
|
||||
* @brief Copies data using the NDMA engine.
|
||||
*
|
||||
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
||||
* @param source Pointer to source data. Must be 4 bytes aligned.
|
||||
* @param[in] size The size of the data. Must be multiple of 4.
|
||||
*/
|
||||
void NDMA_copy(u32 *dest, const u32 *source, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Asynchronous memory fill with the given value using the NDMA engine.
|
||||
*
|
||||
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
||||
* @param[in] value The value each 32-bit word will be set to.
|
||||
* @param[in] size The size of the memory to fill. Must be multiple of 4.
|
||||
*/
|
||||
void NDMA_fillAsync(u32 *dest, u32 value, u32 size);
|
||||
|
||||
/**
|
||||
* @brief Fills memory with the given value using the NDMA engine.
|
||||
*
|
||||
* @param dest Pointer to destination memory. Must be 4 bytes aligned.
|
||||
* @param[in] value The value each 32-bit word will be set to.
|
||||
* @param[in] size The size of the memory to fill. Must be multiple of 4.
|
||||
*/
|
||||
void NDMA_fill(u32 *dest, u32 value, u32 size);
|
|
@ -0,0 +1,183 @@
|
|||
#ifndef __SDMMC_H__
|
||||
#define __SDMMC_H__
|
||||
|
||||
/*
|
||||
* 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-2015, 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 "types.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)
|
||||
|
||||
#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 {
|
||||
u8* rData;
|
||||
const u8* tData;
|
||||
u32 size;
|
||||
u32 error;
|
||||
u16 stat0;
|
||||
u16 stat1;
|
||||
u32 ret[4];
|
||||
u32 initarg;
|
||||
u32 isSDHC;
|
||||
u32 clk;
|
||||
u32 SDOPT;
|
||||
u32 devicenumber;
|
||||
u32 total_size; //size in sectors of the device
|
||||
u32 res;
|
||||
} mmcdevice;
|
||||
|
||||
void sdmmc_init();
|
||||
int sdmmc_sdcard_readsector(u32 sector_no, u8 *out);
|
||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
int sdmmc_sdcard_writesector(u32 sector_no, const u8 *in);
|
||||
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
|
||||
|
||||
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
|
||||
|
||||
int sdmmc_get_cid(bool isNand, u32 *info);
|
||||
|
||||
mmcdevice *getMMCDevice(int drive);
|
||||
|
||||
int Nand_Init();
|
||||
int SD_Init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline u16 sdmmc_read16(u16 reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(volatile u16*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write16(u16 reg, u16 val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(volatile u16*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline u32 sdmmc_read32(u16 reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(volatile u32*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write32(u16 reg, u32 val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(volatile u32*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
|
||||
//---------------------------------------------------------------------------------
|
||||
u16 val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
}
|
||||
|
||||
static inline void setckl(u32 data)
|
||||
{
|
||||
sdmmc_write16(REG_SDCLKCTL, data & 0xFF);
|
||||
sdmmc_write16(REG_SDCLKCTL, 1u<<8 | (data & 0x2FF));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,96 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
// REG_NSPI_CNT
|
||||
#define NSPI_BUS_1BIT (0u)
|
||||
#define NSPI_BUS_4BIT (1u<<12)
|
||||
#define NSPI_DIR_READ (0u)
|
||||
#define NSPI_DIR_WRITE (1u<<13)
|
||||
#define NSPI_ENABLE (1u<<15)
|
||||
|
||||
// REG_NSPI_CS
|
||||
#define NSPI_DESELECT (0u)
|
||||
|
||||
// NSPI_FIFO_STAT
|
||||
#define NSPI_FIFO_BUSY (1u)
|
||||
|
||||
// REG_NSPI_AUTOPOLL
|
||||
#define NSPI_AUTOPOLL_START (1u<<31)
|
||||
|
||||
// REG_NSPI_INT_MASK Bit set = disabled.
|
||||
// REG_NSPI_INT_STAT Status and aknowledge.
|
||||
#define NSPI_INT_TRANSF_END (1u) // Also fires on each auto poll try.
|
||||
#define NSPI_INT_AP_SUCCESS (1u<<1) // Auto poll
|
||||
#define NSPI_INT_AP_TIMEOUT (1u<<2) // Auto poll
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NSPI_CLK_512KHz = 0u,
|
||||
NSPI_CLK_1MHz = 1u,
|
||||
NSPI_CLK_2MHz = 2u,
|
||||
NSPI_CLK_4MHz = 3u,
|
||||
NSPI_CLK_8MHz = 4u,
|
||||
NSPI_CLK_16MHz = 5u
|
||||
} NspiClk;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the SPI buses. Call this only once.
|
||||
*/
|
||||
void SPICARD_init(void);
|
||||
|
||||
/**
|
||||
* @brief Automatically polls a bit of the command response. Use with the macro below.
|
||||
*
|
||||
* @param[in] params The parameters. Use the macro below.
|
||||
*
|
||||
* @return Returns false on failure/timeout and true on success.
|
||||
*/
|
||||
bool _SPICARD_autoPollBit(u32 params);
|
||||
|
||||
/**
|
||||
* @brief Writes and/or reads data to/from a SPI device.
|
||||
*
|
||||
* @param[in] clk The clock frequency to use.
|
||||
* @param[in] in Input data pointer for write.
|
||||
* @param out Output data pointer for read.
|
||||
* @param[in] inSize Input size. Must be <= 0x1FFFFF.
|
||||
* @param[in] outSize Output size. Must be <= 0x1FFFFF.
|
||||
* @param[in] done Set to true if this is the last transfer (chip select).
|
||||
*/
|
||||
void SPICARD_writeRead(NspiClk clk, const u32 *in, u32 *out, u32 inSize, u32 outSize, bool done);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Automatically polls a bit of the command response.
|
||||
*
|
||||
* @param[in] cmd The command.
|
||||
* @param[in] timeout The timeout. Must be 0-15. Tries = 31<<NspiClk + timeout.
|
||||
* @param[in] off The bit offset. Must be 0-7.
|
||||
* @param[in] bitSet Poll for a set ur unset bit.
|
||||
*
|
||||
* @return Returns false on failure/timeout and true on success.
|
||||
*/
|
||||
#define SPICARD_autoPollBit(cmd, timeout, off, bitSet) _SPICARD_autoPollBit((bitSet)<<30 | (off)<<24 | (timeout)<<16 | (cmd))
|
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define TIMER_BASE_FREQ (67027964)
|
||||
|
||||
#define TIMER_COUNT_UP (1u<<2) // For cascading at least 2 timers
|
||||
#define TIMER_IRQ_ENABLE (1u<<6)
|
||||
#define TIMER_ENABLE (1u<<7)
|
||||
|
||||
// Convenience macros for calculating the ticks. Based on libnds
|
||||
#define TIMER_FREQ(n) (-TIMER_BASE_FREQ / (n))
|
||||
#define TIMER_FREQ_64(n) (-(TIMER_BASE_FREQ / 64) / (n))
|
||||
#define TIMER_FREQ_256(n) (-(TIMER_BASE_FREQ / 256) / (n))
|
||||
#define TIMER_FREQ_1024(n) (-(TIMER_BASE_FREQ / 1024) / (n))
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TIMER_0 = 0u,
|
||||
TIMER_1 = 1u,
|
||||
TIMER_2 = 2u,
|
||||
TIMER_3 = 3u
|
||||
} Timer;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TIMER_PRESCALER_1 = 0u,
|
||||
TIMER_PRESCALER_64 = 1u,
|
||||
TIMER_PRESCALER_256 = 2u,
|
||||
TIMER_PRESCALER_1024 = 3u
|
||||
} TimerPrescaler;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Resets/initializes the timer hardware. Should not be called manually.
|
||||
*/
|
||||
void TIMER_init(void);
|
||||
|
||||
/**
|
||||
* @brief Starts a timer.
|
||||
*
|
||||
* @param[in] timer The timer to start.
|
||||
* @param[in] prescaler The prescaler to use.
|
||||
* @param[in] ticks The initial number of ticks. This is also the reload
|
||||
* value on overflow.
|
||||
* @param[in] enableIrq Timer fires IRQs if true.
|
||||
*/
|
||||
void TIMER_start(Timer timer, TimerPrescaler prescaler, u16 ticks, bool enableIrq);
|
||||
|
||||
/**
|
||||
* @brief Returns the current number of ticks of the timer.
|
||||
*
|
||||
* @param[in] timer The timer get the ticks from.
|
||||
*
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
u16 TIMER_getTicks(Timer timer);
|
||||
|
||||
/**
|
||||
* @brief Stops a timer and returns the current number of ticks.
|
||||
*
|
||||
* @param[in] timer The timer to stop.
|
||||
*
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
u16 TIMER_stop(Timer timer);
|
||||
|
||||
/**
|
||||
* @brief Halts the CPU for the specified number of milliseconds.
|
||||
*
|
||||
* @param[in] ms The number of milliseconds to sleep.
|
||||
*/
|
||||
void TIMER_sleep(u32 ms);
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2022 spitzeqc
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,15 +18,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result patchRom(const char *const gamePath, u32 *romSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
void deinitCpu(void);
|
|
@ -0,0 +1,265 @@
|
|||
#pragma once
|
||||
|
||||
// Based on: https://github.com/ARM-software/CMSIS_5/blob/master/CMSIS/Core/Include/cmsis_gcc.h
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
// u32 result, u32 op1.
|
||||
#define MAKE_INTR_U32_1OP(isVolatile, inst) \
|
||||
ALWAYS_INLINE u32 __##inst(u32 op1) \
|
||||
{ \
|
||||
u32 res; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1" : "=r" (res) : "r" (op1) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1" : "=r" (res) : "r" (op1) : ); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
// u32 result, u32 op1, u32 op2.
|
||||
#define MAKE_INTR_U32_2OPS(isVolatile, inst) \
|
||||
ALWAYS_INLINE u32 __##inst(u32 op1, u32 op2) \
|
||||
{ \
|
||||
u32 res; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2" : "=r" (res) : "r" (op1), "r" (op2) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2" : "=r" (res) : "r" (op1), "r" (op2) : ); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
// s32 result, s32 op1, s32 op2.
|
||||
#define MAKE_INTR_S32_2OPS(isVolatile, inst) \
|
||||
ALWAYS_INLINE s32 __##inst(s32 op1, s32 op2) \
|
||||
{ \
|
||||
s32 res; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2" : "=r" (res) : "r" (op1), "r" (op2) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2" : "=r" (res) : "r" (op1), "r" (op2) : ); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
// u32 result, u32 op1, u32 op2, u32 op3.
|
||||
#define MAKE_INTR_U32_3OPS(isVolatile, inst) \
|
||||
ALWAYS_INLINE u32 __##inst(u32 op1, u32 op2, u32 op3) \
|
||||
{ \
|
||||
u32 res; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2, %3" : "=r" (res) : "r" (op1), "r" (op2), "r" (op3) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2, %3" : "=r" (res) : "r" (op1), "r" (op2), "r" (op3) : ); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
// s32 result, s32 op1, s32 op2, s32 op3.
|
||||
#define MAKE_INTR_S32_3OPS(isVolatile, inst) \
|
||||
ALWAYS_INLINE s32 __##inst(s32 op1, s32 op2, s32 op3) \
|
||||
{ \
|
||||
s32 res; \
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2, %3" : "=r" (res) : "r" (op1), "r" (op2), "r" (op3) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2, %3" : "=r" (res) : "r" (op1), "r" (op2), "r" (op3) : ); \
|
||||
return res; \
|
||||
}
|
||||
|
||||
#ifndef __ARMEB__ // Little endian
|
||||
// Special instruction with shared u64 input and output.
|
||||
// u64 result, u32 op1, u32 op2, u64 acc.
|
||||
#define MAKE_INTR_U64_U32_U32_U64(isVolatile, inst) \
|
||||
ALWAYS_INLINE u64 __##inst(u32 op1, u32 op2, u64 acc) \
|
||||
{ \
|
||||
union \
|
||||
{ \
|
||||
u32 r32[2]; \
|
||||
u64 r64; \
|
||||
} r; \
|
||||
r.r64 = acc; \
|
||||
\
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2, %3" : "=r" (r.r32[0]), "=r" (r.r32[1]) : "r" (op1), "r" (op2), "0" (r.r32[0]), "1" (r.r32[1]) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2, %3" : "=r" (r.r32[0]), "=r" (r.r32[1]) : "r" (op1), "r" (op2), "0" (r.r32[0]), "1" (r.r32[1]) : ); \
|
||||
\
|
||||
return r.r64; \
|
||||
}
|
||||
|
||||
#else // Big endian
|
||||
|
||||
// Special instruction with shared u64 input and output.
|
||||
// u64 result, u32 op1, u32 op2, u64 acc.
|
||||
#define MAKE_INTR_U64_U32_U32_U64(isVolatile, inst) \
|
||||
ALWAYS_INLINE u64 __##inst(u32 op1, u32 op2, u64 acc) \
|
||||
{ \
|
||||
union \
|
||||
{ \
|
||||
u32 r32[2]; \
|
||||
u64 r64; \
|
||||
} r; \
|
||||
r.r64 = acc; \
|
||||
\
|
||||
if(isVolatile == 1) \
|
||||
__asm__ volatile(#inst " %0, %1, %2, %3" : "=r" (r.r32[1]), "=r" (r.r32[0]) : "r" (op1), "r" (op2), "0" (r.r32[1]), "1" (r.r32[0]) : ); \
|
||||
else \
|
||||
__asm__(#inst " %0, %1, %2, %3" : "=r" (r.r32[1]), "=r" (r.r32[0]) : "r" (op1), "r" (op2), "0" (r.r32[1]), "1" (r.r32[0]) : ); \
|
||||
\
|
||||
return r.r64; \
|
||||
}
|
||||
#endif // #ifndef __ARMEB__
|
||||
|
||||
|
||||
|
||||
// Pack Halfword Bottom Top.
|
||||
#define __pkhbt(op1, op2, sh) \
|
||||
({ \
|
||||
u32 __res; \
|
||||
__asm__("pkhbt %0, %1, %2, lsl %3" : "=r" (__res) : "r" (op1), "r" (op2), "I" (sh) : ); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
// Pack Halfword Top Bottom.
|
||||
#define __pkhtb(op1, op2, sh) \
|
||||
({ \
|
||||
u32 __res, __sh = (sh); \
|
||||
if(__sh == 0) \
|
||||
__asm__("pkhtb %0, %1, %2" : "=r" (__res) : "r" (op1), "r" (op2) : ); \
|
||||
else \
|
||||
__asm__("pkhtb %0, %1, %2, asr %3" : "=r" (__res) : "r" (op1), "r" (op2), "I" (__sh) : ); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
MAKE_INTR_S32_2OPS(1, qadd) // Signed saturating addition.
|
||||
MAKE_INTR_U32_2OPS(0, qadd8) // Signed saturating parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, qadd16) // Signed saturating parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, qasx) // Signed saturating parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_S32_2OPS(1, qdadd) // Signed saturating Double and Add.
|
||||
MAKE_INTR_S32_2OPS(1, qdsub) // Signed saturating Double and Subtract.
|
||||
MAKE_INTR_U32_2OPS(0, qsax) // Signed saturating parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_S32_2OPS(1, qsub) // Signed saturating Subtract.
|
||||
MAKE_INTR_U32_2OPS(0, qsub8) // Signed saturating parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, qsub16) // Signed saturating parallel halfword-wise subtraction.
|
||||
MAKE_INTR_U32_1OP(0, rev) // Reverse the byte order in a word.
|
||||
MAKE_INTR_U32_1OP(0, rev16) // Reverse the byte order in each halfword independently.
|
||||
MAKE_INTR_U32_1OP(0, revsh) // Reverse the byte order in the bottom halfword, and sign extend to 32 bits.
|
||||
MAKE_INTR_U32_2OPS(1, sadd8) // Signed parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(1, sadd16) // Signed parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(1, sasx) // Signed parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(1, sel) // Select bytes from each operand according to the state of the APSR GE flags.
|
||||
MAKE_INTR_U32_2OPS(0, shadd8) // Signed halving parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, shadd16) // Signed halving parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, shasx) // Signed halving parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, shsax) // Signed halving parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, shsub8) // Signed halving parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, shsub16) // Signed halving parallel halfword-wise subtraction.
|
||||
MAKE_INTR_U32_3OPS(1, smlabb) // Signed Multiply Accumulate, with 16-bit operands (bottom, bottom) and a 32-bit result and accumulator.
|
||||
MAKE_INTR_U32_3OPS(1, smlabt) // Signed Multiply Accumulate, with 16-bit operands (bottom, top) and a 32-bit result and accumulator.
|
||||
MAKE_INTR_U32_3OPS(1, smlatb) // Signed Multiply Accumulate, with 16-bit operands (top, bottom) and a 32-bit result and accumulator.
|
||||
MAKE_INTR_U32_3OPS(1, smlatt) // Signed Multiply Accumulate, with 16-bit operands (top, top) and a 32-bit result and accumulator.
|
||||
MAKE_INTR_U32_3OPS(0, smlad) // Dual 16-bit Signed Multiply with Addition of products and 32-bit accumulation.
|
||||
MAKE_INTR_U32_3OPS(0, smladx) // Dual 16-bit Signed exchange Multiply with Addition of products and 32-bit accumulation.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlal) // Signed Long Multiply, with optional Accumulate, with 32-bit operands, and 64-bit result and accumulator.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlald) // Dual 16-bit Signed Multiply with Addition of products and 64-bit Accumulation.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlaldx) // Dual 16-bit Signed exchange Multiply with Addition of products and 64-bit Accumulation.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlalbb) // Signed Multiply-Accumulate with 16-bit operands (bottom, bottom) and a 64-bit accumulator.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlalbt) // Signed Multiply-Accumulate with 16-bit operands (bottom, top) and a 64-bit accumulator.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlaltb) // Signed Multiply-Accumulate with 16-bit operands (top, bottom) and a 64-bit accumulator.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlaltt) // Signed Multiply-Accumulate with 16-bit operands (top, top) and a 64-bit accumulator.
|
||||
MAKE_INTR_U32_3OPS(1, smlawb) // Signed Multiply-Accumulate Wide, with one 32-bit operand and one 16-bit operand (bottom half), and a 32-bit accumulate value, providing the top 32 bits of the result.
|
||||
MAKE_INTR_U32_3OPS(1, smlawt) // Signed Multiply-Accumulate Wide, with one 32-bit operand and one 16-bit operand (top half), and a 32-bit accumulate value, providing the top 32 bits of the result.
|
||||
MAKE_INTR_U32_3OPS(0, smlsd) // Dual 16-bit Signed Multiply with Subtraction of products and 32-bit accumulation.
|
||||
MAKE_INTR_U32_3OPS(0, smlsdx) // Dual 16-bit Signed exchange Multiply with Subtraction of products and 32-bit accumulation.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlsld) // Dual 16-bit Signed Multiply with Subtraction of products and 64-bit Accumulation.
|
||||
MAKE_INTR_U64_U32_U32_U64(0, smlsldx) // Dual 16-bit Signed exchange Multiply with Subtraction of products and 64-bit Accumulation.
|
||||
MAKE_INTR_S32_3OPS(0, smmla) // Signed Most significant word Multiply with Accumulation.
|
||||
MAKE_INTR_S32_3OPS(0, smmlar) // Signed Most significant word Multiply with Accumulation and rounding.
|
||||
MAKE_INTR_S32_3OPS(0, smmls) // Signed Most significant word Multiply with Subtraction.
|
||||
MAKE_INTR_S32_2OPS(0, smmlsr) // Signed Most significant word Multiply with Subtraction and rounding.
|
||||
MAKE_INTR_S32_2OPS(0, smmul) // Signed Most significant word Multiply.
|
||||
MAKE_INTR_S32_2OPS(0, smmulr) // Signed Most significant word Multiply and round.
|
||||
MAKE_INTR_U32_2OPS(1, smuad) // Dual 16-bit Signed Multiply with Addition of products.
|
||||
MAKE_INTR_U32_2OPS(1, smuadx) // Dual 16-bit Signed Multiply with Addition of products with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, smulbb) // Signed Multiply, with 16-bit operands (bottom, bottom) and a 32-bit result.
|
||||
MAKE_INTR_U32_2OPS(0, smulbt) // Signed Multiply, with 16-bit operands (bottom, top) and a 32-bit result.
|
||||
MAKE_INTR_U32_2OPS(0, smultb) // Signed Multiply, with 16-bit operands (top, bottom) and a 32-bit result.
|
||||
MAKE_INTR_U32_2OPS(0, smultt) // Signed Multiply, with 16-bit operands (top, top) and a 32-bit result.
|
||||
// TODO: smull // Signed Long Multiply, with 32-bit operands and 64-bit result.
|
||||
MAKE_INTR_U32_2OPS(0, smulwb) // Signed Multiply Wide, with one 32-bit and one 16-bit operand (bottom half), providing the top 32 bits of the result.
|
||||
MAKE_INTR_U32_2OPS(0, smulwt) // Signed Multiply Wide, with one 32-bit and one 16-bit operand (top half), providing the top 32 bits of the result.
|
||||
/* Doesn't affect any flags? */ MAKE_INTR_U32_2OPS(0, smusd) // Dual 16-bit Signed Multiply with Subtraction of products.
|
||||
/* Doesn't affect any flags? */ MAKE_INTR_U32_2OPS(0, smusdx) // Dual 16-bit Signed Multiply with Subtraction of products with exchange.
|
||||
|
||||
// Signed Saturate to any bit position, with optional shift before saturating.
|
||||
#define __ssat(op1, op2) \
|
||||
({ \
|
||||
s32 __res; \
|
||||
__asm__ volatile("ssat %0, %1, %2" : "=r" (__res) : "I" (op1), "r" (op2) : "cc"); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
// Parallel halfword Saturate.
|
||||
#define __ssat16(op1, op2) \
|
||||
({ \
|
||||
u32 __res; \
|
||||
__asm__ volatile("ssat16 %0, %1, %2" : "=r" (__res) : "I" (op1), "r" (op2) : "cc"); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
MAKE_INTR_U32_2OPS(1, ssax) // Signed parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(1, ssub8) // Signed parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(1, ssub16) // Signed parallel halfword-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, sxtab) // Sign extend Byte with Add, to extend an 8-bit value to a 32-bit value.
|
||||
MAKE_INTR_U32_2OPS(0, sxtab16) // Sign extend two Bytes with Add, to extend two 8-bit values to two 16-bit values.
|
||||
MAKE_INTR_U32_2OPS(0, sxtah) // Sign extend Halfword with Add, to extend a 16-bit value to a 32-bit value.
|
||||
MAKE_INTR_U32_1OP(0, sxtb) // Sign extend Byte, to extend an 8-bit value to a 32-bit value.
|
||||
MAKE_INTR_U32_1OP(0, sxtb16) // Sign extend two bytes.
|
||||
MAKE_INTR_U32_1OP(0, sxth) // Sign extend Halfword.
|
||||
MAKE_INTR_U32_2OPS(1, uadd8) // Unsigned parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(1, uadd16) // Unsigned parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(1, uasx) // Unsigned parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, uhadd8) // Unsigned halving parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, uhadd16) // Unsigned halving parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, uhasx) // Unsigned halving parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, uhsax) // Unsigned halving parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, uhsub8) // Unsigned halving parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, uhsub16) // Unsigned halving parallel halfword-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, uqadd8) // Unsigned saturating parallel byte-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, uqadd16) // Unsigned saturating parallel halfword-wise addition.
|
||||
MAKE_INTR_U32_2OPS(0, uqasx) // Unsigned saturating parallel add and subtract halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, uqsax) // Unsigned saturating parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(0, uqsub8) // Unsigned saturating parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, uqsub16) // Unsigned saturating parallel halfword-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(0, usad8) // Unsigned Sum of Absolute Differences.
|
||||
MAKE_INTR_U32_3OPS(0, usada8) // Unsigned Sum of Absolute Differences and Accumulate.
|
||||
|
||||
// Unsigned Saturate to any bit position, with optional shift before saturating.
|
||||
#define __usat(op1, op2) \
|
||||
({ \
|
||||
u32 __res; \
|
||||
__asm__ volatile("usat %0, %1, %2" : "=r" (__res) : "I" (op1), "r" (op2) : "cc"); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
// Parallel halfword Saturate.
|
||||
#define __usat16(op1, op2) \
|
||||
({ \
|
||||
u32 __res; \
|
||||
__asm__ volatile("usat16 %0, %1, %2" : "=r" (__res) : "I" (op1), "r" (op2) : "cc"); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
MAKE_INTR_U32_2OPS(1, usax) // Unsigned parallel subtract and add halfwords with exchange.
|
||||
MAKE_INTR_U32_2OPS(1, usub8) // Unsigned parallel byte-wise subtraction.
|
||||
MAKE_INTR_U32_2OPS(1, usub16) // Unsigned parallel halfword-wise subtraction.
|
||||
//MAKE_INTR_U32_2OPS(0, uxtab) // Zero extend Byte and Add.
|
||||
MAKE_INTR_U32_2OPS(0, uxtab16) // Zero extend two Bytes and Add.
|
||||
//MAKE_INTR_U32_2OPS(0, uxtah) // Zero extend Halfword and Add.
|
||||
//MAKE_INTR_U32_1OP(0, uxtb) // Zero extend Byte.
|
||||
MAKE_INTR_U32_1OP(0, uxtb16) // Zero extend two Bytes.
|
||||
//MAKE_INTR_U32_1OP(0, uxth) // Zero extend Halfword.
|
||||
|
||||
|
||||
#undef MAKE_INTR_U32_1OP
|
||||
#undef MAKE_INTR_U32_2OPS
|
||||
#undef MAKE_INTR_U32_3OPS
|
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
#error Only include this in assembly files!
|
||||
#endif
|
||||
|
||||
|
||||
.macro BEGIN_ASM_FUNC name, type=arm, linkage=global, section=text
|
||||
.section .\section\().\name, "ax", %progbits
|
||||
.if \type == thumb
|
||||
.align 1
|
||||
.thumb
|
||||
.else
|
||||
.align 2
|
||||
.arm
|
||||
.endif
|
||||
.\linkage \name
|
||||
.type \name, %function
|
||||
.func \name
|
||||
.cfi_sections .debug_frame
|
||||
.cfi_startproc
|
||||
\name:
|
||||
.endm
|
||||
|
||||
.macro END_ASM_FUNC
|
||||
.cfi_endproc
|
||||
.endfunc
|
||||
.endm
|
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define CUSTOM_ERR_OFFSET (200u)
|
||||
#define MAKE_CUSTOM_ERR(e) (CUSTOM_ERR_OFFSET + (e))
|
||||
|
||||
typedef u32 Result;
|
||||
|
||||
// Keep errors in the range of 0-255.
|
||||
enum
|
||||
{
|
||||
// Common errors.
|
||||
RES_OK = 0u,
|
||||
RES_SD_CARD_REMOVED = 1u,
|
||||
RES_DISK_FULL = 2u,
|
||||
RES_INVALID_ARG = 3u,
|
||||
RES_OUT_OF_MEM = 4u,
|
||||
RES_OUT_OF_RANGE = 5u,
|
||||
RES_NOT_FOUND = 6u,
|
||||
|
||||
// fatfs errors.
|
||||
// Caution: Update fres2Res() in fs.c on ARM9 if this changes!
|
||||
RES_FR_DISK_ERR = 7u, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
RES_FR_INT_ERR = 8u, /* (2) Assertion failed */
|
||||
RES_FR_NOT_READY = 9u, /* (3) The physical drive cannot work */
|
||||
RES_FR_NO_FILE = 10u, /* (4) Could not find the file */
|
||||
RES_FR_NO_PATH = 11u, /* (5) Could not find the path */
|
||||
RES_FR_INVALID_NAME = 12u, /* (6) The path name format is invalid */
|
||||
RES_FR_DENIED = 13u, /* (7) Access denied due to prohibited access or directory full */
|
||||
RES_FR_EXIST = 14u, /* (8) Access denied due to prohibited access */
|
||||
RES_FR_INVALID_OBJECT = 15u, /* (9) The file/directory object is invalid */
|
||||
RES_FR_WRITE_PROTECTED = 16u, /* (10) The physical drive is write protected */
|
||||
RES_FR_INVALID_DRIVE = 17u, /* (11) The logical drive number is invalid */
|
||||
RES_FR_NOT_ENABLED = 18u, /* (12) The volume has no work area */
|
||||
RES_FR_NO_FILESYSTEM = 19u, /* (13) There is no valid FAT volume */
|
||||
RES_FR_MKFS_ABORTED = 20u, /* (14) The f_mkfs() aborted due to any problem */
|
||||
RES_FR_TIMEOUT = 21u, /* (15) Could not get a grant to access the volume within defined period */
|
||||
RES_FR_LOCKED = 22u, /* (16) The operation is rejected according to the file sharing policy */
|
||||
RES_FR_NOT_ENOUGH_CORE = 23u, /* (17) LFN working buffer could not be allocated */
|
||||
RES_FR_TOO_MANY_OPEN_FILES = 24u, /* (18) Number of open files > FF_FS_LOCK */
|
||||
RES_FR_INVALID_PARAMETER = 25u, /* (19) Given parameter is invalid */
|
||||
|
||||
// Custom errors.
|
||||
RES_ROM_TOO_BIG = MAKE_CUSTOM_ERR(0),
|
||||
RES_GBA_RTC_ERR = MAKE_CUSTOM_ERR(1)
|
||||
};
|
||||
|
||||
#undef MAKE_CUSTOM_ERR
|
||||
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
void printError(Result res);
|
||||
void printErrorWaitInput(Result res, u32 waitKeys);
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define fb_assert(c) ((void)0)
|
||||
#else
|
||||
#define fb_assert(c) ((c) ? ((void)0) : __fb_assert(#c ", " __FILE__, __LINE__))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
noreturn void __fb_assert(const char *const str, u32 line);
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "error_codes.h"
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
|
||||
#define FS_MAX_DRIVES (FF_VOLUMES)
|
||||
#define FS_DRIVE_NAMES "sdmc:/"
|
||||
#define FS_MAX_FILES (1u)
|
||||
#define FS_MAX_DIRS (1u)
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FS_DRIVE_SDMC = 0u
|
||||
} FsDrive;
|
||||
|
||||
typedef u32 FHandle;
|
||||
typedef u32 DHandle;
|
||||
|
||||
|
||||
|
||||
Result fMount(FsDrive drive);
|
||||
Result fUnmount(FsDrive drive);
|
||||
Result fGetFree(FsDrive drive, u64 *const size);
|
||||
Result fOpen(FHandle *const hOut, const char *const path, u8 mode);
|
||||
Result fRead(FHandle h, void *const buf, u32 size, u32 *const bytesRead);
|
||||
Result fWrite(FHandle h, const void *const buf, u32 size, u32 *const bytesWritten);
|
||||
Result fSync(FHandle h);
|
||||
Result fLseek(FHandle h, u32 off);
|
||||
u32 fTell(FHandle h);
|
||||
u32 fSize(FHandle h);
|
||||
Result fClose(FHandle h);
|
||||
Result fStat(const char *const path, FILINFO *const fi);
|
||||
Result fChdir(const char *const path);
|
||||
Result fOpenDir(DHandle *const hOut, const char *const path);
|
||||
Result fReadDir(DHandle h, FILINFO *const fi, u32 num, u32 *const entriesRead);
|
||||
Result fCloseDir(DHandle h);
|
||||
Result fMkdir(const char *const path);
|
||||
Result fRename(const char *const old, const char *const _new);
|
||||
Result fUnlink(const char *const path);
|
||||
|
||||
#ifdef ARM9
|
||||
void fsDeinit(void);
|
||||
#endif // ifdef ARM9
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2020 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "error_codes.h"
|
||||
|
||||
|
||||
|
||||
Result fsQuickRead(const char *const path, void *const buf, u32 size);
|
||||
Result fsQuickWrite(const char *const path, const void *const buf, u32 size);
|
||||
Result fsMakePath(const char *const path);
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
void invalidateICache(void);
|
||||
void invalidateICacheRange(const void *base, u32 size);
|
||||
void cleanDCache(void);
|
||||
void flushDCache(void);
|
||||
void cleanDCacheRange(const void *base, u32 size);
|
||||
void flushDCacheRange(const void *base, u32 size);
|
||||
void invalidateDCache(void);
|
||||
void invalidateDCacheRange(const void *base, u32 size);
|
|
@ -0,0 +1,152 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
// REG_DMA330_DSR
|
||||
#define DSR_WAKE_EVNT_SHIFT (4u)
|
||||
#define DSR_WAKE_EVNT_MASK (0x1Fu<<DSR_WAKEUP_EVNT_SHIFT)
|
||||
#define DSR_DNS (1u<<9) // DMA Manager is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
DSR_STAT_STOPPED = 0u,
|
||||
DSR_STAT_EXECUTING = 1u,
|
||||
DSR_STAT_CACHE_MISS = 2u,
|
||||
DSR_STAT_UPDATING_PC = 3u, // Updating program counter.
|
||||
DSR_STAT_WFE = 4u, // Waiting for event.
|
||||
DSR_STAT_FAULTING = 15u,
|
||||
|
||||
DSR_STAT_MASK = DSR_STAT_FAULTING
|
||||
};
|
||||
|
||||
// REG_DMA330_INTEN
|
||||
#define INTEN_SEL_IRQ(n) (1u<<(n)) // Select IRQ instead of event.
|
||||
|
||||
// REG_DMA330_INT_EVENT_RIS
|
||||
#define INT_EVENT_RIS_ACTIVE(n) (1u<<(n)) // Interrupt or event N is active.
|
||||
|
||||
// REG_DMA330_INTMIS
|
||||
#define INTMIS_IRQ_ACTIVE(n) (1u<<(n)) // Interrupt N is active.
|
||||
|
||||
// REG_DMA330_INTCLR
|
||||
#define INTCLR_IRQ_CLR(n) (1u<<(n)) // Clear interrupt N.
|
||||
|
||||
// REG_DMA330_FSRD
|
||||
#define FSRD_FAULTING (1u) // DMA manager is in faulting state.
|
||||
|
||||
// REG_DMA330_FSRC
|
||||
#define FSRC_FAULTING(n) (1u<<(n)) // DMA channel is in faulting or faulting completing state.
|
||||
|
||||
// REG_DMA330_FTRD
|
||||
#define FTRD_UNDEF_INSTR (1u)
|
||||
#define FTRD_OPERAND_INVALID (1u<<1)
|
||||
#define FTRD_DMAGO_ERR (1u<<4) // Starting a secure channel from a non-secure state.
|
||||
#define FTRD_MGR_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTRD_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTRD_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
|
||||
// REG_DMA330_FTR0-7
|
||||
#define FTR_UNDEF_INSTR (1u)
|
||||
#define FTR_OPERAND_INVALID (1u<<1)
|
||||
#define FTR_CH_EVNT_ERR (1u<<5) // Waiting for or creating secure events/interrupts in no-secure state.
|
||||
#define FTR_CH_PERIPH_ERR (1u<<6) // Accessing secure periphals in non-secure state (DMAWFP, DMALDP, DMASTP, DMAFLUSHP).
|
||||
#define FTR_CH_RDWR_ERR (1u<<7) // Secure read or write in non-secure state.
|
||||
#define FTR_CH_MFIFO_ERR (1u<<12) // MFIFO too small to hold or store the data (DMALD, DMAST).
|
||||
#define FTR_CH_ST_DATA_UNAVAIL (1u<<13) // Not enough data in the MFIFO for DMAST to complete.
|
||||
#define FTR_INSTR_FETCH_ERR (1u<<16)
|
||||
#define FTR_DATA_WRITE_ERR (1u<<17)
|
||||
#define FTR_DATA_READ_ERR (1u<<18)
|
||||
#define FTR_DBG_INSTR (1u<<30) // The erroneous instruction came from the debug interface.
|
||||
#define FTR_LOCKUP_ERR (1u<<31) // Channel locked up because of resource starvation.
|
||||
|
||||
// REG_DMA330_CSR0-7
|
||||
#define CSR_WAKE_EVNT_SHIFT (4u)
|
||||
#define CSR_WAKE_EVNT_MASK (0x1Fu<<CSR_WAKEUP_EVNT_SHIFT)
|
||||
#define CSR_DMAWFP_B_NS (1u<<14) // DMAWFP executed with burst operand set.
|
||||
#define CSR_DMAWFP_PERIPH (1u<<15) // DMAWFP executed with periph operand set.
|
||||
#define CSR_CNS (1u<<21) // DMA channel is non-secure.
|
||||
|
||||
enum
|
||||
{
|
||||
CSR_STAT_STOPPED = 0u,
|
||||
CSR_STAT_EXECUTING = 1u,
|
||||
CSR_STAT_CACHE_MISS = 2u,
|
||||
CSR_STAT_UPDATING_PC = 3u, // Updating program counter.
|
||||
CSR_STAT_WFE = 4u, // Waiting for event.
|
||||
CSR_STAT_AT_BARRIER = 5u,
|
||||
CSR_STAT_WFP = 7u, // Waiting for periphal.
|
||||
CSR_STAT_KILLING = 8u,
|
||||
CSR_STAT_COMPLETING = 9u,
|
||||
CSR_STAT_FAULTING_COMPLETING = 14u,
|
||||
CSR_STAT_FAULTING = 15u,
|
||||
|
||||
CSR_STAT_MASK = CSR_STAT_FAULTING
|
||||
};
|
||||
|
||||
// REG_DMA330_CCR0-7
|
||||
#define CCR_SRC_INC (1u)
|
||||
#define CCR_SRC_BURST_SIZE_SHIFT (1u)
|
||||
#define CCR_SRC_BURST_SIZE_MASK (0x7u<<CCR_SRC_BURST_SIZE_SHIFT)
|
||||
#define CCR_SRC_BURST_LEN_SHIFT (4u)
|
||||
#define CCR_SRC_BURST_LEN_MASK (0xFu<<CCR_SRC_BURST_LEN_SHIFT)
|
||||
#define CCR_SRC_PROT_CTRL_SHIFT (8u)
|
||||
#define CCR_SRC_PROT_CTRL_MASK (0x7u<<CCR_SRC_PROT_CTRL_SHIFT)
|
||||
#define CCR_SRC_CACHE_CTRL_SHIFT (11u)
|
||||
#define CCR_SRC_CACHE_CTRL_MASK (0x7u<<CCR_SRC_CACHE_CTRL_SHIFT)
|
||||
|
||||
#define CCR_DST_INC (1u<<14)
|
||||
#define CCR_DST_BURST_SIZE_SHIFT (15u)
|
||||
#define CCR_DST_BURST_SIZE_MASK (0x7u<<CCR_DST_BURST_SIZE_SHIFT)
|
||||
#define CCR_DST_BURST_LEN_SHIFT (18u)
|
||||
#define CCR_DST_BURST_LEN_MASK (0xFu<<CCR_DST_BURST_LEN_SHIFT)
|
||||
#define CCR_DST_PROT_CTRL_SHIFT (22u)
|
||||
#define CCR_DST_PROT_CTRL_MASK (0x7u<<CCR_DST_PROT_CTRL_SHIFT)
|
||||
#define CCR_DST_CACHE_CTRL_SHIFT (25u)
|
||||
#define CCR_DST_CACHE_CTRL_MASK (0x7u<<CCR_DST_CACHE_CTRL_SHIFT)
|
||||
|
||||
#define CCR_END_SWP_SIZE_SHIFT (28u) // END_SWP_SIZE = endian swap size.
|
||||
#define CCR_END_SWP_SIZE_MASK (0x7u<<CCR_END_SWP_SIZE_SHIFT)
|
||||
|
||||
// REG_DMA330_DBGSTATUS
|
||||
#define DBGSTATUS_BUSY (1u)
|
||||
|
||||
// REG_DMA330_DBGCMD
|
||||
#define DBGCMD_EXECUTE (0u)
|
||||
|
||||
// REG_DMA330_DBGINST0
|
||||
#define DBGINST0_THR_MGR (0u) // Select DMA manager thread.
|
||||
#define DBGINST0_THR_CH (1u) // Select DMA channel thread (also needs a channel number).
|
||||
#define DBGINST0(b10, ch, t) ((b10)<<16 | (ch)<<8 | (t)) // b10 = byte 1 and 0, ch = channel num, t = thread.
|
||||
// DBGINST1 stores the remaining 4 instruction bytes.
|
||||
|
||||
|
||||
|
||||
void DMA330_init(void);
|
||||
u8 DMA330_run(u8 ch, const u8 *const prog);
|
||||
u8 DMA330_status(u8 ch);
|
||||
void DMA330_ackIrq(u8 eventIrq);
|
||||
void DMA330_sev(u8 event);
|
||||
void DMA330_kill(u8 ch);
|
||||
|
||||
#ifdef ARM11
|
||||
//void DMA330_dbgPrint(void);
|
||||
#endif // ifdef ARM11
|
|
@ -0,0 +1,126 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mem_map.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define SCREEN_TOP (0u)
|
||||
#define SCREEN_BOT (1u)
|
||||
|
||||
#define SCREEN_WIDTH_TOP (400u)
|
||||
#define SCREEN_HEIGHT_TOP (240u)
|
||||
#define SCREEN_SIZE_TOP (SCREEN_WIDTH_TOP * SCREEN_HEIGHT_TOP * 2)
|
||||
#define SCREEN_WIDTH_BOT (320u)
|
||||
#define SCREEN_HEIGHT_BOT (240u)
|
||||
#define SCREEN_SIZE_BOT (SCREEN_WIDTH_BOT * SCREEN_HEIGHT_BOT * 2)
|
||||
|
||||
// TODO:
|
||||
// Because we are using a VRAM allocator this may break any time.
|
||||
#define FRAMEBUF_TOP_A_1 ((void*)VRAM_BASE)
|
||||
#define FRAMEBUF_BOT_A_1 (FRAMEBUF_TOP_A_1 + SCREEN_SIZE_TOP)
|
||||
#define FRAMEBUF_TOP_A_2 (FRAMEBUF_BOT_A_1 + SCREEN_SIZE_BOT + SCREEN_SIZE_TOP) // Skip B1
|
||||
#define FRAMEBUF_BOT_A_2 (FRAMEBUF_TOP_A_2 + SCREEN_SIZE_TOP)
|
||||
|
||||
#define DEFAULT_BRIGHTNESS (0x30)
|
||||
|
||||
/// Converts packed RGB8 to packed RGB565.
|
||||
#define RGB8_to_565(r,g,b) (((b)>>3)&0x1f)|((((g)>>2)&0x3f)<<5)|((((r)>>3)&0x1f)<<11)
|
||||
|
||||
|
||||
/// Framebuffer format.
|
||||
typedef enum
|
||||
{
|
||||
GFX_RGBA8 = 0, ///< RGBA8. (4 bytes)
|
||||
GFX_BGR8 = 1, ///< BGR8. (3 bytes)
|
||||
GFX_RGB565 = 2, ///< RGB565. (2 bytes)
|
||||
GFX_RGB5A1 = 3, ///< RGB5A1. (2 bytes)
|
||||
GFX_RGBA4 = 4 ///< RGBA4. (2 bytes)
|
||||
} GfxFbFmt;
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
typedef enum
|
||||
{
|
||||
GFX_EVENT_PSC0 = 0u,
|
||||
GFX_EVENT_PSC1 = 1u,
|
||||
GFX_EVENT_PDC0 = 2u,
|
||||
GFX_EVENT_PDC1 = 3u,
|
||||
GFX_EVENT_PPF = 4u,
|
||||
GFX_EVENT_P3D = 5u
|
||||
} GfxEvent;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GFX_BLIGHT_BOT = 1u<<2,
|
||||
GFX_BLIGHT_TOP = 1u<<4,
|
||||
GFX_BLIGHT_BOTH = GFX_BLIGHT_TOP | GFX_BLIGHT_BOT
|
||||
} GfxBlight;
|
||||
|
||||
|
||||
|
||||
void GFX_init(GfxFbFmt fmtTop, GfxFbFmt fmtBot);
|
||||
|
||||
static inline void GFX_initDefault(void)
|
||||
{
|
||||
GFX_init(GFX_BGR8, GFX_BGR8);
|
||||
}
|
||||
|
||||
void GFX_deinit(void);
|
||||
|
||||
void GFX_setFramebufFmt(GfxFbFmt fmtTop, GfxFbFmt fmtBot);
|
||||
|
||||
void GFX_powerOnBacklights(GfxBlight mask);
|
||||
|
||||
void GFX_powerOffBacklights(GfxBlight mask);
|
||||
|
||||
void GFX_setBrightness(u8 top, u8 bot);
|
||||
|
||||
void GFX_setForceBlack(bool top, bool bot);
|
||||
|
||||
void GFX_setDoubleBuffering(u8 screen, bool dBuf);
|
||||
|
||||
void* GFX_getFramebuffer(u8 screen);
|
||||
|
||||
void GFX_swapFramebufs(void);
|
||||
|
||||
void GFX_waitForEvent(GfxEvent event, bool discard);
|
||||
|
||||
// Helpers
|
||||
#define GFX_waitForPSC0() GFX_waitForEvent(GFX_EVENT_PSC0, false)
|
||||
#define GFX_waitForPSC1() GFX_waitForEvent(GFX_EVENT_PSC1, false)
|
||||
#define GFX_waitForVBlank0() GFX_waitForEvent(GFX_EVENT_PDC0, true)
|
||||
//#define GFX_waitForVBlank1() GFX_waitForEvent(GFX_EVENT_PDC1, true) // Disabled
|
||||
#define GFX_waitForPPF() GFX_waitForEvent(GFX_EVENT_PPF, false)
|
||||
#define GFX_waitForP3D() GFX_waitForEvent(GFX_EVENT_P3D, false)
|
||||
|
||||
void GX_memoryFill(u32 *buf0a, u32 buf0v, u32 buf0Sz, u32 val0, u32 *buf1a, u32 buf1v, u32 buf1Sz, u32 val1);
|
||||
|
||||
void GX_displayTransfer(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 flags);
|
||||
|
||||
void GX_textureCopy(const u32 *const in, u32 indim, u32 *out, u32 outdim, u32 size);
|
||||
|
||||
void GX_processCommandList(u32 size, const u32 *const cmdList);
|
||||
|
||||
//void GFX_enterLowPowerState(void);
|
||||
|
||||
//void GFX_returnFromLowPowerState(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,114 @@
|
|||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "error_codes.h"
|
||||
|
||||
|
||||
#define MAX_ROM_SIZE (1024u * 1024 * 32)
|
||||
#define MAX_SAVE_SIZE (1024u * 128)
|
||||
#define ARM7_STUB_LOC (0x3007E00u)
|
||||
#define ARM7_STUB_LOC9 (0x80BFE00u)
|
||||
#define ROM_LOC (0x20000000u)
|
||||
#define SAVE_LOC (0x8080000u)
|
||||
|
||||
|
||||
// REG_LGY_MODE
|
||||
#define LGY_MODE_TWL (1u)
|
||||
#define LGY_MODE_AGB (2u)
|
||||
#define LGY_MODE_START (1u<<15)
|
||||
|
||||
// REG_LGY_GBA_SAVE_TYPE
|
||||
enum
|
||||
{
|
||||
SAVE_TYPE_EEPROM_8k = 0x0u, // "[save] in upper 16Mbyte of ROM area"
|
||||
SAVE_TYPE_EEPROM_8k_2 = 0x1u, // "[save] in upper 100h byte of ROM area"
|
||||
SAVE_TYPE_EEPROM_64k = 0x2u, // "[save] in upper 16Mbyte of ROM area"
|
||||
SAVE_TYPE_EEPROM_64k_2 = 0x3u, // "[save] in upper 100h byte of ROM area"
|
||||
SAVE_TYPE_FLASH_512k_AML_RTC = 0x4u, // "FLASH ID=3D1Fh, Atmel"
|
||||
SAVE_TYPE_FLASH_512k_AML = 0x5u, // "FLASH ID=3D1Fh, Atmel"
|
||||
SAVE_TYPE_FLASH_512k_SST_RTC = 0x6u, // "FLASH ID=D4BFh, SST"
|
||||
SAVE_TYPE_FLASH_512k_SST = 0x7u, // "FLASH ID=D4BFh, SST"
|
||||
SAVE_TYPE_FLASH_512k_PSC_RTC = 0x8u, // "FLASH ID=1B32h, Panasonic"
|
||||
SAVE_TYPE_FLASH_512k_PSC = 0x9u, // "FLASH ID=1B32h, Panasonic"
|
||||
SAVE_TYPE_FLASH_1m_MRX_RTC = 0xAu, // "FLASH ID=09C2h, Macronix"
|
||||
SAVE_TYPE_FLASH_1m_MRX = 0xBu, // "FLASH ID=09C2h, Macronix"
|
||||
SAVE_TYPE_FLASH_1m_SNO_RTC = 0xCu, // "FLASH ID=1362h, Sanyo"
|
||||
SAVE_TYPE_FLASH_1m_SNO = 0xDu, // "FLASH ID=1362h, Sanyo"
|
||||
SAVE_TYPE_SRAM_256k = 0xEu,
|
||||
SAVE_TYPE_NONE = 0xFu,
|
||||
|
||||
SAVE_TYPE_MASK = SAVE_TYPE_NONE
|
||||
};
|
||||
|
||||
// REG_LGY_GBA_SAVE_MAP
|
||||
#define LGY_SAVE_MAP_7 (0u)
|
||||
#define LGY_SAVE_MAP_9 (1u)
|
||||
|
||||
// REG_LGY_GBA_RTC_CNT
|
||||
#define LGY_RTC_CNT_WR (1u) // Write date and time.
|
||||
#define LGY_RTC_CNT_RD (1u<<1) // Read date and time.
|
||||
#define LGY_RTC_CNT_WR_ERR (1u<<14) // Write error (wrong date/time).
|
||||
#define LGY_RTC_CNT_BUSY (1u<<15)
|
||||
|
||||
// REG_LGY_GBA_RTC_BCD_DATE
|
||||
// Shifts
|
||||
#define LGY_RTC_BCD_Y_SHIFT (0u)
|
||||
#define LGY_RTC_BCD_MON_SHIFT (8u)
|
||||
#define LGY_RTC_BCD_D_SHIFT (16u)
|
||||
#define LGY_RTC_BCD_W_SHIFT (24u)
|
||||
// Masks
|
||||
#define LGY_RTC_BCD_Y_MASK (0xFFu<<LGY_RTC_BCD_Y_SHIFT)
|
||||
#define LGY_RTC_BCD_MON_MASK (0x1Fu<<LGY_RTC_BCD_M_SHIFT)
|
||||
#define LGY_RTC_BCD_D_MASK (0x3Fu<<LGY_RTC_BCD_D_SHIFT)
|
||||
#define LGY_RTC_BCD_W_MASK (0x07u<<LGY_RTC_BCD_W_SHIFT)
|
||||
|
||||
// REG_LGY_GBA_RTC_BCD_TIME
|
||||
// Shifts
|
||||
#define LGY_RTC_BCD_H_SHIFT (0u)
|
||||
#define LGY_RTC_BCD_MIN_SHIFT (8u)
|
||||
#define LGY_RTC_BCD_S_SHIFT (16u)
|
||||
// Masks
|
||||
#define LGY_RTC_BCD_H_MASK (0x3Fu<<LGY_RTC_BCD_H_SHIFT)
|
||||
#define LGY_RTC_BCD_MIN_MASK (0x7Fu<<LGY_RTC_BCD_MIN_SHIFT)
|
||||
#define LGY_RTC_BCD_S_MASK (0x7Fu<<LGY_RTC_BCD_S_SHIFT)
|
||||
|
||||
// All values in BCD.
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 h;
|
||||
u8 min;
|
||||
u8 s;
|
||||
u8 unused;
|
||||
};
|
||||
u32 time;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 y;
|
||||
u8 mon;
|
||||
u8 d;
|
||||
u8 dow; // Day of week.
|
||||
};
|
||||
u32 date;
|
||||
};
|
||||
} ALIGN(8) GbaRtc; // Workaround: Poor optimization on pass by value.
|
||||
|
||||
// REGs_LGY_GBA_SAVE_TIMING
|
||||
|
||||
|
||||
|
||||
Result LGY_prepareGbaMode(bool biosIntro, u16 saveType, const char *const savePath);
|
||||
Result LGY_setGbaRtc(const GbaRtc rtc);
|
||||
Result LGY_getGbaRtc(GbaRtc *const out);
|
||||
Result LGY_backupGbaSave(void);
|
||||
#ifdef ARM11
|
||||
void LGY_switchMode(void);
|
||||
void LGY_handleOverrides(void);
|
||||
void LGY_deinit(void);
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "mem_map.h"
|
||||
|
||||
|
||||
#ifdef ARM9
|
||||
#define PXI_REGS_BASE (IO_MEM_ARM9_ONLY + 0x8000)
|
||||
#elif ARM11
|
||||
#define PXI_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x63000)
|
||||
#endif
|
||||
#define REG_PXI_SYNC_RECVD *((const vu8*)(PXI_REGS_BASE + 0x00))
|
||||
#define REG_PXI_SYNC_SENT *((vu8 *)(PXI_REGS_BASE + 0x01)) // Write-only
|
||||
#define REG_PXI_SYNC_IRQ *((vu8 *)(PXI_REGS_BASE + 0x03))
|
||||
#define REG_PXI_SYNC *((vu32*)(PXI_REGS_BASE + 0x00))
|
||||
#define REG_PXI_CNT *((vu16*)(PXI_REGS_BASE + 0x04))
|
||||
#define REG_PXI_SFIFO *((vu32*)(PXI_REGS_BASE + 0x08))
|
||||
#define REG_PXI_RFIFO *((const vu32*)(PXI_REGS_BASE + 0x0C))
|
||||
|
||||
|
||||
// REG_PXI_SYNC
|
||||
#define PXI_SYNC_RECVD (REG_PXI_SYNC & 0xFFu)
|
||||
#define PXI_SYNC_SENT(sent) ((REG_PXI_SYNC & ~(0xFFu<<8)) | (sent)<<8)
|
||||
#ifdef ARM9
|
||||
#define PXI_SYNC_IRQ (1u<<29)
|
||||
#elif ARM11
|
||||
#define PXI_SYNC_IRQ (1u<<30)
|
||||
#endif
|
||||
#define PXI_SYNC_IRQ_ENABLE (1u<<31)
|
||||
|
||||
// REG_PXI_SYNC_IRQ
|
||||
#ifdef ARM9
|
||||
#define PXI_SYNC_IRQ_IRQ (1u<<5)
|
||||
#define PXI_SYNC_IRQ_IRQ2 (1u<<6)
|
||||
#elif ARM11
|
||||
#define PXI_SYNC_IRQ_IRQ (1u<<6)
|
||||
#endif
|
||||
#define PXI_SYNC_IRQ_IRQ_ENABLE (1u<<7)
|
||||
|
||||
// REG_PXI_CNT
|
||||
#define PXI_CNT_SFIFO_EMPTY (1u<<0)
|
||||
#define PXI_CNT_SFIFO_FULL (1u<<1)
|
||||
#define PXI_CNT_SFIFO_NOT_FULL_IRQ_ENABLE (1u<<2)
|
||||
#define PXI_CNT_FLUSH_SFIFO (1u<<3)
|
||||
#define PXI_CNT_RFIFO_EMPTY (1u<<8)
|
||||
#define PXI_CNT_RFIFO_FULL (1u<<9)
|
||||
#define PXI_CNT_RFIFO_NOT_EMPTY_IRQ_ENABLE (1u<<10)
|
||||
#define PXI_CNT_FIFO_ERROR (1u<<14) // Also used for aknowledge
|
||||
#define PXI_CNT_ENABLE_SRFIFO (1u<<15)
|
||||
|
||||
|
||||
|
||||
void PXI_init(void);
|
||||
u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words);
|
||||
void PXI_sendPanicCmd(u32 cmd); // Not intended for normal use!
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define IPC_MAX_PARAMS (15)
|
||||
#define IPC_CMD_RESP_FLAG (1u<<15)
|
||||
#define IPC_CMD_ID_MASK(cmd) ((cmd)>>8) // Max 127
|
||||
#define IPC_CMD_IN_BUFS_MASK(cmd) ((cmd)>>6 & 3u) // Max 3
|
||||
#define IPC_CMD_OUT_BUFS_MASK(cmd) ((cmd)>>4 & 3u) // Max 3
|
||||
#define IPC_CMD_PARAMS_MASK(cmd) ((cmd) & 15u) // Max 15
|
||||
|
||||
|
||||
// https://stackoverflow.com/a/52770279
|
||||
// Note: __COUNTER__ is non standard.
|
||||
#define MAKE_CMD9(inBufs, outBufs, params) ((__COUNTER__ - _CMD9_C_BASE)<<8 | (inBufs)<<6 | (outBufs)<<4 | params)
|
||||
#define MAKE_CMD11(inBufs, outBufs, params) ((__COUNTER__ - _CMD11_C_BASE)<<8 | (inBufs)<<6 | (outBufs)<<4 | params)
|
||||
|
||||
enum {_CMD9_C_BASE = __COUNTER__ + 1}; // Start at 0.
|
||||
typedef enum
|
||||
{
|
||||
// Filesystem API.
|
||||
IPC_CMD9_FMOUNT = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FUNMOUNT = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FGETFREE = MAKE_CMD9(0, 1, 1),
|
||||
IPC_CMD9_FOPEN = MAKE_CMD9(1, 1, 1),
|
||||
IPC_CMD9_FREAD = MAKE_CMD9(0, 2, 1),
|
||||
IPC_CMD9_FWRITE = MAKE_CMD9(1, 1, 1),
|
||||
IPC_CMD9_FSYNC = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FLSEEK = MAKE_CMD9(0, 0, 2),
|
||||
IPC_CMD9_FTELL = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FSIZE = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FCLOSE = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FSTAT = MAKE_CMD9(1, 1, 0),
|
||||
IPC_CMD9_FCHDIR = MAKE_CMD9(1, 0, 0),
|
||||
IPC_CMD9_FOPEN_DIR = MAKE_CMD9(1, 1, 0),
|
||||
IPC_CMD9_FREAD_DIR = MAKE_CMD9(0, 2, 2),
|
||||
IPC_CMD9_FCLOSE_DIR = MAKE_CMD9(0, 0, 1),
|
||||
IPC_CMD9_FMKDIR = MAKE_CMD9(1, 0, 0),
|
||||
IPC_CMD9_FRENAME = MAKE_CMD9(2, 0, 0),
|
||||
IPC_CMD9_FUNLINK = MAKE_CMD9(1, 0, 0),
|
||||
|
||||
// open_agb_firm specific API.
|
||||
IPC_CMD9_PREPARE_GBA = MAKE_CMD9(1, 0, 2),
|
||||
IPC_CMD9_SET_GBA_RTC = MAKE_CMD9(0, 0, 2),
|
||||
IPC_CMD9_GET_GBA_RTC = MAKE_CMD9(0, 1, 0),
|
||||
IPC_CMD9_BACKUP_GBA_SAVE = MAKE_CMD9(0, 0, 0),
|
||||
|
||||
// Miscellaneous API.
|
||||
IPC_CMD9_PREPARE_POWER = MAKE_CMD9(0, 0, 0) // Also used for panic() and guruMeditation().
|
||||
} IpcCmd9;
|
||||
|
||||
enum {_CMD11_C_BASE = __COUNTER__ + 1}; // Start at 0.
|
||||
typedef enum
|
||||
{
|
||||
// Miscellaneous API.
|
||||
IPC_CMD11_PRINT_MSG = MAKE_CMD11(0, 0, 0), // Invalid on purpose. Will be decided later.
|
||||
IPC_CMD11_PANIC = MAKE_CMD11(0, 0, 0),
|
||||
IPC_CMD11_EXCEPTION = MAKE_CMD11(0, 0, 0)
|
||||
} IpcCmd11;
|
||||
|
||||
#undef MAKE_CMD9
|
||||
#undef MAKE_CMD11
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *ptr;
|
||||
u32 size;
|
||||
} IpcBuffer;
|
||||
|
||||
|
||||
|
||||
u32 IPC_handleCmd(u8 cmdId, u32 inBufs, u32 outBufs, const u32 *const buf);
|
|
@ -0,0 +1,153 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef ARM9
|
||||
/* ITCM */
|
||||
#define ITCM_BASE (0x00000000)
|
||||
#define ITCM_KERNEL_MIRROR (0x01FF8000)
|
||||
#define ITCM_BOOT9_MIRROR (0x07FF8000)
|
||||
#define ITCM_SIZE (0x00008000) // 32 KiB
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
/* ARM11 bootrom */
|
||||
#define BOOT11_BASE (0x00000000)
|
||||
#define BOOT11_MIRROR1 (0x00010000)
|
||||
#define BOOT11_SIZE (0x00010000) // 64 KiB
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ARM9
|
||||
/* ARM9 RAM */
|
||||
#define A9_RAM_BASE (0x08000000)
|
||||
#define A9_RAM_N3DS_EXT_BASE (A9_RAM_BASE + 0x100000)
|
||||
#define A9_RAM_SIZE (0x00100000) // 1 MiB
|
||||
#define A9_RAM_N3DS_EXT_SIZE (0x00080000) // 512 KiB
|
||||
#endif
|
||||
|
||||
|
||||
/* IO mem */
|
||||
#define IO_MEM_BASE (0x10000000)
|
||||
#define IO_MEM_ARM9_ONLY (IO_MEM_BASE)
|
||||
#define IO_MEM_ARM9_ARM11 (IO_MEM_BASE + 0x100000)
|
||||
#define IO_MEM_ARM11_ONLY (IO_MEM_BASE + 0x200000)
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
/* ARM11 MPCore private region */
|
||||
#define MPCORE_PRIV_REG_BASE (0x17E00000)
|
||||
#define MPCORE_PRIV_REG_SIZE (0x00002000) // 8 KiB
|
||||
|
||||
|
||||
/* L2C-310 Level 2 Cache Controller */
|
||||
#define L2_CACHE_CONTR_BASE (0x17E10000)
|
||||
#define L2_CACHE_CONTR_SIZE (0x00001000) // 4 KiB
|
||||
#endif
|
||||
|
||||
|
||||
/* VRAM */
|
||||
#define VRAM_BASE (0x18000000)
|
||||
#define VRAM_SIZE (0x00600000)
|
||||
#define VRAM_BANK0 (VRAM_BASE)
|
||||
#define VRAM_BANK1 (VRAM_BASE + 0x300000)
|
||||
|
||||
|
||||
/* DSP mem */
|
||||
#define DSP_MEM_BASE (0x1FF00000)
|
||||
#define DSP_MEM_SIZE (0x00080000) // 512 KiB
|
||||
|
||||
|
||||
/* AXIWRAM */
|
||||
#define AXIWRAM_BASE (0x1FF80000)
|
||||
#define AXIWRAM_SIZE (0x00080000) // 512 KiB
|
||||
|
||||
|
||||
/* FCRAM */
|
||||
#define FCRAM_BASE (0x20000000)
|
||||
#define FCRAM_N3DS_EXT_BASE (FCRAM_BASE + 0x8000000)
|
||||
#define FCRAM_SIZE (0x08000000) // 128 MiB
|
||||
#define FCRAM_N3DS_EXT_SIZE (FCRAM_SIZE)
|
||||
|
||||
|
||||
#ifdef ARM9
|
||||
/* OTP */
|
||||
#define OTP_BASE (0x10012000)
|
||||
#define OTP_SIZE (0x00000100) // 256 bytes
|
||||
|
||||
|
||||
/* DTCM */
|
||||
#define DTCM_BASE (0xFFF00000)
|
||||
#define DTCM_SIZE (0x00004000) // 16 KiB
|
||||
|
||||
|
||||
/* ARM9 bootrom */
|
||||
#define BOOT9_BASE (0xFFFF0000)
|
||||
#define BOOT9_SIZE (0x00010000) // 64 KiB
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
/* ARM11 bootrom */
|
||||
#define BOOT11_MIRROR2 (0xFFFF0000)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Custom mappings */
|
||||
#ifdef ARM9
|
||||
#define A9_VECTORS_START (A9_RAM_BASE)
|
||||
#define A9_VECTORS_SIZE (0x40)
|
||||
#define A9_STUB_ENTRY (ITCM_KERNEL_MIRROR + ITCM_SIZE - 0x200)
|
||||
#define A9_STUB_SIZE (0x200)
|
||||
#define A9_HEAP_END (A9_RAM_BASE + A9_RAM_SIZE)
|
||||
#define A9_STACK_START (DTCM_BASE)
|
||||
#define A9_STACK_END (DTCM_BASE + DTCM_SIZE - 0x400)
|
||||
#define A9_IRQ_STACK_START (DTCM_BASE + DTCM_SIZE - 0x400)
|
||||
#define A9_IRQ_STACK_END (DTCM_BASE + DTCM_SIZE)
|
||||
#define A9_EXC_STACK_START (ITCM_KERNEL_MIRROR + (ITCM_SIZE / 2))
|
||||
#define A9_EXC_STACK_END (ITCM_KERNEL_MIRROR + ITCM_SIZE)
|
||||
#define FIRM_LOAD_ADDR (VRAM_BASE + 0x200000)
|
||||
#define RAM_FIRM_BOOT_ADDR (FCRAM_BASE + 0x1000)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ARM11
|
||||
#define A11_C0_STACK_START (AXIWRAM_BASE) // Core 0 stack
|
||||
#define A11_C0_STACK_END (A11_C0_STACK_START + 0x2000)
|
||||
#define A11_C1_STACK_START (A11_C0_STACK_END) // Core 1 stack
|
||||
#define A11_C1_STACK_END (A11_C1_STACK_START + 0x2000)
|
||||
// WARNING: The stacks for core 2/3 are temporary
|
||||
#define A11_C2_STACK_START (FCRAM_BASE - 0x600) // Core 2 stack
|
||||
#define A11_C2_STACK_END (FCRAM_BASE - 0x400)
|
||||
#define A11_C3_STACK_START (FCRAM_BASE - 0x400) // Core 3 stack
|
||||
#define A11_C3_STACK_END (FCRAM_BASE - 0x200)
|
||||
#define A11_EXC_STACK_START (VRAM_BASE + VRAM_SIZE - 0x200000)
|
||||
#define A11_EXC_STACK_END (VRAM_BASE + VRAM_SIZE - 0x100000)
|
||||
#define A11_MMU_TABLES_BASE (A11_C1_STACK_END)
|
||||
#define A11_VECTORS_START (AXIWRAM_BASE + AXIWRAM_SIZE - 0x60)
|
||||
#define A11_VECTORS_SIZE (0x60)
|
||||
#define A11_FALLBACK_ENTRY (AXIWRAM_BASE + AXIWRAM_SIZE - 0x4)
|
||||
#define A11_STUB_ENTRY (AXIWRAM_BASE + AXIWRAM_SIZE - 0x200)
|
||||
#define A11_STUB_SIZE (0x1A0) // Don't overwrite the vectors
|
||||
#define A11_HEAP_END (AXIWRAM_BASE + AXIWRAM_SIZE)
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
void iomemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size);
|
||||
void iomemset(vu32 *ptr, u32 value, u32 size);
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2018 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,16 +18,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void convert160pFrameFast(void);
|
||||
void convert240pFrameFast(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
//void WEAK __systemInit(void);
|
||||
void WEAK __systemDeinit(void);
|
|
@ -0,0 +1,77 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <inttypes.h> // printf()/scanf() macros
|
||||
#include <stdalign.h> // alignas(alignment_in_bytes)
|
||||
#include <stdbool.h> // bool, true/false
|
||||
#include <stddef.h> // size_t, NULL...
|
||||
#include <stdint.h> // uint8_t, uint16_t...
|
||||
#include <stdnoreturn.h> // noreturn keyword
|
||||
#include <unistd.h> // ssize_t
|
||||
|
||||
|
||||
|
||||
#define ALIGN(a) __attribute__((aligned(a))) // Use alignas() instead.
|
||||
#define NAKED __attribute__((naked))
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#define ALWAYS_INLINE __attribute__((always_inline)) static inline
|
||||
#define PACKED __attribute__((packed))
|
||||
#define TARGET_ARM __attribute__((target("arm")))
|
||||
#define TARGET_THUMB __attribute__((target("thumb")))
|
||||
#define UNUSED __attribute__((unused))
|
||||
#define USED __attribute__((used))
|
||||
#define WEAK __attribute__((weak))
|
||||
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
typedef volatile uint8_t vu8;
|
||||
typedef volatile uint16_t vu16;
|
||||
typedef volatile uint32_t vu32;
|
||||
typedef volatile uint64_t vu64;
|
||||
|
||||
typedef volatile int8_t vs8;
|
||||
typedef volatile int16_t vs16;
|
||||
typedef volatile int32_t vs32;
|
||||
typedef volatile int64_t vs64;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[3];
|
||||
} _u96;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[4];
|
||||
} _u128;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[16];
|
||||
} _u512;
|
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define min(a,b) ((size_t) (a) <= (size_t) (b) ? (size_t) (a) : (size_t) (b))
|
||||
|
||||
#define arrayEntries(array) sizeof(array)/sizeof(*array)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Waits at least the specified amount of CPU cycles.
|
||||
*
|
||||
* @param[in] cycles The cycles to wait.
|
||||
*/
|
||||
NAKED void wait_cycles(u32 cycles);
|
||||
|
||||
/**
|
||||
* @brief Safer strcpy with checks.
|
||||
* The dst string always gets terminated except when num is 0.
|
||||
* If the src string is too long nothing is copied and dst will be terminated.
|
||||
* This function is not safe against race conditions!
|
||||
*
|
||||
* @param dst The destination pointer.
|
||||
* @param[in] src The source pointer.
|
||||
* @param[in] num Maximum number of chars to copy including null terminator.
|
||||
*
|
||||
* @return The length of the copied string in bytes including null terminator.
|
||||
*/
|
||||
size_t safeStrcpy(char *const dst, const char *const src, size_t num);
|
||||
|
||||
/**
|
||||
* @brief Basic string to float conversion. Limited to 6 decimal places.
|
||||
* Doesn't support exponents.
|
||||
*
|
||||
* @param[in] str The string.
|
||||
*
|
||||
* @return The floatingpoint number represented by str.
|
||||
*/
|
||||
float str2float(const char *str);
|
||||
|
||||
// case insensitive string compare function
|
||||
int strnicmp(const char *str1, const char *str2, u32 len);
|
||||
|
||||
// custom safe strncpy, string is always 0-terminated for buflen > 0
|
||||
void strncpy_s(char *dest, const char *src, u32 nchars, const u32 buflen);
|
||||
|
||||
void memcpy_s(void *dstBuf, size_t dstBufSize, size_t dstBufOffset,
|
||||
void *srcBuf, size_t srcBufSize, size_t srcBufOffset, bool reverse);
|
||||
|
||||
u32 getleu32(const void* ptr);
|
||||
|
||||
u32 swap32(u32 val);
|
||||
|
||||
static inline u32 intLog2(u32 val)
|
||||
{
|
||||
// The result is undefined if __builtin_clz() is called with 0.
|
||||
return (val ? 31u - __builtin_clz(val) : 0u);
|
||||
}
|
||||
|
||||
// Round up to the next power of 2.
|
||||
static inline u32 nextPow2(u32 val)
|
||||
{
|
||||
// Portable variant:
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
/*val--;
|
||||
val |= val>>1;
|
||||
val |= val>>2;
|
||||
val |= val>>4;
|
||||
val |= val>>8;
|
||||
val |= val>>16;
|
||||
val++;
|
||||
|
||||
return val;*/
|
||||
|
||||
// Warning: Allowed range is 2 - 2147483648.
|
||||
// Everything else is undefined behavior.
|
||||
return 1u<<(32u - __builtin_clz(val - 1));
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2022 derrek, profi200
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,36 +18,23 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "error_codes.h"
|
||||
// MAX_PRIO_BITS The number of available priorities. Minimum 3. Maximum 32.
|
||||
#define MAX_PRIO_BITS (4)
|
||||
|
||||
/*
|
||||
* Maximum number of objects we can create (Slabheap).
|
||||
*/
|
||||
#define MAX_TASKS (3) // Including main and idle task.
|
||||
#define MAX_EVENTS (10)
|
||||
#define MAX_MUTEXES (3)
|
||||
#define MAX_SEMAPHORES (0)
|
||||
#define MAX_TIMERS (0)
|
||||
|
||||
#define IDLE_STACK_SIZE (0x1000) // Keep in mind this stack is used in interrupt contex! TODO: Change this.
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// TODO: More checks. For example slabheap.
|
||||
#if (MAX_PRIO_BITS < 3 || MAX_PRIO_BITS > 32)
|
||||
#error "Invalid number of maximum task priorities!"
|
||||
#endif
|
||||
|
||||
#define MAKE_CUSTOM_ERR(e) (CUSTOM_ERR_OFFSET + (e))
|
||||
|
||||
// Keep errors in the range of 0-CUSTOM_ERR_OFFSET - 1.
|
||||
enum
|
||||
{
|
||||
// Custom errors.
|
||||
RES_ROM_TOO_BIG = MAKE_CUSTOM_ERR(0u),
|
||||
RES_INVALID_PATCH = MAKE_CUSTOM_ERR(1u),
|
||||
|
||||
MAX_OAF_RES_VALUE = RES_ROM_TOO_BIG
|
||||
};
|
||||
|
||||
#undef MAKE_CUSTOM_ERR
|
||||
|
||||
|
||||
|
||||
const char* oafResult2String(Result res);
|
||||
#ifdef __ARM11__
|
||||
void printError(Result res);
|
||||
void printErrorWaitInput(Result res, u32 waitKeys);
|
||||
#endif // ifdef __ARM11__
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 r4;
|
||||
u32 r5;
|
||||
u32 r6;
|
||||
u32 r7;
|
||||
u32 r8;
|
||||
u32 r9;
|
||||
u32 r10;
|
||||
u32 r11;
|
||||
u32 lr; // pc
|
||||
} cpuRegs;
|
||||
|
||||
|
||||
|
||||
KRes switchContext(KRes res, uintptr_t *oldSp, uintptr_t newSp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "types.h"
|
||||
#include "internal/list.h"
|
||||
#include "kernel.h"
|
||||
#include "arm.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TASK_STATE_DEAD = 0,
|
||||
//TASK_STATE_READY = 1,
|
||||
TASK_STATE_RUNNING = 1,
|
||||
TASK_STATE_BLOCKED = 2,
|
||||
TASK_STATE_RUNNING_SHORT = 3 // Continue task as soon as the woken ones are finished.
|
||||
} TaskState;
|
||||
|
||||
struct TaskCb
|
||||
{
|
||||
ListNode node;
|
||||
u8 core; // TODO: Multicore
|
||||
u8 prio;
|
||||
u8 id;
|
||||
KRes res; // Last error code. Also abused for taskArg.
|
||||
uintptr_t savedSp;
|
||||
void *stack;
|
||||
// Name?
|
||||
// Exit code?
|
||||
}; // Task context
|
||||
typedef struct TaskCb TaskCb;
|
||||
static_assert(offsetof(TaskCb, node) == 0, "Error: Member node of TaskCb is not at offset 0!");
|
||||
|
||||
|
||||
|
||||
const TaskCb* getCurrentTask(void);
|
||||
KRes waitQueueBlock(ListNode *waitQueue);
|
||||
bool waitQueueWakeN(ListNode *waitQueue, u32 wakeCount, KRes res, bool reschedule);
|
||||
|
||||
|
||||
static inline void kernelLock(void)
|
||||
{
|
||||
__cpsid(i);
|
||||
//spinlockLock(&g_lock);
|
||||
}
|
||||
static inline void kernelUnlock(void)
|
||||
{
|
||||
__cpsie(i);
|
||||
//spinlockUnlock(&g_lock);
|
||||
}
|
||||
|
||||
|
||||
// These functions belong in other headers however we
|
||||
// don't want to make them accessible in the public API.
|
||||
void _eventSlabInit(void);
|
||||
void _mutexSlabInit(void);
|
||||
void _semaphoreSlabInit(void);
|
||||
void _timerInit(void);
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
void kmemcpy(u32 *restrict dst, const u32 *restrict src, u32 size);
|
||||
|
||||
// Alias of kmemcpy() with volatile arguments.
|
||||
void iokmemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size);
|
||||
|
||||
void kmemset(u32 *ptr, u32 value, u32 size);
|
||||
|
||||
// Alias of kmemset() with volatile arguments.
|
||||
void iokmemset(vu32 *ptr, u32 value, u32 size);
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
// Based on https://github.com/torvalds/linux/blob/master/include/linux/list.h
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#define LIST_INIT_VAL(name) ((ListNode){&(name), &(name)})
|
||||
|
||||
#define LIST_ENTRY(ptr, type, member) \
|
||||
({ \
|
||||
void *__mptr = (void*)(ptr); \
|
||||
(type*)(__mptr - (size_t)&((type*)0)->member); \
|
||||
})
|
||||
|
||||
#define LIST_FIRST_ENTRY(ptr, type, member) \
|
||||
LIST_ENTRY((ptr)->next, type, member)
|
||||
|
||||
#define LIST_NEXT_ENTRY(pos, member) \
|
||||
LIST_ENTRY((pos)->member.next, typeof(*(pos)), member)
|
||||
|
||||
#define LIST_FOR_EACH_ENTRY(pos, start, member) \
|
||||
for(pos = LIST_FIRST_ENTRY(start, typeof(*pos), member); \
|
||||
&pos->member != (start); \
|
||||
pos = LIST_NEXT_ENTRY(pos, member))
|
||||
|
||||
|
||||
typedef struct ListNode ListNode;
|
||||
struct ListNode
|
||||
{
|
||||
ListNode *next;
|
||||
ListNode *prev;
|
||||
};
|
||||
//static_assert(offsetof(ListNode, next) == 0, "Error: Member next of ListNode is not at offset 0!");
|
||||
|
||||
|
||||
|
||||
static inline void listInit(ListNode *start)
|
||||
{
|
||||
*start = LIST_INIT_VAL(*start);
|
||||
}
|
||||
|
||||
static inline bool listEmpty(const ListNode *start)
|
||||
{
|
||||
return start->next == start;
|
||||
}
|
||||
|
||||
// Internal function. Don't use unless you know what you are doing!
|
||||
static inline void _listAdd(ListNode *node, ListNode *next, ListNode *prev)
|
||||
{
|
||||
node->next = next;
|
||||
node->prev = prev;
|
||||
next->prev = node;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
static inline void listAddBefore(ListNode *entry, ListNode *node)
|
||||
{
|
||||
_listAdd(node, entry, entry->prev);
|
||||
}
|
||||
|
||||
static inline void listAddAfter(ListNode *entry, ListNode *node)
|
||||
{
|
||||
_listAdd(node, entry->next, entry);
|
||||
}
|
||||
|
||||
// Internal function. Don't use unless you know what you are doing!
|
||||
static inline void _listDelete(ListNode *next, ListNode *prev)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
static inline void listDelete(ListNode *entry)
|
||||
{
|
||||
_listDelete(entry->next, entry->prev);
|
||||
}
|
||||
|
||||
static inline ListNode* listRemoveTail(ListNode *start)
|
||||
{
|
||||
ListNode *const node = start->next;
|
||||
|
||||
listDelete(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline ListNode* listRemoveHead(ListNode *start)
|
||||
{
|
||||
ListNode *const node = start->prev;
|
||||
|
||||
listDelete(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// Some function aliases for queues.
|
||||
#define listPush(start, node) listAddBefore((start), (node))
|
||||
#define listPop(start) listRemoveTail((start))
|
||||
#define listPushTail(start, node) listAddAfter((start), (node))
|
||||
#define listPopHead(start) listRemoveHead((start))
|
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include "internal/list.h"
|
||||
|
||||
|
||||
typedef ListNode SlabHeap;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the slabheap.
|
||||
*
|
||||
* @param slab SlabHeap object pointer.
|
||||
* @param[in] objSize The size of the object slots.
|
||||
* @param[in] num The maximum number of object slots.
|
||||
*/
|
||||
void slabInit(SlabHeap *slab, size_t objSize, size_t num);
|
||||
|
||||
/**
|
||||
* @brief Allocates an object slot from the slabheap.
|
||||
*
|
||||
* @param slab SlabHeap object pointer.
|
||||
*
|
||||
* @return Returns a pointer to the object slot.
|
||||
*/
|
||||
void* slabAlloc(SlabHeap *slab);
|
||||
|
||||
/**
|
||||
* @brief Same as slabAlloc() but clears slots.
|
||||
*
|
||||
* @param slab SlabHeap object pointer.
|
||||
* @param[in] clrSize The clear size (passed to memset()).
|
||||
*
|
||||
* @return Returns a pointer to the object slot.
|
||||
*/
|
||||
void* slabCalloc(SlabHeap *slab, size_t clrSize);
|
||||
|
||||
/**
|
||||
* @brief Deallocates an object slot.
|
||||
*
|
||||
* @param slab SlabHeap object pointer.
|
||||
* @param ptr The object slot pointer.
|
||||
*/
|
||||
void slabFree(SlabHeap *slab, void *ptr);
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
|
||||
static inline void spinlockLock(u32 *lock)
|
||||
{
|
||||
u32 tmp;
|
||||
__asm__ volatile("1: ldrex %0, [%1]\n"
|
||||
" teq %0, #0\n"
|
||||
" wfene\n"
|
||||
" strexeq %0, %2, [%1]\n"
|
||||
" teqeq %0, #0\n"
|
||||
" bne 1b\n"
|
||||
" mcr p15, 0, %0, c7, c10, 5" // DMB
|
||||
: "=&r" (tmp) : "r" (lock), "r" (1) : "cc", "memory");
|
||||
}
|
||||
|
||||
static inline void spinlockUnlock(u32 *lock)
|
||||
{
|
||||
__asm__ volatile("mcr p15, 0, %0, c7, c10, 5\n" // DMB
|
||||
"str %0, [%1]\n"
|
||||
"mcr p15, 0, %0, c7, c10, 4\n" // DSB
|
||||
"sev"
|
||||
: : "r" (0), "r" (lock) : "memory");
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#define LIKELY(expr) __builtin_expect((expr), true)
|
||||
#define UNLIKELY(expr) __builtin_expect((expr), false)
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
KRES_OK = 0, // No error.
|
||||
KRES_INVALID_HANDLE = 1, // The handle or object doesn't exist.
|
||||
KRES_HANDLE_DELETED = 2, // The handle has been deleted externally.
|
||||
//KRES_WAIT_QUEUE_FULL = 3, // The wait queue is full. We can't block on it.
|
||||
KRES_WOULD_BLOCK = 3, // The function would block. For non-blocking APIs.
|
||||
KRES_NO_PERMISSIONS = 4 // You have no permissions. Example unlocking a mutex on a different task.
|
||||
};
|
||||
|
||||
typedef uintptr_t KRes; // See createTask()
|
||||
typedef struct TaskCb KTask;
|
||||
typedef void (*TaskFunc)(void*);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the kernel. Only call this once.
|
||||
*
|
||||
* @param[in] priority The priority of the main task.
|
||||
*/
|
||||
void kernelInit(uint8_t priority);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new kernel task.
|
||||
*
|
||||
* @param[in] stackSize The stack size.
|
||||
* @param[in] priority The priority.
|
||||
* @param[in] entry The entry function.
|
||||
* @param taskArg The task entry function argument.
|
||||
*
|
||||
* @return Returns a KTask handle.
|
||||
*/
|
||||
KTask* createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg);
|
||||
|
||||
/**
|
||||
* @brief Switches to the next task. Use with care.
|
||||
*/
|
||||
void yieldTask(void);
|
||||
|
||||
/**
|
||||
* @brief Task exit function. Must be called from the task that exits.
|
||||
*/
|
||||
void taskExit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct KEvent KEvent;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new KEvent.
|
||||
*
|
||||
* @param[in] oneShot Event fires only once and auto clears if true.
|
||||
*
|
||||
* @return The KEvent pointer or NULL when out of memory.
|
||||
*/
|
||||
KEvent* createEvent(bool oneShot);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*/
|
||||
void deleteEvent(KEvent *const kevent);
|
||||
|
||||
/**
|
||||
* @brief Binds the given KEvent to an interrupt.
|
||||
*
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
* @param[in] id The interrupt id.
|
||||
* @param[in] prio The interrupt priority.
|
||||
*/
|
||||
void bindInterruptToEvent(KEvent *const kevent, uint8_t id, uint8_t prio);
|
||||
|
||||
void unbindInterruptEvent(uint8_t id);
|
||||
|
||||
/**
|
||||
* @brief Waits for the given KEvent to be signaled.
|
||||
*
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres above.
|
||||
*/
|
||||
KRes waitForEvent(KEvent *const kevent);
|
||||
|
||||
/**
|
||||
* @brief Signals a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
* @param[in] reschedule Set to true to immediately reschedule.
|
||||
*/
|
||||
void signalEvent(KEvent *const kevent, bool reschedule);
|
||||
|
||||
/**
|
||||
* @brief Clears a KEvent.
|
||||
*
|
||||
* @param[in] kevent The KEvent pointer.
|
||||
*/
|
||||
void clearEvent(KEvent *const kevent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct KMutex KMutex; // TODO: Implement this using semaphores?
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new KMutex.
|
||||
*
|
||||
* @return The KMutex pointer or NULL when out of memory.
|
||||
*/
|
||||
KMutex* createMutex(void);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*/
|
||||
void deleteMutex(KMutex *const kmutex);
|
||||
|
||||
/**
|
||||
* @brief Locks a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres.
|
||||
*/
|
||||
KRes lockMutex(KMutex *const kmutex);
|
||||
|
||||
/**
|
||||
* @brief Unlocks a KMutex.
|
||||
*
|
||||
* @param[in] kmutex The KMutex pointer.
|
||||
*
|
||||
* @return Returns KRES_NO_PERMISSIONS if the current task
|
||||
* @return is not the owner. Otherwise KRES_OK.
|
||||
*/
|
||||
KRes unlockMutex(KMutex *const kmutex);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct KSema KSema;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new KSema.
|
||||
*
|
||||
* @param[in] count The initial count of the semaphore.
|
||||
*
|
||||
* @return The KSema pointer or NULL when out of memory.
|
||||
*/
|
||||
KSema* createSemaphore(int32_t count);
|
||||
|
||||
/**
|
||||
* @brief Deletes a KSema.
|
||||
*
|
||||
* @param[in] ksema The KSema handle.
|
||||
*/
|
||||
void deleteSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Polls a KSema.
|
||||
*
|
||||
* @param[in] ksema The KSema pointer.
|
||||
*
|
||||
* @return Returns KRES_OK or KRES_WOULD_BLOCK.
|
||||
*/
|
||||
KRes pollSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Decreases the semaphore and blocks if <=0.
|
||||
*
|
||||
* @param[in] ksema The KSema pointer.
|
||||
*
|
||||
* @return Returns the result. See Kres above.
|
||||
*/
|
||||
KRes waitForSemaphore(KSema *const ksema);
|
||||
|
||||
/**
|
||||
* @brief Increases the semaphore and wakes up signalCount waiting tasks if any.
|
||||
*
|
||||
* @param[in] ksema The KSema pointer.
|
||||
* @param[in] signalCount The number to increase the semaphore by.
|
||||
* @param[in] reschedule Set to true to immediately reschedule.
|
||||
*/
|
||||
void signalSemaphore(KSema *const ksema, uint32_t signalCount, bool reschedule);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2023 profi200
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,9 +18,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "types.h"
|
||||
#include "arm11/config.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -28,19 +26,20 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 sha1[20];
|
||||
char serial[4];
|
||||
u32 attr;
|
||||
} GbaDbEntry;
|
||||
static_assert(sizeof(GbaDbEntry) == 28, "Error: GBA DB entry struct is not packed!");
|
||||
typedef struct KTimer KTimer;
|
||||
|
||||
|
||||
|
||||
u16 detectSaveType(const u32 romSize, const u16 defaultSave);
|
||||
u16 getSaveType(const OafConfig *const cfg, const u32 romSize, const char *const savePath);
|
||||
KTimer* createTimer(bool pulse);
|
||||
|
||||
void deleteTimer(KTimer *const ktimer);
|
||||
|
||||
void startTimer(KTimer *const ktimer, uint32_t usec);
|
||||
|
||||
void stopTimer(KTimer *const ktimer);
|
||||
|
||||
KRes waitForTimer(KTimer *const ktimer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "asm_macros.h"
|
||||
|
||||
.arm
|
||||
.cpu mpcore
|
||||
.fpu vfpv2
|
||||
|
||||
|
||||
|
||||
@ void switchContextNoScratchRegs(u32 *curRegs, const u32 *newRegs)
|
||||
/*ASM_FUNC switchContextNoScratchRegs
|
||||
stmia r0!, {r4-r11, sp, lr}
|
||||
add r0, r0, #20 @ Skip r0-r3, r12
|
||||
adr r2, switchContextNoScratchRegs_end
|
||||
mrs r3, cpsr
|
||||
stmia r0, {r2, r3}
|
||||
ldmia r1!, {r4-r11, sp, lr}
|
||||
add r1, r1, #20 @ Skip r0-r3, r12
|
||||
rfeia r1
|
||||
switchContextNoScratchRegs_end:
|
||||
cpsie i
|
||||
bx lr
|
||||
|
||||
@ void switchContextAllRegs(u32 *curRegs, const u32 *newRegs)
|
||||
ASM_FUNC switchContextAllRegs
|
||||
stmia r0!, {r4-r11, sp, lr}
|
||||
add r0, r0, #20 @ Skip r0-r3, r12
|
||||
adr r2, switchContextAllRegs_end
|
||||
mrs r3, cpsr
|
||||
stmia r0, {r2, r3}
|
||||
ldmia r1!, {r4-r11, sp, lr}
|
||||
ldr r3, [r1, #24] @ cpsr
|
||||
cps #19 @ SVC mode
|
||||
msr spsr_fsxc, r3
|
||||
ldmia r1, {r0-r3, r12, pc}^
|
||||
switchContextAllRegs_end:
|
||||
cpsie i
|
||||
bx lr*/
|
||||
|
||||
@ KRes switchContext(KRes res, uintptr_t *oldSp, uintptr_t newSp);
|
||||
BEGIN_ASM_FUNC switchContext
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
str sp, [r1]
|
||||
mov sp, r2
|
||||
ldmfd sp!, {r4-r11, lr}
|
||||
bx lr
|
||||
END_ASM_FUNC
|
||||
|
||||
|
||||
.pool
|
|
@ -0,0 +1,258 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdnoreturn.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "kernel.h"
|
||||
#include "internal/config.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/kmemcpy_set.h"
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/util.h"
|
||||
#include "internal/list.h"
|
||||
#include "internal/contextswitch.h"
|
||||
#include "arm.h"
|
||||
|
||||
|
||||
static TaskCb *g_curTask = NULL;
|
||||
static u32 g_readyBitmap = 0;
|
||||
static ListNode g_runQueues[MAX_PRIO_BITS] = {0};
|
||||
static SlabHeap g_taskSlab = {0};
|
||||
static u32 g_numTasks = 0;
|
||||
static TaskCb *g_curDeadTask = NULL; // TODO: Improve dead task handling.
|
||||
|
||||
|
||||
|
||||
static KRes scheduler(TaskState curTaskState);
|
||||
noreturn static void kernelIdleTask(void);
|
||||
|
||||
static void initKernelState(void)
|
||||
{
|
||||
for(int i = 0; i < MAX_PRIO_BITS; i++) listInit(&g_runQueues[i]);
|
||||
slabInit(&g_taskSlab, sizeof(TaskCb), MAX_TASKS);
|
||||
_eventSlabInit();
|
||||
_mutexSlabInit();
|
||||
_semaphoreSlabInit();
|
||||
//_timerInit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Public kernel API.
|
||||
*/
|
||||
// TODO: Are KTask handles needed? (for the main task)
|
||||
// TODO: Thread local storage. Needed?
|
||||
void kernelInit(uint8_t priority)
|
||||
{
|
||||
if(priority > MAX_PRIO_BITS - 1u) return;
|
||||
|
||||
// TODO: Split this mess into helper functions.
|
||||
initKernelState();
|
||||
|
||||
TaskCb *const idleT = (TaskCb*)slabAlloc(&g_taskSlab);
|
||||
void *const iStack = malloc(IDLE_STACK_SIZE);
|
||||
TaskCb *const mainT = (TaskCb*)slabCalloc(&g_taskSlab, sizeof(TaskCb));
|
||||
if(idleT == NULL || iStack == NULL || mainT == NULL)
|
||||
{
|
||||
slabFree(&g_taskSlab, idleT);
|
||||
free(iStack);
|
||||
slabFree(&g_taskSlab, mainT);
|
||||
return;
|
||||
}
|
||||
|
||||
cpuRegs *const regs = (cpuRegs*)(iStack + IDLE_STACK_SIZE - sizeof(cpuRegs));
|
||||
regs->lr = (u32)kernelIdleTask;
|
||||
idleT->prio = 1;
|
||||
// id is already set to 0.
|
||||
idleT->savedSp = (uintptr_t)regs;
|
||||
idleT->stack = iStack;
|
||||
|
||||
// Main task already running. Nothing more to setup.
|
||||
mainT->id = 1;
|
||||
mainT->prio = priority;
|
||||
|
||||
g_curTask = mainT;
|
||||
g_readyBitmap = 1u<<1; // The idle task has priority 1 and is always ready.
|
||||
listPush(&g_runQueues[1], &idleT->node);
|
||||
g_numTasks = 2;
|
||||
}
|
||||
|
||||
KTask* createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg)
|
||||
{
|
||||
if(priority > MAX_PRIO_BITS - 1u) return NULL;
|
||||
|
||||
// Make sure the stack is aligned to 8 bytes
|
||||
stackSize = (stackSize + 7u) & ~7u;
|
||||
|
||||
SlabHeap *const taskSlabPtr = &g_taskSlab;
|
||||
TaskCb *const newT = (TaskCb*)slabAlloc(taskSlabPtr);
|
||||
void *const stack = malloc(stackSize);
|
||||
if(newT == NULL || stack == NULL)
|
||||
{
|
||||
slabFree(taskSlabPtr, newT);
|
||||
free(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cpuRegs *const regs = (cpuRegs*)(stack + stackSize - sizeof(cpuRegs));
|
||||
kmemset((u32*)regs, 0, sizeof(cpuRegs));
|
||||
regs->lr = (u32)entry;
|
||||
newT->prio = priority;
|
||||
newT->id = g_numTasks; // TODO: Make this more sophisticated.
|
||||
// TODO: This is kinda hacky abusing the result member to pass the task arg.
|
||||
// Pass args and stuff on the stack?
|
||||
newT->res = (KRes)taskArg;
|
||||
newT->savedSp = (uintptr_t)regs;
|
||||
newT->stack = stack;
|
||||
|
||||
kernelLock();
|
||||
listPush(&g_runQueues[priority], &newT->node);
|
||||
g_readyBitmap |= 1u<<priority;
|
||||
g_numTasks++;
|
||||
kernelUnlock();
|
||||
|
||||
return newT;
|
||||
}
|
||||
|
||||
// TODO: setTaskPriority().
|
||||
|
||||
void yieldTask(void)
|
||||
{
|
||||
kernelLock();
|
||||
scheduler(TASK_STATE_RUNNING);
|
||||
}
|
||||
|
||||
void taskExit(void)
|
||||
{
|
||||
kernelLock();
|
||||
scheduler(TASK_STATE_DEAD);
|
||||
while(1); // TODO: panic?
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Internal functions.
|
||||
*/
|
||||
const TaskCb* getCurrentTask(void)
|
||||
{
|
||||
return g_curTask;
|
||||
}
|
||||
|
||||
// The wait queue and scheduler functions automatically unlock the kernel lock
|
||||
// and expect to be called with locked lock.
|
||||
KRes waitQueueBlock(ListNode *waitQueue)
|
||||
{
|
||||
listPush(waitQueue, &g_curTask->node);
|
||||
return scheduler(TASK_STATE_BLOCKED);
|
||||
}
|
||||
|
||||
bool waitQueueWakeN(ListNode *waitQueue, u32 wakeCount, KRes res, bool reschedule)
|
||||
{
|
||||
if(listEmpty(waitQueue) || !wakeCount)
|
||||
{
|
||||
kernelUnlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 readyBitmap = 0;
|
||||
ListNode *const runQueues = g_runQueues;
|
||||
if(LIKELY(reschedule))
|
||||
{
|
||||
// Put ourself on top of the list first so we run immediately
|
||||
// after the woken tasks to finish the work we were doing.
|
||||
// TODO: Verify if this is a good strategy.
|
||||
TaskCb *const curTask = g_curTask;
|
||||
const u8 curPrio = curTask->prio;
|
||||
listPushTail(&runQueues[curPrio], &curTask->node);
|
||||
readyBitmap = 1u<<curPrio;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/*
|
||||
* Edge case:
|
||||
* 2 tasks, 1 single shot event. Task 2 waits first and then task 1.
|
||||
* When signaled (by an IRQ) only task 1 will ever run instead of
|
||||
* alternating between both because task 1 always lands on the
|
||||
* head (as intended) but on wakeup we take N tasks from the head
|
||||
* to preserve order.
|
||||
*
|
||||
* Workaround:
|
||||
* Take tasks from the tail instead. This will however punish
|
||||
* the longest waiting tasks unnecessarily.
|
||||
*/
|
||||
//TaskCb *task = LIST_ENTRY(listPopHead(waitQueue), TaskCb, node);
|
||||
TaskCb *task = LIST_ENTRY(listPop(waitQueue), TaskCb, node);
|
||||
readyBitmap |= 1u<<task->prio;
|
||||
task->res = res;
|
||||
listPushTail(&runQueues[task->prio], &task->node);
|
||||
} while(!listEmpty(waitQueue) && --wakeCount);
|
||||
g_readyBitmap |= readyBitmap;
|
||||
|
||||
if(LIKELY(reschedule)) scheduler(TASK_STATE_RUNNING_SHORT);
|
||||
else kernelUnlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static KRes scheduler(TaskState curTaskState)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if((__getCpsr() & PSR_MODE_MASK) != PSR_SYS_MODE) panic();
|
||||
#endif
|
||||
|
||||
TaskCb *const curDeadTask = g_curDeadTask;
|
||||
// TODO: Get rid of this and find a better way.
|
||||
if(UNLIKELY(curDeadTask != NULL))
|
||||
{
|
||||
free(curDeadTask->stack);
|
||||
slabFree(&g_taskSlab, curDeadTask);
|
||||
g_curDeadTask = NULL;
|
||||
}
|
||||
|
||||
TaskCb *const curTask = g_curTask;
|
||||
u32 readyBitmap = g_readyBitmap;
|
||||
ListNode *const runQueues = g_runQueues;
|
||||
// Warning. The result is undefined if the input of this builtin is 0!
|
||||
// Edge case: All tasks are sleeping except the (curently running) idle task.
|
||||
// g_readyBitmap is 0 in this case.
|
||||
const unsigned int readyPrio = (readyBitmap ? 31u - __builtin_clz(readyBitmap) : 0u);
|
||||
if(LIKELY(curTaskState == TASK_STATE_RUNNING))
|
||||
{
|
||||
const u8 curPrio = curTask->prio;
|
||||
|
||||
if(readyPrio < curPrio)
|
||||
{
|
||||
kernelUnlock();
|
||||
return KRES_OK;
|
||||
}
|
||||
|
||||
listPush(&runQueues[curPrio], &curTask->node);
|
||||
readyBitmap |= 1u<<curPrio;
|
||||
}
|
||||
else if(UNLIKELY(curTaskState == TASK_STATE_DEAD))
|
||||
{
|
||||
g_curDeadTask = curTask;
|
||||
g_numTasks--;
|
||||
}
|
||||
|
||||
TaskCb *newTask = LIST_ENTRY(listPop(&runQueues[readyPrio]), TaskCb, node);
|
||||
if(listEmpty(&runQueues[readyPrio])) readyBitmap &= ~(1u<<readyPrio);
|
||||
g_readyBitmap = readyBitmap;
|
||||
|
||||
TaskCb *oldTask = curTask;
|
||||
g_curTask = newTask;
|
||||
const KRes res = newTask->res;
|
||||
kernelUnlock();
|
||||
|
||||
return switchContext(res, &oldTask->savedSp, newTask->savedSp);
|
||||
}
|
||||
|
||||
// TODO: Cleanup deleted tasks in here? Or create a worker task?
|
||||
noreturn static void kernelIdleTask(void)
|
||||
{
|
||||
do
|
||||
{
|
||||
__wfi();
|
||||
kernelLock();
|
||||
scheduler(TASK_STATE_RUNNING);
|
||||
} while(1);
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "kevent.h"
|
||||
#include "internal/list.h"
|
||||
#include "arm11/hardware/interrupt.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/config.h"
|
||||
|
||||
|
||||
struct KEvent
|
||||
{
|
||||
bool signaled;
|
||||
const bool oneShot;
|
||||
ListNode waitQueue;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_eventSlab = {0};
|
||||
static KEvent *g_irqEventTable[128 - 32] = {0}; // 128 - 32 private interrupts.
|
||||
|
||||
|
||||
|
||||
void _eventSlabInit(void)
|
||||
{
|
||||
slabInit(&g_eventSlab, sizeof(KEvent), MAX_EVENTS);
|
||||
}
|
||||
|
||||
static void eventIrqHandler(u32 intSource)
|
||||
{
|
||||
signalEvent(g_irqEventTable[intSource - 32], false);
|
||||
}
|
||||
|
||||
KEvent* createEvent(bool oneShot)
|
||||
{
|
||||
KEvent *const kevent = (KEvent*)slabAlloc(&g_eventSlab);
|
||||
|
||||
kevent->signaled = false;
|
||||
*(bool*)&kevent->oneShot = oneShot;
|
||||
listInit(&kevent->waitQueue);
|
||||
|
||||
return kevent;
|
||||
}
|
||||
|
||||
void deleteEvent(KEvent *const kevent)
|
||||
{
|
||||
kernelLock();
|
||||
waitQueueWakeN(&kevent->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_eventSlab, kevent);
|
||||
}
|
||||
|
||||
// TODO: Critical sections needed for bind/unbind?
|
||||
void bindInterruptToEvent(KEvent *const kevent, uint8_t id, uint8_t prio)
|
||||
{
|
||||
if(id < 32 || id > 127) return;
|
||||
|
||||
g_irqEventTable[id - 32] = kevent;
|
||||
IRQ_registerIsr(id, prio, 0, eventIrqHandler);
|
||||
}
|
||||
|
||||
void unbindInterruptEvent(uint8_t id)
|
||||
{
|
||||
if(id < 32 || id > 127) return;
|
||||
|
||||
g_irqEventTable[id - 32] = NULL;
|
||||
IRQ_unregisterIsr(id);
|
||||
}
|
||||
|
||||
// TODO: Timeout.
|
||||
KRes waitForEvent(KEvent *const kevent)
|
||||
{
|
||||
KRes res;
|
||||
|
||||
kernelLock();
|
||||
if(kevent->signaled)
|
||||
{
|
||||
if(kevent->oneShot) kevent->signaled = false;
|
||||
kernelUnlock();
|
||||
res = KRES_OK;
|
||||
}
|
||||
else res = waitQueueBlock(&kevent->waitQueue);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void signalEvent(KEvent *const kevent, bool reschedule)
|
||||
{
|
||||
kernelLock();
|
||||
if(!kevent->signaled)
|
||||
{
|
||||
if(kevent->oneShot)
|
||||
{
|
||||
if(!waitQueueWakeN(&kevent->waitQueue, 1, KRES_OK, reschedule))
|
||||
kevent->signaled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
kevent->signaled = true;
|
||||
waitQueueWakeN(&kevent->waitQueue, (u32)-1, KRES_OK, reschedule);
|
||||
}
|
||||
}
|
||||
else kernelUnlock();
|
||||
}
|
||||
|
||||
void clearEvent(KEvent *const kevent)
|
||||
{
|
||||
kernelLock(); // TODO: Can we do this without locks?
|
||||
kevent->signaled = false;
|
||||
kernelUnlock();
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@ Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s
|
||||
|
||||
.arm
|
||||
.cpu arm946e-s
|
||||
.fpu softvfp
|
||||
|
||||
|
||||
|
||||
@ void kmemcpy(u32 *restrict dst, const u32 *restrict src, u32 size);
|
||||
@ void iokmemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size);
|
||||
.section .text.kmemcpy, "ax", %progbits
|
||||
.global kmemcpy
|
||||
.global iokmemcpy
|
||||
.type kmemcpy %function
|
||||
.type iokmemcpy %function
|
||||
.align 2
|
||||
kmemcpy:
|
||||
iokmemcpy:
|
||||
bics r12, r2, #31
|
||||
beq kmemcpy_test_words
|
||||
stmfd sp!, {r4-r10}
|
||||
kmemcpy_blocks_lp:
|
||||
ldmia r1!, {r3-r10}
|
||||
subs r12, #32
|
||||
stmia r0!, {r3-r10}
|
||||
bne kmemcpy_blocks_lp
|
||||
ldmfd sp!, {r4-r10}
|
||||
kmemcpy_test_words:
|
||||
ands r12, r2, #28
|
||||
beq kmemcpy_halfword_byte
|
||||
kmemcpy_words_lp:
|
||||
ldr r3, [r1], #4
|
||||
subs r12, #4
|
||||
str r3, [r0], #4
|
||||
bne kmemcpy_words_lp
|
||||
kmemcpy_halfword_byte:
|
||||
tst r2, #2
|
||||
ldrneh r3, [r1], #2
|
||||
strneh r3, [r0], #2
|
||||
tst r2, #1
|
||||
ldrneb r3, [r1]
|
||||
strneb r3, [r0]
|
||||
bx lr
|
||||
|
||||
|
||||
@ void kmemset(u32 *ptr, u32 value, u32 size);
|
||||
@ void iokmemset(vu32 *ptr, u32 value, u32 size);
|
||||
.section .text.kmemset, "ax", %progbits
|
||||
.global kmemset
|
||||
.global iokmemset
|
||||
.type kmemset %function
|
||||
.type iokmemset %function
|
||||
.align 2
|
||||
kmemset:
|
||||
iokmemset:
|
||||
bics r12, r2, #31
|
||||
beq kmemset_test_words
|
||||
stmfd sp!, {r4-r9}
|
||||
mov r3, r1
|
||||
mov r4, r1
|
||||
mov r5, r1
|
||||
mov r6, r1
|
||||
mov r7, r1
|
||||
mov r8, r1
|
||||
mov r9, r1
|
||||
kmemset_blocks_lp:
|
||||
stmia r0!, {r1, r3-r9}
|
||||
subs r12, #32
|
||||
bne kmemset_blocks_lp
|
||||
ldmfd sp!, {r4-r9}
|
||||
kmemset_test_words:
|
||||
ands r12, r2, #28
|
||||
beq kmemset_halfword_byte
|
||||
kmemset_words_lp:
|
||||
str r1, [r0], #4
|
||||
subs r12, #4
|
||||
bne kmemset_words_lp
|
||||
kmemset_halfword_byte:
|
||||
tst r2, #2
|
||||
strneh r1, [r0], #2
|
||||
tst r2, #1
|
||||
strneb r1, [r0]
|
||||
bx lr
|
|
@ -0,0 +1,88 @@
|
|||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "kmutex.h"
|
||||
#include "internal/list.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/util.h"
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/config.h"
|
||||
|
||||
|
||||
struct KMutex
|
||||
{
|
||||
const TaskCb *owner;
|
||||
ListNode waitQueue;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_mutexSlab = {0};
|
||||
|
||||
|
||||
|
||||
void _mutexSlabInit(void)
|
||||
{
|
||||
slabInit(&g_mutexSlab, sizeof(KMutex), MAX_MUTEXES);
|
||||
}
|
||||
|
||||
// TODO: Test mutex with multiple cores.
|
||||
KMutex* createMutex(void)
|
||||
{
|
||||
KMutex *const kmutex = (KMutex*)slabAlloc(&g_mutexSlab);
|
||||
|
||||
kmutex->owner = NULL;
|
||||
listInit(&kmutex->waitQueue);
|
||||
|
||||
return kmutex;
|
||||
}
|
||||
|
||||
void deleteMutex(KMutex *const kmutex)
|
||||
{
|
||||
kernelLock();
|
||||
waitQueueWakeN(&kmutex->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_mutexSlab, kmutex);
|
||||
}
|
||||
|
||||
KRes lockMutex(KMutex *const kmutex)
|
||||
{
|
||||
KRes res;
|
||||
|
||||
do
|
||||
{
|
||||
kernelLock();
|
||||
if(UNLIKELY(kmutex->owner != NULL))
|
||||
{
|
||||
res = waitQueueBlock(&kmutex->waitQueue);
|
||||
if(UNLIKELY(res != KRES_OK)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
kmutex->owner = getCurrentTask();
|
||||
kernelUnlock();
|
||||
res = KRES_OK;
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: Test if it works and only unlocks if current task == owner.
|
||||
KRes unlockMutex(KMutex *const kmutex)
|
||||
{
|
||||
KRes res = KRES_OK;
|
||||
|
||||
kernelLock();
|
||||
if(LIKELY(kmutex->owner != NULL))
|
||||
{
|
||||
if(LIKELY(kmutex->owner == getCurrentTask()))
|
||||
{
|
||||
kmutex->owner = NULL;
|
||||
waitQueueWakeN(&kmutex->waitQueue, 1, KRES_OK, true);
|
||||
}
|
||||
else res = KRES_NO_PERMISSIONS;
|
||||
}
|
||||
else kernelUnlock();
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "ksemaphore.h"
|
||||
#include "internal/list.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/util.h"
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/config.h"
|
||||
|
||||
|
||||
struct KSema
|
||||
{
|
||||
s32 count;
|
||||
ListNode waitQueue;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_semaSlab = {0};
|
||||
|
||||
|
||||
|
||||
void _semaphoreSlabInit(void)
|
||||
{
|
||||
slabInit(&g_semaSlab, sizeof(KSema), MAX_SEMAPHORES);
|
||||
}
|
||||
|
||||
// TODO: Test semaphore with multiple cores.
|
||||
KSema* createSemaphore(int32_t count)
|
||||
{
|
||||
KSema *const ksema = (KSema*)slabAlloc(&g_semaSlab);
|
||||
|
||||
ksema->count = count;
|
||||
listInit(&ksema->waitQueue);
|
||||
|
||||
return ksema;
|
||||
}
|
||||
|
||||
void deleteSemaphore(KSema *const ksema)
|
||||
{
|
||||
kernelLock();
|
||||
waitQueueWakeN(&ksema->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_semaSlab, ksema);
|
||||
}
|
||||
|
||||
KRes pollSemaphore(KSema *const ksema)
|
||||
{
|
||||
KRes res;
|
||||
|
||||
// TODO: Plain spinlocks instead?
|
||||
kernelLock();
|
||||
if(UNLIKELY(ksema->count <= 0)) res = KRES_WOULD_BLOCK;
|
||||
else {ksema->count--; res = KRES_OK;}
|
||||
kernelUnlock();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
KRes waitForSemaphore(KSema *const ksema)
|
||||
{
|
||||
KRes res;
|
||||
|
||||
kernelLock();
|
||||
if(UNLIKELY(--ksema->count < 0)) res = waitQueueBlock(&ksema->waitQueue);
|
||||
else {kernelUnlock(); res = KRES_OK;}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void signalSemaphore(KSema *const ksema, uint32_t signalCount, bool reschedule)
|
||||
{
|
||||
kernelLock();
|
||||
//if(UNLIKELY(++ksema->count <= 0))
|
||||
if(UNLIKELY((ksema->count += signalCount) <= 0))
|
||||
waitQueueWakeN(&ksema->waitQueue, signalCount, KRES_OK, reschedule);
|
||||
else kernelUnlock();
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "types.h"
|
||||
#include "ktimer.h"
|
||||
#include "internal/list.h"
|
||||
#include "arm11/hardware/interrupt.h"
|
||||
#include "arm11/hardware/timer.h"
|
||||
#include "internal/kernel_private.h"
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/config.h"
|
||||
//#include "arm11/fmt.h"
|
||||
|
||||
|
||||
/*struct KTimer
|
||||
{
|
||||
ListNode node;
|
||||
u32 delta;
|
||||
u32 ticks;
|
||||
const bool pulse;
|
||||
ListNode waitQueue;
|
||||
};
|
||||
|
||||
|
||||
static SlabHeap g_timerSlab = {0};
|
||||
static ListNode g_deltaQueue = {0};
|
||||
|
||||
|
||||
|
||||
static void timerIsr(UNUSED u32 intSource);
|
||||
static void addToDeltaQueue(KTimer *const timer, u32 ticks);
|
||||
|
||||
void _timerInit(void)
|
||||
{
|
||||
slabInit(&g_timerSlab, sizeof(KTimer), MAX_TIMERS);
|
||||
listInit(&g_deltaQueue);
|
||||
IRQ_registerIsr(IRQ_TIMER, 12, 0, timerIsr);
|
||||
}
|
||||
|
||||
KTimer* createTimer(bool pulse)
|
||||
{
|
||||
KTimer *const ktimer = (KTimer*)slabAlloc(&g_timerSlab);
|
||||
|
||||
*(bool*)&ktimer->pulse = pulse;
|
||||
listInit(&ktimer->waitQueue);
|
||||
|
||||
return ktimer;
|
||||
}
|
||||
|
||||
void deleteTimer(KTimer *const ktimer)
|
||||
{
|
||||
kernelLock();
|
||||
waitQueueWakeN(&ktimer->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
|
||||
|
||||
slabFree(&g_timerSlab, ktimer);
|
||||
}
|
||||
|
||||
static void timerIsr(UNUSED u32 intSource)
|
||||
{
|
||||
kernelLock();
|
||||
//if(listEmpty(&g_deltaQueue)) *((vu32*)4) = 4; // This should never happen
|
||||
KTimer *ktimer = LIST_ENTRY(listPop(&g_deltaQueue), KTimer, node);
|
||||
if(ktimer->pulse) addToDeltaQueue(ktimer, ktimer->ticks);
|
||||
if(!listEmpty(&g_deltaQueue))
|
||||
{
|
||||
// Don't use fp math in ISRs.
|
||||
TIMER_start(1, LIST_FIRST_ENTRY(&g_deltaQueue, KTimer, node)->delta, false, true);
|
||||
}
|
||||
waitQueueWakeN(&ktimer->waitQueue, (u32)-1, KRES_OK, false);
|
||||
}
|
||||
|
||||
static void addToDeltaQueue(KTimer *const ktimer, u32 ticks)
|
||||
{
|
||||
KTimer *pos;
|
||||
u32 deltaSum = 0;
|
||||
LIST_FOR_EACH_ENTRY(pos, &g_deltaQueue, node)
|
||||
{
|
||||
deltaSum += pos->delta;
|
||||
if(deltaSum > ticks)
|
||||
{
|
||||
ktimer->delta = ticks - (deltaSum - pos->delta);
|
||||
listAddBefore(&pos->node, &ktimer->node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ktimer->delta = ticks;
|
||||
listPush(&g_deltaQueue, &ktimer->node);
|
||||
}
|
||||
|
||||
void startTimer(KTimer *const ktimer, uint32_t usec)
|
||||
{
|
||||
const u32 ticks = TIMER_FREQ(1, 1000000) * usec;
|
||||
ktimer->ticks = ticks;
|
||||
|
||||
kernelLock();
|
||||
const bool firstTimer = listEmpty(&g_deltaQueue);
|
||||
addToDeltaQueue(ktimer, ticks);
|
||||
kernelUnlock();
|
||||
if(firstTimer) TIMER_start(1, ticks, false, true);
|
||||
}
|
||||
|
||||
void stopTimer(KTimer *const ktimer)
|
||||
{
|
||||
}
|
||||
|
||||
KRes waitForTimer(KTimer *const ktimer)
|
||||
{
|
||||
kernelLock();
|
||||
return waitQueueBlock(&ktimer->waitQueue);
|
||||
}*/
|
|
@ -0,0 +1,44 @@
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "internal/slabheap.h"
|
||||
#include "internal/kmemcpy_set.h"
|
||||
|
||||
|
||||
|
||||
void slabInit(SlabHeap *slab, size_t objSize, size_t num)
|
||||
{
|
||||
if(objSize < sizeof(SlabHeap) || !num) return;
|
||||
|
||||
listInit(slab);
|
||||
|
||||
void *pool = malloc(objSize * num);
|
||||
if(!pool) return;
|
||||
do
|
||||
{
|
||||
listPush(slab, (SlabHeap*)pool);
|
||||
pool += objSize;
|
||||
} while(--num);
|
||||
}
|
||||
|
||||
void* slabAlloc(SlabHeap *slab)
|
||||
{
|
||||
if(!slab || listEmpty(slab)) return NULL;
|
||||
|
||||
return listPop(slab);
|
||||
}
|
||||
|
||||
void* slabCalloc(SlabHeap *slab, size_t clrSize)
|
||||
{
|
||||
void *const ptr = slabAlloc(slab);
|
||||
if(ptr) kmemset(ptr, 0, clrSize);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void slabFree(SlabHeap *slab, void *ptr)
|
||||
{
|
||||
if(!slab || !ptr) return;
|
||||
|
||||
// Keep gaps filled by allocating the same mem
|
||||
// again next time an object is allocated.
|
||||
listPushTail(slab, (SlabHeap*)ptr);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
Subproject commit ed4525140dacc54e5924f60b25a00c69371866a0
|
|
@ -1 +0,0 @@
|
|||
Subproject commit f6717f66858634b677ed695ee346a89db7684b43
|
Binary file not shown.
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
static rbtree_t sAddrMap;
|
||||
|
||||
struct addrMapNode
|
||||
{
|
||||
rbtree_node node;
|
||||
MemChunk chunk;
|
||||
};
|
||||
|
||||
#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node)
|
||||
|
||||
static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs)
|
||||
{
|
||||
auto lhs = getAddrMapNode(_lhs)->chunk.addr;
|
||||
auto rhs = getAddrMapNode(_rhs)->chunk.addr;
|
||||
if (lhs < rhs)
|
||||
return -1;
|
||||
if (lhs > rhs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void addrMapNodeDestructor(rbtree_node_t* a)
|
||||
{
|
||||
free(getAddrMapNode(a));
|
||||
}
|
||||
|
||||
static addrMapNode* getNode(void* addr)
|
||||
{
|
||||
addrMapNode n;
|
||||
n.chunk.addr = (u8*)addr;
|
||||
auto p = rbtree_find(&sAddrMap, &n.node);
|
||||
return p ? getAddrMapNode(p) : nullptr;
|
||||
}
|
||||
|
||||
static addrMapNode* newNode(const MemChunk& chunk)
|
||||
{
|
||||
auto p = (addrMapNode*)malloc(sizeof(addrMapNode));
|
||||
if (!p) return nullptr;
|
||||
p->chunk = chunk;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void delNode(addrMapNode* node)
|
||||
{
|
||||
rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor);
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
#include "mem_pool.h"
|
||||
|
||||
/*
|
||||
// This method is currently unused
|
||||
void MemPool::CoalesceLeft(MemBlock* b)
|
||||
{
|
||||
auto curPtr = b->base;
|
||||
for (auto p = b->prev; p; p = p->prev)
|
||||
{
|
||||
if ((p->base + p->size) != curPtr) break;
|
||||
curPtr = p->base;
|
||||
p->size += b->size;
|
||||
DelBlock(b);
|
||||
b = p;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void MemPool::CoalesceRight(MemBlock* b)
|
||||
{
|
||||
auto curPtr = b->base + b->size;
|
||||
auto next = b->next;
|
||||
for (auto n = next; n; n = next)
|
||||
{
|
||||
next = n->next;
|
||||
if (n->base != curPtr) break;
|
||||
b->size += n->size;
|
||||
curPtr += n->size;
|
||||
DelBlock(n);
|
||||
}
|
||||
}
|
||||
|
||||
bool MemPool::Allocate(MemChunk& chunk, u32 size, int align)
|
||||
{
|
||||
// Don't shift out of bounds (CERT INT34-C)
|
||||
if(align >= 32 || align < 0)
|
||||
return false;
|
||||
|
||||
// Alignment must not be 0
|
||||
if(align == 0)
|
||||
return false;
|
||||
|
||||
u32 alignMask = (1 << align) - 1;
|
||||
|
||||
// Check if size doesn't fit neatly in alignment
|
||||
if(size & alignMask)
|
||||
{
|
||||
// Make sure addition won't overflow (CERT INT30-C)
|
||||
if(size > UINT32_MAX - alignMask)
|
||||
return false;
|
||||
|
||||
// Pad size to next alignment
|
||||
size = (size + alignMask) &~ alignMask;
|
||||
}
|
||||
|
||||
// Find the first suitable block
|
||||
for (auto b = first; b; b = b->next)
|
||||
{
|
||||
auto addr = b->base;
|
||||
u32 begWaste = (u32)addr & alignMask;
|
||||
if (begWaste > 0) begWaste = alignMask + 1 - begWaste;
|
||||
if (begWaste > b->size) continue;
|
||||
addr += begWaste;
|
||||
u32 bSize = b->size - begWaste;
|
||||
if (bSize < size) continue;
|
||||
|
||||
// Found space!
|
||||
chunk.addr = addr;
|
||||
chunk.size = size;
|
||||
|
||||
// Resize the block
|
||||
if (!begWaste)
|
||||
{
|
||||
b->base += size;
|
||||
b->size -= size;
|
||||
if (!b->size)
|
||||
DelBlock(b);
|
||||
} else
|
||||
{
|
||||
auto nAddr = addr + size;
|
||||
auto nSize = bSize - size;
|
||||
b->size = begWaste;
|
||||
if (nSize)
|
||||
{
|
||||
// We need to add the tail chunk that wasn't used to the list
|
||||
auto n = MemBlock::Create(nAddr, nSize);
|
||||
if (n) InsertAfter(b, n);
|
||||
else chunk.size += nSize; // we have no choice but to waste the space.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MemPool::Deallocate(const MemChunk& chunk)
|
||||
{
|
||||
u8* cAddr = chunk.addr;
|
||||
auto cSize = chunk.size;
|
||||
bool done = false;
|
||||
|
||||
// Try to merge the chunk somewhere into the list
|
||||
for (auto b = first; !done && b; b = b->next)
|
||||
{
|
||||
auto addr = b->base;
|
||||
if (addr > cAddr)
|
||||
{
|
||||
if ((cAddr + cSize) == addr)
|
||||
{
|
||||
// Merge the chunk to the left of the block
|
||||
b->base = cAddr;
|
||||
b->size += cSize;
|
||||
} else
|
||||
{
|
||||
// We need to insert a new block
|
||||
auto c = MemBlock::Create(cAddr, cSize);
|
||||
if (c) InsertBefore(b, c);
|
||||
}
|
||||
done = true;
|
||||
} else if ((b->base + b->size) == cAddr)
|
||||
{
|
||||
// Coalesce to the right
|
||||
b->size += cSize;
|
||||
CoalesceRight(b);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
// Either the list is empty or the chunk address is past the end
|
||||
// address of the last block -- let's add a new block at the end
|
||||
auto b = MemBlock::Create(cAddr, cSize);
|
||||
if (b) AddBlock(b);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void MemPool::Dump(const char* title)
|
||||
{
|
||||
printf("<%s> VRAM Pool Dump\n", title);
|
||||
for (auto b = first; b; b = b->next)
|
||||
printf(" - %p (%u bytes)\n", b->base, b->size);
|
||||
}
|
||||
*/
|
||||
|
||||
u32 MemPool::GetFreeSpace()
|
||||
{
|
||||
u32 acc = 0;
|
||||
for (auto b = first; b; b = b->next)
|
||||
acc += b->size;
|
||||
return acc;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct MemChunk
|
||||
{
|
||||
u8* addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct MemBlock
|
||||
{
|
||||
MemBlock *prev, *next;
|
||||
u8* base;
|
||||
u32 size;
|
||||
|
||||
static MemBlock* Create(u8* base, u32 size)
|
||||
{
|
||||
auto b = (MemBlock*)malloc(sizeof(MemBlock));
|
||||
if (!b) return nullptr;
|
||||
b->prev = nullptr;
|
||||
b->next = nullptr;
|
||||
b->base = base;
|
||||
b->size = size;
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
struct MemPool
|
||||
{
|
||||
MemBlock *first, *last;
|
||||
|
||||
bool Ready() { return first != nullptr; }
|
||||
|
||||
void AddBlock(MemBlock* blk)
|
||||
{
|
||||
blk->prev = last;
|
||||
if (last) last->next = blk;
|
||||
if (!first) first = blk;
|
||||
last = blk;
|
||||
}
|
||||
|
||||
void DelBlock(MemBlock* b)
|
||||
{
|
||||
auto prev = b->prev, &pNext = prev ? prev->next : first;
|
||||
auto next = b->next, &nPrev = next ? next->prev : last;
|
||||
pNext = next;
|
||||
nPrev = prev;
|
||||
free(b);
|
||||
}
|
||||
|
||||
void InsertBefore(MemBlock* b, MemBlock* p)
|
||||
{
|
||||
auto prev = b->prev, &pNext = prev ? prev->next : first;
|
||||
b->prev = p;
|
||||
p->next = b;
|
||||
p->prev = prev;
|
||||
pNext = p;
|
||||
}
|
||||
|
||||
void InsertAfter(MemBlock* b, MemBlock* n)
|
||||
{
|
||||
auto next = b->next, &nPrev = next ? next->prev : last;
|
||||
b->next = n;
|
||||
n->prev = b;
|
||||
n->next = next;
|
||||
nPrev = n;
|
||||
}
|
||||
|
||||
//void CoalesceLeft(MemBlock* b);
|
||||
void CoalesceRight(MemBlock* b);
|
||||
|
||||
bool Allocate(MemChunk& chunk, u32 size, int align);
|
||||
void Deallocate(const MemChunk& chunk);
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
MemBlock* next = nullptr;
|
||||
for (auto b = first; b; b = next)
|
||||
{
|
||||
next = b->next;
|
||||
free(b);
|
||||
}
|
||||
first = nullptr;
|
||||
last = nullptr;
|
||||
}
|
||||
|
||||
//void Dump(const char* title);
|
||||
u32 GetFreeSpace();
|
||||
};
|
|
@ -0,0 +1,95 @@
|
|||
extern "C"
|
||||
{
|
||||
#include "types.h"
|
||||
#include "arm11/allocator/vram.h"
|
||||
#include "arm11/util/rbtree.h"
|
||||
}
|
||||
|
||||
#include "mem_pool.h"
|
||||
#include "addrmap.h"
|
||||
|
||||
static MemPool sVramPool;
|
||||
|
||||
static bool vramInit()
|
||||
{
|
||||
auto blk = MemBlock::Create((u8*)0x18000000, 0x00600000);
|
||||
if (blk)
|
||||
{
|
||||
sVramPool.AddBlock(blk);
|
||||
rbtree_init(&sAddrMap, addrMapNodeComparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* vramMemAlign(size_t size, size_t alignment)
|
||||
{
|
||||
// Enforce minimum alignment
|
||||
if (alignment < 16)
|
||||
alignment = 16;
|
||||
|
||||
// Convert alignment to shift amount
|
||||
int shift;
|
||||
for (shift = 4; shift < 32; shift ++)
|
||||
{
|
||||
if ((1U<<shift) == alignment)
|
||||
break;
|
||||
}
|
||||
if (shift == 32) // Invalid alignment
|
||||
return nullptr;
|
||||
|
||||
// Initialize the pool if it is not ready
|
||||
if (!sVramPool.Ready() && !vramInit())
|
||||
return nullptr;
|
||||
|
||||
// Allocate the chunk
|
||||
MemChunk chunk;
|
||||
if (!sVramPool.Allocate(chunk, size, shift))
|
||||
return nullptr;
|
||||
|
||||
auto node = newNode(chunk);
|
||||
if (!node)
|
||||
{
|
||||
sVramPool.Deallocate(chunk);
|
||||
return nullptr;
|
||||
}
|
||||
if (rbtree_insert(&sAddrMap, &node->node)) {}
|
||||
return chunk.addr;
|
||||
}
|
||||
|
||||
void* vramAlloc(size_t size)
|
||||
{
|
||||
return vramMemAlign(size, 0x80);
|
||||
}
|
||||
|
||||
void* vramRealloc(void* mem, size_t size)
|
||||
{
|
||||
(void)mem;
|
||||
(void)size;
|
||||
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t vramGetSize(void* mem)
|
||||
{
|
||||
auto node = getNode(mem);
|
||||
return node ? node->chunk.size : 0;
|
||||
}
|
||||
|
||||
void vramFree(void* mem)
|
||||
{
|
||||
auto node = getNode(mem);
|
||||
if (!node) return;
|
||||
|
||||
// Free the chunk
|
||||
sVramPool.Deallocate(node->chunk);
|
||||
|
||||
// Free the node
|
||||
delNode(node);
|
||||
}
|
||||
|
||||
u32 vramSpaceFree()
|
||||
{
|
||||
return sVramPool.GetFreeSpace();
|
||||
}
|
|
@ -1,323 +0,0 @@
|
|||
/*
|
||||
* This file is part of open_agb_firm
|
||||
* Copyright (C) 2024 profi200
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "arm11/config.h"
|
||||
#include "inih/ini.h"
|
||||
#include "util.h"
|
||||
#include "fsutil.h"
|
||||
|
||||
|
||||
#define INI_BUF_SIZE (1024u)
|
||||
#define DEFAULT_CONFIG "[general]\n" \
|
||||
"backlight=64\n" \
|
||||
"backlightSteps=5\n" \
|
||||
"directBoot=false\n" \
|
||||
"useGbaDb=true\n" \
|
||||
"useSavesFolder=true\n\n" \
|
||||
\
|
||||
"[video]\n" \
|
||||
"scaler=matrix\n" \
|
||||
"colorProfile=none\n" \
|
||||
"contrast=1.0\n" \
|
||||
"brightness=0.0\n" \
|
||||
"saturation=1.0\n\n" \
|
||||
\
|
||||
"[audio]\n" \
|
||||
"audioOut=auto\n" \
|
||||
"volume=127\n\n" \
|
||||
\
|
||||
"[advanced]\n" \
|
||||
"saveOverride=false\n" \
|
||||
"defaultSave=sram_256k"
|
||||
|
||||
|
||||
|
||||
// Default config.
|
||||
OafConfig g_oafConfig =
|
||||
{
|
||||
// [general]
|
||||
64, // backlight
|
||||
5, // backlightSteps
|
||||
false, // directBoot
|
||||
true, // useGbaDb
|
||||
true, // useSavesFolder
|
||||
|
||||
// [video]
|
||||
2, // scaler
|
||||
0, // colorProfile
|
||||
1.f, // contrast
|
||||
0.f, // brightness
|
||||
1.f, // saturation
|
||||
|
||||
// [audio]
|
||||
0, // Automatic audio output.
|
||||
127, // Control via volume slider.
|
||||
|
||||
// [input]
|
||||
{ // buttonMaps
|
||||
0, // A
|
||||
0, // B
|
||||
0, // Select
|
||||
0, // Start
|
||||
0, // Right
|
||||
0, // Left
|
||||
0, // Up
|
||||
0, // Down
|
||||
0, // R
|
||||
0 // L
|
||||
},
|
||||
|
||||
// [game]
|
||||
0, // saveSlot
|
||||
255, // saveType
|
||||
|
||||
// [advanced]
|
||||
false, // saveOverride
|
||||
14 // defaultSave
|
||||
};
|
||||
|
||||
|
||||
|
||||
static u32 parseButtons(const char *str)
|
||||
{
|
||||
if(str == NULL || *str == '\0') return 0;
|
||||
|
||||
char buf[32]; // Should be enough for all useful mappings.
|
||||
buf[31] = '\0';
|
||||
strncpy(buf, str, 31);
|
||||
|
||||
char *bufPtr = buf;
|
||||
static const char *const buttonStrLut[32] =
|
||||
{
|
||||
"A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN",
|
||||
"R", "L", "X", "Y", "", "", "ZL", "ZR",
|
||||
"", "", "", "", "TOUCH", "", "", "",
|
||||
"CS_RIGHT", "CS_LEFT", "CS_UP", "CS_DOWN", "CP_RIGHT", "CP_LEFT", "CP_UP", "CP_DOWN"
|
||||
};
|
||||
u32 map = 0;
|
||||
while(1)
|
||||
{
|
||||
char *const nextDelimiter = strchr(bufPtr, ',');
|
||||
if(nextDelimiter != NULL) *nextDelimiter = '\0';
|
||||
|
||||
unsigned i = 0;
|
||||
while(i < 32 && strcmp(buttonStrLut[i], bufPtr) != 0) ++i;
|
||||
if(i == 32) break;
|
||||
map |= 1u<<i;
|
||||
|
||||
if(nextDelimiter == NULL) break;
|
||||
|
||||
bufPtr = nextDelimiter + 1; // Skip delimiter.
|
||||
}
|
||||
|
||||
// Empty strings will match the entry for bit 12.
|
||||
return map & ~(1u<<12);
|
||||
}
|
||||
|
||||
static int cfgIniCallback(void *user, const char *section, const char *name, const char *value)
|
||||
{
|
||||
OafConfig *const config = (OafConfig*)user;
|
||||
|
||||
if(strcmp(section, "general") == 0)
|
||||
{
|
||||
if(strcmp(name, "backlight") == 0)
|
||||
config->backlight = (u8)strtoul(value, NULL, 10);
|
||||
else if(strcmp(name, "backlightSteps") == 0)
|
||||
config->backlightSteps = (u8)strtoul(value, NULL, 10);
|
||||
else if(strcmp(name, "directBoot") == 0)
|
||||
config->directBoot = (strcmp(value, "false") == 0 ? false : true);
|
||||
else if(strcmp(name, "useGbaDb") == 0)
|
||||
config->useGbaDb = (strcmp(value, "true") == 0 ? true : false);
|
||||
else if(strcmp(name, "useSavesFolder") == 0)
|
||||
config->useSavesFolder = (strcmp(value, "true") == 0 ? true : false);
|
||||
}
|
||||
else if(strcmp(section, "video") == 0)
|
||||
{
|
||||
if(strcmp(name, "scaler") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
config->scaler = 0;
|
||||
else if(strcmp(value, "bilinear") == 0)
|
||||
config->scaler = 1;
|
||||
else if(strcmp(value, "matrix") == 0)
|
||||
config->scaler = 2;
|
||||
}
|
||||
else if(strcmp(name, "colorProfile") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
config->colorProfile = 0;
|
||||
else if(strcmp(value, "gba") == 0)
|
||||
config->colorProfile = 1;
|
||||
else if(strcmp(value, "gb_micro") == 0)
|
||||
config->colorProfile = 2;
|
||||
else if(strcmp(value, "gba_sp101") == 0)
|
||||
config->colorProfile = 3;
|
||||
else if(strcmp(value, "nds") == 0)
|
||||
config->colorProfile = 4;
|
||||
else if(strcmp(value, "ds_lite") == 0)
|
||||
config->colorProfile = 5;
|
||||
else if(strcmp(value, "nso") == 0)
|
||||
config->colorProfile = 6;
|
||||
else if(strcmp(value, "vba") == 0)
|
||||
config->colorProfile = 7;
|
||||
else if(strcmp(value, "identity") == 0)
|
||||
config->colorProfile = 8;
|
||||
//else if(strcmp(value, "custom") == 0) // TODO: Implement user provided profile.
|
||||
// config->colorProfile = 9;
|
||||
}
|
||||
else if(strcmp(name, "contrast") == 0)
|
||||
config->contrast = str2float(value);
|
||||
else if(strcmp(name, "brightness") == 0)
|
||||
config->brightness = str2float(value);
|
||||
else if(strcmp(name, "saturation") == 0)
|
||||
config->saturation = str2float(value);
|
||||
}
|
||||
else if(strcmp(section, "audio") == 0)
|
||||
{
|
||||
if(strcmp(name, "audioOut") == 0)
|
||||
{
|
||||
if(strcmp(value, "auto") == 0)
|
||||
config->audioOut = 0;
|
||||
else if(strcmp(value, "speakers") == 0)
|
||||
config->audioOut = 1;
|
||||
else if(strcmp(value, "headphones") == 0)
|
||||
config->audioOut = 2;
|
||||
}
|
||||
else if(strcmp(name, "volume") == 0)
|
||||
config->volume = (s8)strtol(value, NULL, 10);
|
||||
}
|
||||
else if(strcmp(section, "input") == 0)
|
||||
{
|
||||
const u32 button = parseButtons(name) & 0x3FFu; // Only allow GBA buttons.
|
||||
if(button != 0)
|
||||
{
|
||||
// If the config option happens to abuse parseButtons() we will only use the highest bit.
|
||||
const u32 shift = 31u - __builtin_clzl(button);
|
||||
const u32 map = parseButtons(value);
|
||||
config->buttonMaps[shift] = map;
|
||||
}
|
||||
}
|
||||
else if(strcmp(section, "game") == 0)
|
||||
{
|
||||
if(strcmp(name, "saveSlot") == 0)
|
||||
config->saveSlot = (u8)strtoul(value, NULL, 10);
|
||||
if(strcmp(name, "saveType") == 0)
|
||||
{
|
||||
if(strcmp(value, "eeprom_8k") == 0)
|
||||
config->saveType = 0;
|
||||
if(strcmp(value, "rom_256m_eeprom_8k") == 0)
|
||||
config->saveType = 1;
|
||||
if(strcmp(value, "eeprom_64k") == 0)
|
||||
config->saveType = 2;
|
||||
if(strcmp(value, "rom_256m_eeprom_64k") == 0)
|
||||
config->saveType = 3;
|
||||
if(strcmp(value, "flash_512k_atmel_rtc") == 0)
|
||||
config->saveType = 4;
|
||||
if(strcmp(value, "flash_512k_atmel") == 0)
|
||||
config->saveType = 5;
|
||||
if(strcmp(value, "flash_512k_sst_rtc") == 0)
|
||||
config->saveType = 6;
|
||||
if(strcmp(value, "flash_512k_sst") == 0)
|
||||
config->saveType = 7;
|
||||
if(strcmp(value, "flash_512k_panasonic_rtc") == 0)
|
||||
config->saveType = 8;
|
||||
if(strcmp(value, "flash_512k_panasonic") == 0)
|
||||
config->saveType = 9;
|
||||
if(strcmp(value, "flash_1m_macronix_rtc") == 0)
|
||||
config->saveType = 10;
|
||||
if(strcmp(value, "flash_1m_macronix") == 0)
|
||||
config->saveType = 11;
|
||||
if(strcmp(value, "flash_1m_sanyo_rtc") == 0)
|
||||
config->saveType = 12;
|
||||
if(strcmp(value, "flash_1m_sanyo") == 0)
|
||||
config->saveType = 13;
|
||||
if(strcmp(value, "sram_256k") == 0)
|
||||
config->saveType = 14;
|
||||
if(strcmp(value, "none") == 0)
|
||||
config->saveType = 15;
|
||||
if(strcmp(value, "auto") == 0)
|
||||
config->saveType = 255;
|
||||
}
|
||||
}
|
||||
else if(strcmp(section, "advanced") == 0)
|
||||
{
|
||||
if(strcmp(name, "saveOverride") == 0)
|
||||
config->saveOverride = (strcmp(value, "false") == 0 ? false : true);
|
||||
if(strcmp(name, "defaultSave") == 0)
|
||||
{
|
||||
if(strcmp(value, "eeprom_8k") == 0)
|
||||
config->defaultSave = 0;
|
||||
if(strcmp(value, "rom_256m_eeprom_8k") == 0)
|
||||
config->defaultSave = 1;
|
||||
if(strcmp(value, "eeprom_64k") == 0)
|
||||
config->defaultSave = 2;
|
||||
if(strcmp(value, "rom_256m_eeprom_64k") == 0)
|
||||
config->defaultSave = 3;
|
||||
if(strcmp(value, "flash_512k_atmel_rtc") == 0)
|
||||
config->defaultSave = 4;
|
||||
if(strcmp(value, "flash_512k_atmel") == 0)
|
||||
config->defaultSave = 5;
|
||||
if(strcmp(value, "flash_512k_sst_rtc") == 0)
|
||||
config->defaultSave = 6;
|
||||
if(strcmp(value, "flash_512k_sst") == 0)
|
||||
config->defaultSave = 7;
|
||||
if(strcmp(value, "flash_512k_panasonic_rtc") == 0)
|
||||
config->defaultSave = 8;
|
||||
if(strcmp(value, "flash_512k_panasonic") == 0)
|
||||
config->defaultSave = 9;
|
||||
if(strcmp(value, "flash_1m_macronix_rtc") == 0)
|
||||
config->defaultSave = 10;
|
||||
if(strcmp(value, "flash_1m_macronix") == 0)
|
||||
config->defaultSave = 11;
|
||||
if(strcmp(value, "flash_1m_sanyo_rtc") == 0)
|
||||
config->defaultSave = 12;
|
||||
if(strcmp(value, "flash_1m_sanyo") == 0)
|
||||
config->defaultSave = 13;
|
||||
if(strcmp(value, "sram_256k") == 0)
|
||||
config->defaultSave = 14;
|
||||
if(strcmp(value, "none") == 0)
|
||||
config->defaultSave = 15;
|
||||
}
|
||||
}
|
||||
else return 0; // Error.
|
||||
|
||||
return 1; // 1 is no error? Really?
|
||||
}
|
||||
|
||||
// TODO: Instead of writing a hardcoded string turn default config into a string.
|
||||
Result parseOafConfig(const char *const path, OafConfig *cfg, const bool newCfgOnError)
|
||||
{
|
||||
char *iniBuf = (char*)calloc(INI_BUF_SIZE, 1);
|
||||
if(iniBuf == NULL) return RES_OUT_OF_MEM;
|
||||
|
||||
cfg = (cfg != NULL ? cfg : &g_oafConfig);
|
||||
Result res = fsQuickRead(path, iniBuf, INI_BUF_SIZE - 1);
|
||||
if(res == RES_OK) ini_parse_string(iniBuf, cfgIniCallback, cfg);
|
||||
else if(newCfgOnError)
|
||||
{
|
||||
const char *const defaultConfig = DEFAULT_CONFIG;
|
||||
res = fsQuickWrite(path, defaultConfig, strlen(defaultConfig));
|
||||
}
|
||||
|
||||
free(iniBuf);
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,800 @@
|
|||
/*
|
||||
* This code is part of ctrulib (https://github.com/smealum/ctrulib)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "types.h"
|
||||
#include "arm11/fmt.h"
|
||||
#include "hardware/gfx.h"
|
||||
#include "util.h"
|
||||
#include "arm11/console.h"
|
||||
|
||||
#include "arm11/font_6x10.h"
|
||||
|
||||
//set up the palette for color printing
|
||||
static u16 colorTable[] = {
|
||||
RGB8_to_565( 0, 0, 0), // faint black
|
||||
RGB8_to_565(255, 0, 0), // bright red
|
||||
RGB8_to_565( 0,255, 0), // bright green
|
||||
RGB8_to_565(255,255, 0), // bright yellow
|
||||
RGB8_to_565( 0, 0,255), // bright blue
|
||||
RGB8_to_565(255, 0,255), // bright magenta
|
||||
RGB8_to_565( 0,255,255), // bright cyan
|
||||
RGB8_to_565(255,255,255), // bright white
|
||||
|
||||
RGB8_to_565( 64, 64, 64), // almost black
|
||||
RGB8_to_565(224, 0, 0), // accent red
|
||||
RGB8_to_565( 64,255, 64), // accent green
|
||||
RGB8_to_565(255,255, 32), // accent yellow
|
||||
RGB8_to_565( 64, 64,255), // accent blue
|
||||
RGB8_to_565(255, 0,255), // bright magenta
|
||||
RGB8_to_565( 0,255,255), // bright cyan
|
||||
RGB8_to_565(192,192,192), // almost white
|
||||
|
||||
RGB8_to_565(128,128,128), // bright black
|
||||
RGB8_to_565( 64, 0, 0), // faint red
|
||||
RGB8_to_565( 0, 64, 0), // faint green
|
||||
RGB8_to_565( 64, 64, 0), // faint yellow
|
||||
RGB8_to_565( 0, 0, 64), // faint blue
|
||||
RGB8_to_565( 64, 0, 64), // faint magenta
|
||||
RGB8_to_565( 0, 64, 64), // faint cyan
|
||||
RGB8_to_565( 96, 96, 96), // faint white
|
||||
};
|
||||
|
||||
PrintConsole defaultConsole =
|
||||
{
|
||||
//Font:
|
||||
{
|
||||
default_font, //font gfx
|
||||
0, //first ascii character in the set
|
||||
256 //number of characters in the font set
|
||||
},
|
||||
(u16*)NULL,
|
||||
0,0, //cursorX cursorY
|
||||
0,0, //prevcursorX prevcursorY
|
||||
53, //console width
|
||||
24, //console height
|
||||
0, //window x
|
||||
0, //window y
|
||||
53, //window width
|
||||
24, //window height
|
||||
3, //tab size
|
||||
7, // foreground color
|
||||
0, // background color
|
||||
0, // flags
|
||||
0, //print callback
|
||||
false //console initialized
|
||||
};
|
||||
|
||||
PrintConsole currentCopy;
|
||||
|
||||
PrintConsole* currentConsole = ¤tCopy;
|
||||
|
||||
PrintConsole* consoleGetDefault(void){return &defaultConsole;}
|
||||
|
||||
void consolePrintChar(int c);
|
||||
void consoleDrawChar(int c);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static void consoleCls(char mode) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
int i = 0;
|
||||
int colTemp,rowTemp;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case '[':
|
||||
case '0':
|
||||
{
|
||||
colTemp = currentConsole->cursorX ;
|
||||
rowTemp = currentConsole->cursorY ;
|
||||
|
||||
while(i++ < ((currentConsole->windowHeight * currentConsole->windowWidth) - (rowTemp * currentConsole->consoleWidth + colTemp)))
|
||||
consolePrintChar(' ');
|
||||
|
||||
currentConsole->cursorX = colTemp;
|
||||
currentConsole->cursorY = rowTemp;
|
||||
break;
|
||||
}
|
||||
case '1':
|
||||
{
|
||||
colTemp = currentConsole->cursorX ;
|
||||
rowTemp = currentConsole->cursorY ;
|
||||
|
||||
currentConsole->cursorY = 0;
|
||||
currentConsole->cursorX = 0;
|
||||
|
||||
while (i++ < (rowTemp * currentConsole->windowWidth + colTemp))
|
||||
consolePrintChar(' ');
|
||||
|
||||
currentConsole->cursorX = colTemp;
|
||||
currentConsole->cursorY = rowTemp;
|
||||
break;
|
||||
}
|
||||
case '2':
|
||||
{
|
||||
currentConsole->cursorY = 0;
|
||||
currentConsole->cursorX = 0;
|
||||
|
||||
while(i++ < currentConsole->windowHeight * currentConsole->windowWidth)
|
||||
consolePrintChar(' ');
|
||||
|
||||
currentConsole->cursorY = 0;
|
||||
currentConsole->cursorX = 0;
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
static void consoleClearLine(char mode) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
int i = 0;
|
||||
int colTemp;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case '[':
|
||||
case '0':
|
||||
{
|
||||
colTemp = currentConsole->cursorX ;
|
||||
|
||||
while(i++ < (currentConsole->windowWidth - colTemp)) {
|
||||
consolePrintChar(' ');
|
||||
}
|
||||
|
||||
currentConsole->cursorX = colTemp;
|
||||
|
||||
break;
|
||||
}
|
||||
case '1':
|
||||
{
|
||||
colTemp = currentConsole->cursorX ;
|
||||
|
||||
currentConsole->cursorX = 0;
|
||||
|
||||
while(i++ < ((currentConsole->windowWidth - colTemp)-2)) {
|
||||
consolePrintChar(' ');
|
||||
}
|
||||
|
||||
currentConsole->cursorX = colTemp;
|
||||
|
||||
break;
|
||||
}
|
||||
case '2':
|
||||
{
|
||||
colTemp = currentConsole->cursorX ;
|
||||
|
||||
currentConsole->cursorX = 0;
|
||||
|
||||
while(i++ < currentConsole->windowWidth) {
|
||||
consolePrintChar(' ');
|
||||
}
|
||||
|
||||
currentConsole->cursorX = colTemp;
|
||||
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__ ((format (scanf, 2, 3))) int fb_sscanf(const char *s, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
|
||||
int ret = 0;
|
||||
const char *const oldS = s;
|
||||
while(*fmt)
|
||||
{
|
||||
if(*fmt == '%')
|
||||
{
|
||||
bool number = false;
|
||||
|
||||
switch(*++fmt)
|
||||
{
|
||||
case 'd':
|
||||
*va_arg(args, int*) = atoi(s);
|
||||
number = true;
|
||||
ret++;
|
||||
break;
|
||||
case 'c':
|
||||
*va_arg(args, char*) = *s++;
|
||||
ret++;
|
||||
break;
|
||||
case 'n':
|
||||
*va_arg(args, int*) = (int)(s - oldS);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
if(number) while(*s >= '0' && *s <= '9') s++;
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*fmt != *s) break;
|
||||
fmt++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
ssize_t con_write(UNUSED struct _reent *r,UNUSED void *fd,const char *ptr, size_t len) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
char chr;
|
||||
|
||||
int i, count = 0;
|
||||
const char *tmp = ptr;
|
||||
|
||||
if(!tmp || (int)len<=0) return -1;
|
||||
|
||||
i = 0;
|
||||
|
||||
while(i<(int)len) {
|
||||
|
||||
chr = *(tmp++);
|
||||
i++; count++;
|
||||
|
||||
if ( chr == 0x1b && *tmp == '[' ) {
|
||||
bool escaping = true;
|
||||
const char *escapeseq = tmp++;
|
||||
int escapelen = 1;
|
||||
i++; count++;
|
||||
|
||||
do {
|
||||
chr = *(tmp++);
|
||||
i++; count++; escapelen++;
|
||||
int parameter, assigned, consumed;
|
||||
|
||||
// make sure parameters are positive values and delimited by semicolon
|
||||
if((chr >= '0' && chr <= '9') || chr == ';')
|
||||
continue;
|
||||
|
||||
switch (chr) {
|
||||
//---------------------------------------
|
||||
// Cursor directional movement
|
||||
//---------------------------------------
|
||||
case 'A':
|
||||
consumed = 0;
|
||||
assigned = fb_sscanf(escapeseq,"[%dA%n", ¶meter, &consumed);
|
||||
if (assigned==0) parameter = 1;
|
||||
if (consumed)
|
||||
currentConsole->cursorY = (currentConsole->cursorY - parameter) < 0 ? 0 : currentConsole->cursorY - parameter;
|
||||
escaping = false;
|
||||
break;
|
||||
case 'B':
|
||||
consumed = 0;
|
||||
assigned = fb_sscanf(escapeseq,"[%dB%n", ¶meter, &consumed);
|
||||
if (assigned==0) parameter = 1;
|
||||
if (consumed)
|
||||
currentConsole->cursorY = (currentConsole->cursorY + parameter) > currentConsole->windowHeight - 1 ? currentConsole->windowHeight - 1 : currentConsole->cursorY + parameter;
|
||||
escaping = false;
|
||||
break;
|
||||
case 'C':
|
||||
consumed = 0;
|
||||
assigned = fb_sscanf(escapeseq,"[%dC%n", ¶meter, &consumed);
|
||||
if (assigned==0) parameter = 1;
|
||||
if (consumed)
|
||||
currentConsole->cursorX = (currentConsole->cursorX + parameter) > currentConsole->windowWidth - 1 ? currentConsole->windowWidth - 1 : currentConsole->cursorX + parameter;
|
||||
escaping = false;
|
||||
break;
|
||||
case 'D':
|
||||
consumed = 0;
|
||||
assigned = fb_sscanf(escapeseq,"[%dD%n", ¶meter, &consumed);
|
||||
if (assigned==0) parameter = 1;
|
||||
if (consumed)
|
||||
currentConsole->cursorX = (currentConsole->cursorX - parameter) < 0 ? 0 : currentConsole->cursorX - parameter;
|
||||
escaping = false;
|
||||
break;
|
||||
//---------------------------------------
|
||||
// Cursor position movement
|
||||
//---------------------------------------
|
||||
case 'H':
|
||||
case 'f':
|
||||
{
|
||||
int x, y;
|
||||
char c;
|
||||
if(fb_sscanf(escapeseq,"[%d;%d%c", &y, &x, &c) == 3 && (c == 'f' || c == 'H')) {
|
||||
currentConsole->cursorX = x;
|
||||
currentConsole->cursorY = y;
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
x = y = 1;
|
||||
if(fb_sscanf(escapeseq,"[%d;%c", &y, &c) == 2 && (c == 'f' || c == 'H')) {
|
||||
currentConsole->cursorX = x;
|
||||
currentConsole->cursorY = y;
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
x = y = 1;
|
||||
if(fb_sscanf(escapeseq,"[;%d%c", &x, &c) == 2 && (c == 'f' || c == 'H')) {
|
||||
currentConsole->cursorX = x;
|
||||
currentConsole->cursorY = y;
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
x = y = 1;
|
||||
if(fb_sscanf(escapeseq,"[;%c", &c) == 1 && (c == 'f' || c == 'H')) {
|
||||
currentConsole->cursorX = x;
|
||||
currentConsole->cursorY = y;
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// invalid format
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
//---------------------------------------
|
||||
// Screen clear
|
||||
//---------------------------------------
|
||||
case 'J':
|
||||
if(escapelen <= 3)
|
||||
consoleCls(escapeseq[escapelen-2]);
|
||||
escaping = false;
|
||||
break;
|
||||
//---------------------------------------
|
||||
// Line clear
|
||||
//---------------------------------------
|
||||
case 'K':
|
||||
if(escapelen <= 3)
|
||||
consoleClearLine(escapeseq[escapelen-2]);
|
||||
escaping = false;
|
||||
break;
|
||||
//---------------------------------------
|
||||
// Save cursor position
|
||||
//---------------------------------------
|
||||
case 's':
|
||||
if(escapelen == 2) {
|
||||
currentConsole->prevCursorX = currentConsole->cursorX ;
|
||||
currentConsole->prevCursorY = currentConsole->cursorY ;
|
||||
}
|
||||
escaping = false;
|
||||
break;
|
||||
//---------------------------------------
|
||||
// Load cursor position
|
||||
//---------------------------------------
|
||||
case 'u':
|
||||
if(escapelen == 2) {
|
||||
currentConsole->cursorX = currentConsole->prevCursorX ;
|
||||
currentConsole->cursorY = currentConsole->prevCursorY ;
|
||||
}
|
||||
escaping = false;
|
||||
break;
|
||||
//---------------------------------------
|
||||
// Color scan codes
|
||||
//---------------------------------------
|
||||
case 'm':
|
||||
escapeseq++;
|
||||
escapelen--;
|
||||
|
||||
do {
|
||||
parameter = 0;
|
||||
if (escapelen == 1) {
|
||||
consumed = 1;
|
||||
} else if (memchr(escapeseq,';',escapelen)) {
|
||||
fb_sscanf(escapeseq,"%d;%n", ¶meter, &consumed);
|
||||
} else {
|
||||
fb_sscanf(escapeseq,"%dm%n", ¶meter, &consumed);
|
||||
}
|
||||
|
||||
escapeseq += consumed;
|
||||
escapelen -= consumed;
|
||||
|
||||
switch(parameter) {
|
||||
case 0: // reset
|
||||
currentConsole->flags = 0;
|
||||
currentConsole->bg = 0;
|
||||
currentConsole->fg = 7;
|
||||
break;
|
||||
|
||||
case 1: // bold
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
|
||||
currentConsole->flags |= CONSOLE_COLOR_BOLD;
|
||||
break;
|
||||
|
||||
case 2: // faint
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
|
||||
currentConsole->flags |= CONSOLE_COLOR_FAINT;
|
||||
break;
|
||||
|
||||
case 3: // italic
|
||||
currentConsole->flags |= CONSOLE_ITALIC;
|
||||
break;
|
||||
|
||||
case 4: // underline
|
||||
currentConsole->flags |= CONSOLE_UNDERLINE;
|
||||
break;
|
||||
|
||||
case 5: // blink slow
|
||||
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
|
||||
currentConsole->flags |= CONSOLE_BLINK_SLOW;
|
||||
break;
|
||||
|
||||
case 6: // blink fast
|
||||
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
|
||||
currentConsole->flags |= CONSOLE_BLINK_FAST;
|
||||
break;
|
||||
|
||||
case 7: // reverse video
|
||||
currentConsole->flags |= CONSOLE_COLOR_REVERSE;
|
||||
break;
|
||||
|
||||
case 8: // conceal
|
||||
currentConsole->flags |= CONSOLE_CONCEAL;
|
||||
break;
|
||||
|
||||
case 9: // crossed-out
|
||||
currentConsole->flags |= CONSOLE_CROSSED_OUT;
|
||||
break;
|
||||
|
||||
case 21: // bold off
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
|
||||
break;
|
||||
|
||||
case 22: // normal color
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
|
||||
break;
|
||||
|
||||
case 23: // italic off
|
||||
currentConsole->flags &= ~CONSOLE_ITALIC;
|
||||
break;
|
||||
|
||||
case 24: // underline off
|
||||
currentConsole->flags &= ~CONSOLE_UNDERLINE;
|
||||
break;
|
||||
|
||||
case 25: // blink off
|
||||
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
|
||||
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
|
||||
break;
|
||||
|
||||
case 27: // reverse off
|
||||
currentConsole->flags &= ~CONSOLE_COLOR_REVERSE;
|
||||
break;
|
||||
|
||||
case 29: // crossed-out off
|
||||
currentConsole->flags &= ~CONSOLE_CROSSED_OUT;
|
||||
break;
|
||||
|
||||
case 30 ... 37: // writing color
|
||||
currentConsole->fg = parameter - 30;
|
||||
break;
|
||||
|
||||
case 39: // reset foreground color
|
||||
currentConsole->fg = 7;
|
||||
break;
|
||||
|
||||
case 40 ... 47: // screen color
|
||||
currentConsole->bg = parameter - 40;
|
||||
break;
|
||||
|
||||
case 49: // reset background color
|
||||
currentConsole->fg = 0;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
} while (escapelen > 0);
|
||||
|
||||
escaping = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
// some sort of unsupported escape; just gloss over it
|
||||
escaping = false;
|
||||
break;
|
||||
}
|
||||
} while (escaping);
|
||||
continue;
|
||||
}
|
||||
|
||||
consolePrintChar(chr);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
PrintConsole* consoleInit(u8 screen, PrintConsole* console) {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
if(console) {
|
||||
currentConsole = console;
|
||||
} else {
|
||||
console = currentConsole;
|
||||
}
|
||||
|
||||
*currentConsole = defaultConsole;
|
||||
|
||||
console->consoleInitialised = 1;
|
||||
|
||||
//gfxSetScreenFormat(screen,GSP_RGB565_OES);
|
||||
GFX_setDoubleBuffering(screen, false);
|
||||
|
||||
console->frameBuffer = (u16*)GFX_getFramebuffer(screen);
|
||||
|
||||
if(screen==SCREEN_TOP) {
|
||||
console->consoleWidth = 66;
|
||||
console->windowWidth = 66;
|
||||
}
|
||||
|
||||
|
||||
consoleCls('2');
|
||||
|
||||
return currentConsole;
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
PrintConsole *consoleSelect(PrintConsole* console){
|
||||
//---------------------------------------------------------------------------------
|
||||
PrintConsole *tmp = currentConsole;
|
||||
currentConsole = console;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
PrintConsole *consoleGet(void){
|
||||
//---------------------------------------------------------------------------------
|
||||
return currentConsole;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
u16 consoleGetFgColor(void){
|
||||
//---------------------------------------------------------------------------------
|
||||
return colorTable[currentConsole->fg];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void consoleSetFont(PrintConsole* console, ConsoleFont* font){
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
if(!console) console = currentConsole;
|
||||
|
||||
console->font = *font;
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
static void newRow() {
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
currentConsole->cursorY ++;
|
||||
|
||||
|
||||
if(currentConsole->cursorY >= currentConsole->windowHeight) {
|
||||
currentConsole->cursorY --;
|
||||
u16 *dst = ¤tConsole->frameBuffer[(currentConsole->windowX * 6 * 240) + (239 - (currentConsole->windowY * 10))];
|
||||
u16 *src = dst - 10;
|
||||
|
||||
int i,j;
|
||||
|
||||
for (i=0; i<currentConsole->windowWidth*6; i++) {
|
||||
u32 *from = (u32*)((int)src & ~3);
|
||||
u32 *to = (u32*)((int)dst & ~3);
|
||||
for (j=0;j<(((currentConsole->windowHeight-1)*10)/2);j++) *(to--) = *(from--);
|
||||
dst += 240;
|
||||
src += 240;
|
||||
}
|
||||
|
||||
consoleClearLine('2');
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void consoleDrawChar(int c) {
|
||||
//---------------------------------------------------------------------------------
|
||||
c -= currentConsole->font.asciiOffset;
|
||||
if ( c < 0 || c > currentConsole->font.numChars ) return;
|
||||
|
||||
const u8 *fontdata = currentConsole->font.gfx + (10 * c);
|
||||
|
||||
int writingColor = currentConsole->fg;
|
||||
int screenColor = currentConsole->bg;
|
||||
|
||||
if (currentConsole->flags & CONSOLE_COLOR_BOLD) {
|
||||
writingColor += 8;
|
||||
} else if (currentConsole->flags & CONSOLE_COLOR_FAINT) {
|
||||
writingColor += 16;
|
||||
}
|
||||
|
||||
if (currentConsole->flags & CONSOLE_COLOR_REVERSE) {
|
||||
int tmp = writingColor;
|
||||
writingColor = screenColor;
|
||||
screenColor = tmp;
|
||||
}
|
||||
|
||||
u16 bg = colorTable[screenColor];
|
||||
u16 fg = colorTable[writingColor];
|
||||
|
||||
u8 b1 = *(fontdata++);
|
||||
u8 b2 = *(fontdata++);
|
||||
u8 b3 = *(fontdata++);
|
||||
u8 b4 = *(fontdata++);
|
||||
u8 b5 = *(fontdata++);
|
||||
u8 b6 = *(fontdata++);
|
||||
u8 b7 = *(fontdata++);
|
||||
u8 b8 = *(fontdata++);
|
||||
u8 b9 = *(fontdata++);
|
||||
u8 b10 = *(fontdata++);
|
||||
|
||||
if (currentConsole->flags & CONSOLE_UNDERLINE) b10 = 0xff;
|
||||
|
||||
if (currentConsole->flags & CONSOLE_CROSSED_OUT) b5 = 0xff;
|
||||
|
||||
u8 mask = 0x80;
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
int x = (currentConsole->cursorX + currentConsole->windowX) * 6;
|
||||
int y = ((currentConsole->cursorY + currentConsole->windowY) * 10);
|
||||
|
||||
u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 9))];
|
||||
|
||||
for (i=0;i<6;i++) {
|
||||
if (b10 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b9 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b8 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b7 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b6 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b5 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b4 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b3 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b2 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
if (b1 & mask) { *(screen++) = fg; }else{ *(screen++) = bg; }
|
||||
mask >>= 1;
|
||||
screen += 240 - 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void consolePrintChar(int c) {
|
||||
//---------------------------------------------------------------------------------
|
||||
if (c==0) return;
|
||||
|
||||
if(currentConsole->PrintChar)
|
||||
if(currentConsole->PrintChar(currentConsole, c))
|
||||
return;
|
||||
|
||||
if(currentConsole->cursorX >= currentConsole->windowWidth) {
|
||||
currentConsole->cursorX = 0;
|
||||
|
||||
newRow();
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
/*
|
||||
The only special characters we will handle are tab (\t), carriage return (\r), line feed (\n)
|
||||
and backspace (\b).
|
||||
Carriage return & line feed will function the same: go to next line and put cursor at the beginning.
|
||||
For everything else, use VT sequences.
|
||||
|
||||
Reason: VT sequences are more specific to the task of cursor placement.
|
||||
The special escape sequences \b \f & \v are archaic and non-portable.
|
||||
*/
|
||||
case 8:
|
||||
currentConsole->cursorX--;
|
||||
|
||||
if(currentConsole->cursorX < 0) {
|
||||
if(currentConsole->cursorY > 0) {
|
||||
currentConsole->cursorX = currentConsole->windowX - 1;
|
||||
currentConsole->cursorY--;
|
||||
} else {
|
||||
currentConsole->cursorX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
consoleDrawChar(' ');
|
||||
break;
|
||||
|
||||
case 9:
|
||||
currentConsole->cursorX += currentConsole->tabSize - ((currentConsole->cursorX)%(currentConsole->tabSize));
|
||||
break;
|
||||
case 10:
|
||||
newRow();
|
||||
// falls through
|
||||
case 13:
|
||||
currentConsole->cursorX = 0;
|
||||
break;
|
||||
default:
|
||||
consoleDrawChar(c);
|
||||
++currentConsole->cursorX ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void consoleClear(void) {
|
||||
//---------------------------------------------------------------------------------
|
||||
ee_printf("\x1b[2J");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height){
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
if(!console) console = currentConsole;
|
||||
|
||||
console->windowWidth = width;
|
||||
console->windowHeight = height;
|
||||
console->windowX = x;
|
||||
console->windowY = y;
|
||||
|
||||
console->cursorX = 0;
|
||||
console->cursorY = 0;
|
||||
|
||||
}
|
||||
|
||||
void drawConsoleWindow(PrintConsole* console, int thickness, u8 colorIndex) {
|
||||
|
||||
if(colorIndex >= 16) return;
|
||||
|
||||
if(!console) console = currentConsole;
|
||||
|
||||
int startx = console->windowX * 8 - thickness;
|
||||
int endx = (console->windowX + console->windowWidth) * 8 + thickness;
|
||||
|
||||
int starty = (console->windowY - 1) * 8 - thickness;
|
||||
int endy = console->windowHeight * 8 + thickness;
|
||||
|
||||
u16 color = colorTable[colorIndex];
|
||||
|
||||
// upper line
|
||||
for(int y = starty; y < starty + thickness; y++)
|
||||
for(int x = startx; x < endx; x++)
|
||||
{
|
||||
u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))];
|
||||
*screen = color;
|
||||
}
|
||||
|
||||
// lower line
|
||||
for(int y = endy; y > endy - thickness; y--)
|
||||
for(int x = startx; x < endx; x++)
|
||||
{
|
||||
u16 *screen = ¤tConsole->frameBuffer[(x * 240) + (239 - (y + 7))];
|
||||
*screen = color;
|
||||
}
|
||||
|
||||
// left and right
|
||||
for(int y = starty; y < endy; y++)
|
||||
{
|
||||
for(int i = 0; i < thickness; i++)
|
||||
{
|
||||
u16 *screen = ¤tConsole->frameBuffer[((startx + i) * 240) + (239 - (y + 7))];
|
||||
*screen = color;
|
||||
screen = ¤tConsole->frameBuffer[((endx - thickness + i) * 240) + (239 - (y + 7))];
|
||||
*screen = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void consoleSetCursor(PrintConsole* console, int x, int y) {
|
||||
console->cursorX = x;
|
||||
console->cursorY = y;
|
||||
}
|
||||
|
||||
u16 consoleGetRGB565Color(u8 colorIndex) {
|
||||
if(colorIndex >= arrayEntries(colorTable))
|
||||
return 0;
|
||||
return colorTable[colorIndex];
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue