Compare commits

..

119 Commits

Author SHA1 Message Date
profi200 6b882e9395
Don't run actions on pull requests. 2024-12-06 22:37:25 +01:00
profi200 4e4c2aa2b5
Updated all libretro based color profiles.
Added GB micro, GBA SP (AGS-101), DS lite and VBA/No$GBA profiles.
2024-12-04 00:44:14 +01:00
profi200 dd90d498c4
!Breaking change! Changed the config file format to use strings in many places instead of values.
Added a new saturation setting for color profiles other than none.
Removed lcdGamma and displayGamma temporarily.
Updated README.md with all the changes.
2024-12-03 20:34:53 +01:00
Elouan Martinet 877f7c61d0 Add an option to use current rom directory for config and saves 2024-10-28 09:30:36 +01:00
profi200 7a7190baea
[README] Mention that oaf is not affected by the screen wrap bug because people are talking shit. 2024-09-22 15:14:03 +02:00
profi200 edd43a6fcc
Updated libn3ds.
Fixed hang on power off when all backlights are off (libn3ds).
Screenshots are now always in native resolution.
2024-08-30 18:45:24 +02:00
profi200 50e2f30e0d
[README] Mention new features and oaf is no longer in alpha. 2024-08-02 19:35:52 +02:00
profi200 79b2457e8b
[File browser] Filter out all entries starting with a dot. F.....g Mac OS. 2024-07-31 16:19:46 +02:00
profi200 5356e5c89a
Implemented full gamma correction for top LCDs which improves colors noticeably without crushing details in shadows.
The disadvantage is that the gbaGamma, lcdGamma, brightness and contrast settings don't work anymore for now. They will be reimplemented with color profile settings later.
2024-07-30 16:37:05 +02:00
profi200 67ce019b36
Forgot to check the ROM size before adding the padding. 2024-07-26 21:22:40 +02:00
profi200 41db8760a6
Made ROM padding code ~42% faster. 2024-07-26 20:37:49 +02:00
profi200 3a70cdc27f Improved README for screenshots and color correction. 2024-07-25 17:19:41 +02:00
profi200 b1c66e24a2 Added experimental support for true color correction to mimic the look of the crappy GBA LCD. Thanks to hunterk and Pokefan531 for their work on the libretro shaders this is based on. 2024-07-25 17:19:41 +02:00
profi200 f7efd62ea9 Fixed save type selector cursor at the wrong position and added cache flushing. 2024-07-25 17:19:41 +02:00
profi200 073daac2bb Separated video functions into own .c file. 2024-07-25 17:19:41 +02:00
profi200 15436e02a7 Updated submodules.
Fixed compatibility with latest libn3ds.
2024-07-25 17:19:41 +02:00
profi200 3e91716c80 c2x --> c23. Supported since gcc 14.1.0. 2024-07-25 17:19:41 +02:00
profi200 f9786b14a1 Updated libn3ds for a critical GPIO fix. Also updated the other submodules. 2024-07-25 17:19:41 +02:00
profi200 bd5b207106 Updated bitmap.h with comments. 2024-07-25 17:19:41 +02:00
profi200 7c8c3d6fe8 Load GBA scaler matrix from SD if found. 2024-07-25 17:19:41 +02:00
profi200 6cf6059023 Updated libn3ds submodule for the capture card workaround. 2024-07-25 17:19:41 +02:00
profi200 1ad621d4f4 Fixed a file handle leak just introduced by myself. Thanks @PSI-Rockin for finding it. 2024-07-25 17:19:41 +02:00
profi200 9f331c24f7 Use a more safe variant of binary search for the GBA db. 2024-07-25 17:19:41 +02:00
profi200 3ffb706f3b Fixed strict-aliasing warning in save_type.c. 2024-07-25 17:19:41 +02:00
profi200 c85a4b1b57 Fixed strict-aliasing warnings in gpu_cmd_lists.c. 2024-07-25 17:19:41 +02:00
profi200 6db20e190c Added min macro to patch.c because it was removed from libn3ds. 2024-07-25 17:19:41 +02:00
profi200 d7f701f02a Fixed compatibility with latest libn3ds. 2024-07-25 17:19:41 +02:00
profi200 2bca9b04b6 Updated submodules. 2024-07-25 17:19:41 +02:00
profi200 678cbd9ae3
Automatic builds from all branches. 2024-05-19 22:36:52 +02:00
profi200 479069d039
Updated README.md adding the missing [input] to the example. 2024-04-08 15:36:49 +02:00
profi200 99cf0fdacc
Updated to checkout/cache/upload-artifact v4. 2024-02-24 20:58:04 +01:00
Nemris 9d13ad3722 Refactor IPS patching. 2024-02-24 20:45:18 +01:00
Nemris 07bdaf521d Normalize indentation. 2024-02-24 20:45:18 +01:00
profi200 e14704181c
Round the gamma table entries instead of discarding the fraction part. 2024-01-29 17:43:58 +01:00
profi200 63e4422db1
Cleaned up the old gamma table adjustment code a little. 2023-10-06 16:11:20 +02:00
profi200 b554c7c35c
Updated libn3ds and some defines. 2023-10-06 16:10:29 +02:00
profi200 5f46a967a8
Hardcode GPU cmd list sizes in the header instead of 2 places so i don't make *that* mistake again. 2023-09-20 00:24:47 +02:00
profi200 dc5ac1749f
Fixed ROM mirrors for 1 MiB ROMs. Thanks to @endrift for discovering this. 2023-09-20 00:15:31 +02:00
profi200 855f6b131a
Added a few missing copyright headers. 2023-09-19 20:58:03 +02:00
profi200 e77b04f089
Split open_agb_firm.c into more .c files. A long overdue change. 2023-09-19 20:48:07 +02:00
profi200 ddba28b226
Fixed a double free oopsie. 2023-08-25 13:17:56 +02:00
profi200 8db77d523e
Oops, this happens when not checking wtf the written code actually does. 2023-08-23 02:33:22 +02:00
profi200 4377d28d14
Use macro for GPU render buffer address. 2023-08-23 02:26:09 +02:00
profi200 1ca27c22f6
Disable borders for scaled modes. There are so few pixels left they don't make sense. 2023-08-23 02:21:50 +02:00
profi200 6766b224dc
Set scale matrix outside libn3ds. 2023-08-23 02:09:29 +02:00
profi200 a3c8f76e82
Use glob matching in .gitignore. 2023-08-23 02:04:39 +02:00
Harrison 92c591da22
GBA database updates (#128) 2023-08-23 01:30:01 +02:00
profi200 0f55ad941c
Updated libn3ds. 2023-08-12 18:18:06 +02:00
profi200 cf7d1915e0
Added software audio volume control. 2023-08-12 18:17:13 +02:00
profi200 8ecc7ce458
Added border support for 1:1 scaling mode. 2023-08-10 22:29:16 +02:00
profi200 4f96bae9d3
Updated libraries/submodules. 2023-08-07 01:57:45 +02:00
profi200 014c341e67
Added button remapping. Closes #25. 2023-08-07 01:57:15 +02:00
profi200 726a4f3355
Implemented proper headphone detection.
Added a config option to override the audio output.
2023-08-05 02:07:13 +02:00
profi200 30351188a4
Updated libs/submodules. 2023-08-05 02:06:15 +02:00
profi200 cecd0d31f3
Cache ctr_firm_builder. 2023-05-02 03:43:04 +02:00
profi200 3d8a24769d
Use checkout for ctr_firm_builder. 2023-05-02 02:19:00 +02:00
profi200 1e5e1ea6a9
Updated workflow. 2023-05-02 02:03:58 +02:00
profi200 5e103deecc
Updated libn3ds to work around a hardware bug. 2022-08-15 00:35:09 +02:00
profi200 80f48ca43e
Added inih as submodule as well. 2022-07-25 15:17:23 +02:00
profi200 a70673dea7
Added lgyFbScaler tool for experiments with hardware scaling. 2022-07-24 18:11:24 +02:00
profi200 99d6b1e1ea
Use latest libn3ds with fixed paths. 2022-07-24 17:45:08 +02:00
profi200 6298503e6b
Moved libn3ds to libraries/libn3ds.
Include libn3ds license in releases and nightlies.
2022-07-24 16:50:20 +02:00
profi200 cdacbc7dc5
Use a special makefile rule to avoid unpacking the release archive and p7zip dependency. 2022-07-24 15:53:41 +02:00
profi200 edaa5fb2cb
Don't limit make to 4 jobs. 2022-07-24 15:18:37 +02:00
profi200 d80588ffc4
Limit the clone depth for faster CI builds. 2022-07-24 03:40:28 +02:00
profi200 93d5cdf045
Moved open_agb_firm specific error codes and error printing out of libn3ds. 2022-07-24 01:52:03 +02:00
profi200 45830c8c68
Forgot to mention the Actions tab. 2022-07-16 15:02:00 +02:00
profi200 c171c4da1d
Added nightly build link. 2022-07-16 14:09:25 +02:00
profi200 b1739994a2
Clean up CI script.
And don't embed commit hash in artifact name.
2022-07-16 13:53:25 +02:00
profi200 6bfccaee80
Testing GitHub Actions. 2022-07-15 19:45:03 +02:00
profi200 b710d8e326
Updated libn3ds.
Renamed thirdparty to libraries.
2022-07-14 03:00:31 +02:00
spitzeqc 834c0ffbbf
Added IPS and UPS patch support (#75) 2022-07-14 02:46:37 +02:00
profi200 b1d2b5a84a
Updated libn3ds. 2022-07-03 01:38:56 +02:00
profi200 09622b88f8
Corrected clone instructions. 2022-07-03 01:32:54 +02:00
profi200 48448c749c
Added repo clone/update instructions 2022-06-29 16:37:34 +02:00
profi200 a13499c49e
Fixed README.md for latest changes. 2022-06-29 16:06:07 +02:00
profi200 1fe529f4c5
Overhauled brightness control. 2022-06-29 15:58:09 +02:00
profi200 bd6bc4fd54
Removed hardcoded libn3ds. 2022-06-29 15:55:07 +02:00
spitzeqc ee21e3edb0 Changed backlight power to use GFX_powerOffBacklights() and moved brightness control to 'main' function 2022-06-28 00:41:14 +02:00
spitzeqc 6b5abf383d Added ability to turn screen on and off 2022-06-28 00:41:14 +02:00
spitzeqc 56bf27a026 Added brightness adjustment in-game 2022-06-28 00:41:14 +02:00
profi200 3183839120
Ported toshsd and sdmmc drivers for DSi. 2022-06-24 00:24:44 +02:00
profi200 5ab356a248
Minor toshsd/sdmmc driver code cleanup/improvement. 2022-06-23 15:21:01 +02:00
profi200 9bd9497315
Fixed glitches when taking screenshots. This should also fix freezes.
Screenshots now have the date and time in the file name.
2022-06-20 20:03:46 +02:00
profi200 25b1f794c2
Fixed/improved documentation.
Made triggering the screenshot feature easier. Exact timing is no longer required when pressing SELECT + Y. However the screenshot feature may cause graphic glitches. This will be fixed later.
2022-06-20 18:10:25 +02:00
profi200 9e44587f1c
Simplified clock management for toshsd/sdmmc drivers. 2022-06-08 20:22:54 +02:00
profi200 dbaad7d09c
Major overhaul of (e)MMC/SD card driver including high capacity (e)MMC support (untested).
Various small bug fixes and documentation improvement.
Other, unrelated bug fixes/changes.
2022-06-01 19:30:52 +02:00
profi200 4e86b0c6bf
Fixed error detection on file write. 2022-05-22 23:47:07 +02:00
profi200 b128dd4575
Do not power off if an error occurs while powering off. 2022-05-22 21:12:34 +02:00
profi200 a588af0b3c
Fixed FatFs name in error codes. 2022-05-22 00:39:31 +02:00
profi200 dd4f51334f
Updated fatFs to R0.14b. 2022-05-22 00:13:56 +02:00
profi200 97bdad5710
Toshsd driver pretty much finished now (SDIO IRQ support missing).
Added some missing function and argument descriptions + other minor changes.
2022-05-10 19:34:27 +02:00
profi200 f486ba2b9f
Small toshsd and sdmmc driver overhaul. 2022-05-07 17:36:20 +02:00
profi200 8f86f79461
[toshsd/sdmmc] Renamed slot to card. 2022-05-01 20:56:05 +02:00
profi200 78fd101c66
Allow ROMs bigger than 32 MiB to be loaded with a warning.
Note: If any game/ROM hack tries to access data out of bounds it will crash sooner or later. Don't open issues for such ROMs.
2022-05-01 20:33:13 +02:00
profi200 c139ceb720
Allow large file reads and writes via fatfs.
Miscellaneous NDMA driver changes.
2022-05-01 20:29:25 +02:00
profi200 92f3208daa
Use asm_macros.h in both start.s files. 2022-04-29 18:25:13 +02:00
profi200 f9f47df59e
Switched to unified assembly syntax. 2022-04-28 23:38:26 +02:00
profi200 9d54442c42
SD/(e)MMC driver cleanup. 2022-04-28 17:10:43 +02:00
profi200 b8b75d784c
Fixed RTC type conversion warning. 2022-04-26 03:02:31 +02:00
profi200 5714b5eb16
Merge branch 'master' of github.com:profi200/open_agb_firm 2022-04-25 21:03:11 +02:00
profi200 dc0320615b
A bit of unplanned SHA driver optimization. Saves about 1 ms per MiB. 2022-04-23 01:45:07 +02:00
profi200 3a31110673
Fixed MCU battery level/temperature code. 2022-04-23 01:40:05 +02:00
profi200 1c680e7d52
Partial MCU driver rewrite.
Miscellaneous changes/fixes.
2022-03-29 17:29:24 +02:00
profi200 4a6603d110
Added day of week calculation for the GBA RTC. 2022-01-25 00:18:13 +01:00
profi200 2222e54f0f
Fixed a bug that may cause the file browser not to display all 1000 files.
Made file sorting faster.
Miscellaneous fixes.
2022-01-16 20:46:38 +01:00
Midnoclose 782596facd Add firmtool support 2022-01-09 15:14:18 +01:00
profi200 a9fcf853bb
Forgot a newline while changing the default config in previous commit. Fixes #53. 2022-01-05 16:19:46 +01:00
profi200 9756e2eafc
Added configurable scaling. Very hacky implementation because no citro3d and DMA-330 JIT. 2022-01-05 00:01:03 +01:00
profi200 15cf1bffd5
Added per-game config support. Place "romName.ini" in "/3ds/open_agb_firm/saves" to change per-game settings. Currently only saveSlot is configurable.
Updated README.md.
2021-12-21 19:40:16 +01:00
profi200 247cb19cb5
Actually screw the useSaveFolder config. "/3ds/open_agb_firm/saves" is the new location for savegames and future per-game configs.
Added code for savegame slots. Currently not configurable.
2021-12-19 19:27:52 +01:00
profi200 35243abed0
Updated README for commit d7baad122a.
Added a README note on the crappy sound.
2021-12-19 00:02:53 +01:00
profi200 37f3df4a52
Added autoboot. Place "autoboot.txt" in "/3ds/open_agb_firm".
Note: The autoboot path must be a single line starting with "sdmc:/".
2021-12-18 23:45:51 +01:00
profi200 d7baad122a
Renamed a few config options and added a savegame path one (currently non-functional).
Moved config parsing and backlight setup to an earlier location.
Misc changes.
2021-12-18 03:04:25 +01:00
profi200 b09e3a0eee
Bump file browser entry limit to 1000 files and folders. Please note that the real limit is dynamic and depends on file name lengths. Fixes #37. 2021-12-16 18:33:49 +01:00
profi200 6129451b75
Code size reduction + slightly more readable code in setupSaveType(). 2021-12-13 02:12:53 +01:00
profi200 f59f596a2b
Make the ARM9 fast again. 2021-12-09 18:33:00 +01:00
profi200 434f714ef1
Fixed white screen issues with save type none games. Fixes #48. 2021-12-09 13:22:39 +01:00
profi200 82d54b341c
Force DWARF 4 debug symbols for now. 2021-12-09 00:34:52 +01:00
204 changed files with 3592 additions and 48771 deletions

52
.github/workflows/c-cpp.yml vendored Normal file
View File

@ -0,0 +1,52 @@
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

23
.gitignore vendored
View File

@ -1,14 +1,9 @@
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
tools/gba-db-builder/gba_db.bin
tools/gba-db-builder/gba.dat
tools/gba-db-builder/gba.xml
open_agb_firm.firm
open_agb_firm*.7z
/.*
!/.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*.*

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[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

View File

@ -9,16 +9,25 @@ 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
@ -30,37 +39,66 @@ all: checkarm9 checkarm11 $(TARGET).firm
#---------------------------------------------------------------------------------
checkarm9:
@$(MAKE) -j4 --no-print-directory -C arm9
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9
#---------------------------------------------------------------------------------
checkarm11:
@$(MAKE) -j4 --no-print-directory -C arm11
@$(MAKE) -j$(NPROC) --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) -j4 --no-print-directory -C arm9
@$(MAKE) -j$(NPROC) --no-print-directory -C arm9
#---------------------------------------------------------------------------------
arm11/$(TARGET)11.bin:
@$(MAKE) -j4 --no-print-directory -C arm11
@$(MAKE) -j$(NPROC) --no-print-directory -C arm11
#---------------------------------------------------------------------------------
clean:
@$(MAKE) --no-print-directory -C arm9 clean
@$(MAKE) --no-print-directory -C arm11 clean
rm -f $(TARGET).firm *.7z
rm -fr $(TARGET).firm *.7z nightly
#---------------------------------------------------------------------------------
release: clean
@$(MAKE) -j4 --no-print-directory -C arm9 NO_DEBUG=1
@$(MAKE) -j4 --no-print-directory -C arm11 NO_DEBUG=1
@$(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
@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 libn3ds/thirdparty/fatfs/LICENSE.txt thirdparty/inih/LICENSE.txt LICENSE.txt README.md
@7z rn $(TARGET)$(VERS_STRING).7z resources/gba_db.bin 3ds/open_agb_firm/gba_db.bin libn3ds/thirdparty/fatfs/LICENSE.txt LICENSE_fatfs.txt thirdparty/inih/LICENSE.txt LICENSE_inih.txt
@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

191
README.md
View File

@ -6,10 +6,16 @@ open_agb_firm is also a complete and better alternative to GBA VC injects (AGB_F
* 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.
## Disclaimer
open_agb_firm is currently in alpha. 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.
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.
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.
@ -18,14 +24,23 @@ Additionally, we are not responsible for any damage that may occur to your syste
* 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.
* After open_agb_firm launches, use the file browser to navigate to a `.gba` ROM to run.
## Controls
A/B/L/R/START/SELECT - GBA buttons, respectively
SELECT+Y - Dump screen output to `/3ds/open_agb_firm/texture_dump.bmp`
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
@ -34,58 +49,160 @@ Settings are stored in `/3ds/open_agb_firm/config.ini`.
### General
General settings.
`u8 backlight` - Backlight brightness
`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.
`bool biosIntro` - Show GBA BIOS intro at game startup
`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 useGbaDb` - Use `gba_db.bin` to get save types
`bool useSavesFolder` - Use `/3ds/open_agb_firm/saves` for save files instead of the ROM directory.
* Default: `true`
### Video
Video-related settings.
`float inGamma` - Screen input gamma
* Default: `2.2`
`string scaler` - Video scaler.
* Default: `matrix`
* Options: `none`, `bilinear`, `matrix`
`float outGamma` - Screen output gamma
* Default : `1.54`
`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
`float contrast` - Screen gain. No effect when `colorProfile=none`.
* Default: `1.0`
`float brightness` - Screen lift
`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
`bool saveOverride` - Open save type override menu after selecting a game.
* Default: `false`
`u16 defaultSave` - Change save type default when save type is not in `gba_db.bin` and cannot be autodetected
* Default: `14` (SRAM 256k)
* Possible values:
* `0`, `1`: EEPROM 8k
* `2`, `3`: EEPROM 64k
* `4`, `6`, `8`: Flash 512k RTC
* `5`, `7`, `9`: Flash 512k
* `10`, `12`: Flash 1m RTC
* `11`, `13`: Flash 1m
* `14`: SRAM 256k
* `15`: None
`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
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 (including brightness control during gameplay).
* Lack of settings.
* 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.
@ -99,6 +216,7 @@ open_agb_firm using the 3DS's built-in GBA hardware. Unfortunately, this comes w
* \>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).
## 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.
@ -130,13 +248,24 @@ A: There's a good chance that the save you're having issues with is an EEPROM sa
**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)
* [Corelink DMA-330 Assembler](https://github.com/profi200/dma330as)
* [CTR Firm Builder](https://github.com/derrekr/ctr_firm_builder)
* [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 `firmbuilder` binaries are in the PATH environment variable and accessible to the Makefile.
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`.
@ -158,7 +287,9 @@ You may use this under the terms of the GNU General Public License GPL v3 or the
* **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 freenode**
* **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)**
* ...everyone who contributed to **3dbrew.org**
Copyright (C) 2021 derrek, profi200, d0k3
Copyright (C) 2024 derrek, profi200, d0k3

View File

@ -8,6 +8,7 @@ endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
include $(TOPDIR)/../libraries/libn3ds/libn3ds11.mk
#---------------------------------------------------------------------------------
# TARGET is the name of the output
@ -18,15 +19,11 @@ include $(DEVKITARM)/base_rules
#---------------------------------------------------------------------------------
#TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := ../libn3ds/kernel/source ../libn3ds/source ../libn3ds/source/drivers/mmc \
../libn3ds/source/drivers ../libn3ds/source/arm11 ../libn3ds/source/arm11/allocator \
../libn3ds/source/arm11/drivers ../libn3ds/source/arm11/util/rbtree ../source/arm11 \
../thirdparty/inih
SOURCES += ../source ../source/arm11 ../libraries/inih
DATA :=
INCLUDES := ../libn3ds/include ../libn3ds/kernel/include ../libn3ds/thirdparty ../include \
../thirdparty
DEFINES := -DARM11 -D_3DS -DVERS_STRING=\"$(VERS_STRING)\" \
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR) -DOAF_SCALE_SELECT=2
INCLUDES += ../include ../libraries
DEFINES := -D__ARM11__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
ASSETS :=
ifneq ($(strip $(NO_DEBUG)),)
@ -36,18 +33,18 @@ endif
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork
ARCH := -march=armv6k+vfpv2 -mtune=mpcore -mfloat-abi=hard -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
CFLAGS := $(ARCH) -std=c17 -O2 -g -flto -mword-relocations \
CFLAGS := $(ARCH) -std=c23 -O2 -gdwarf-4 -flto -mword-relocations \
-ffunction-sections -fno-math-errno -Wall -Wextra
CFLAGS += $(INCLUDE) $(DEFINES)
CXXFLAGS := $(ARCH) -std=c++17 -O2 -g -flto -fno-rtti -fno-exceptions \
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
-mword-relocations -ffunction-sections -fno-math-errno -Wall -Wextra
CXXFLAGS += $(INCLUDE) $(DEFINES)
ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES)
LDFLAGS = $(ARCH) -g -flto -specs=../arm11.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
ASFLAGS := $(ARCH) -gdwarf-4 -flto $(INCLUDE) $(DEFINES)
LDFLAGS = $(ARCH) -gdwarf-4 -flto -specs=../arm11.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
ifeq ($(strip $(NO_DEBUG)),)
CFLAGS := $(subst -flto,,$(CFLAGS)) -fstack-protector-strong -fno-inline

View File

@ -8,6 +8,7 @@ endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/base_rules
include $(TOPDIR)/../libraries/libn3ds/libn3ds9.mk
#---------------------------------------------------------------------------------
# TARGET is the name of the output
@ -18,11 +19,10 @@ include $(DEVKITARM)/base_rules
#---------------------------------------------------------------------------------
#TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := ../libn3ds/source ../libn3ds/source/drivers/mmc ../libn3ds/source/drivers ../libn3ds/source/arm9 \
../libn3ds/source/arm9/drivers ../libn3ds/thirdparty/fatfs ../source/arm9
SOURCES += ../source/arm9
DATA :=
INCLUDES := ../libn3ds/include ../libn3ds/thirdparty ../include ../thirdparty
DEFINES := -DARM9 -D_3DS -DVERS_STRING=\"$(VERS_STRING)\" \
INCLUDES += ../include
DEFINES := -D__ARM9__ -D__3DS__ -DLIBN3DS_LEGACY=1 -DVERS_STRING=\"$(VERS_STRING)\" \
-DVERS_MAJOR=$(VERS_MAJOR) -DVERS_MINOR=$(VERS_MINOR)
ifneq ($(strip $(NO_DEBUG)),)
@ -32,18 +32,18 @@ endif
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork
ARCH := -march=armv5te -mtune=arm946e-s -mfloat-abi=soft -mtp=soft -marm -mthumb-interwork -masm-syntax-unified
CFLAGS := $(ARCH) -std=c17 -O2 -g -flto -mword-relocations \
CFLAGS := $(ARCH) -std=c23 -O2 -gdwarf-4 -flto -mword-relocations \
-ffunction-sections -Wall -Wextra
CFLAGS += $(INCLUDE) $(DEFINES)
CXXFLAGS := $(ARCH) -std=c++17 -O2 -g -flto -fno-rtti -fno-exceptions \
CXXFLAGS := $(ARCH) -std=c++23 -O2 -gdwarf-4 -flto -fno-rtti -fno-exceptions \
-mword-relocations -ffunction-sections -Wall -Wextra
CXXFLAGS += $(INCLUDE) $(DEFINES)
ASFLAGS := $(ARCH) -g -flto $(INCLUDE) $(DEFINES)
LDFLAGS = $(ARCH) -g -flto -specs=../arm9.specs -Wl,-Map,$(notdir $*.map) -nostartfiles
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

89
include/arm11/bitmap.h Normal file
View File

@ -0,0 +1,89 @@
#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

76
include/arm11/config.h Normal file
View File

@ -0,0 +1,76 @@
#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

View File

@ -2,7 +2,7 @@
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* 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
@ -18,9 +18,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
noreturn void _start(void);
void deinitCpu(void);
void convert160pFrameFast(void);
void convert240pFrameFast(void);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -2,7 +2,7 @@
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* 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
@ -22,6 +22,13 @@
noreturn void panic();
noreturn void panicMsg(const char *msg);
//void dumpMem(u8 *mem, u32 size, char *filepath);
#ifdef __cplusplus
extern "C"
{
#endif
void makeOpenBusPaddingFast(u32 *romEnd);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -22,4 +22,13 @@
#ifdef __cplusplus
extern "C"
{
#endif
Result browseFiles(const char *const basePath, char selected[512]);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -21,433 +21,25 @@
#include "types.h"
#if OAF_SCALE_SELECT == 0
// 240x160 no scaling, no filter.
alignas(16) static const u8 gbaGpuInitList[1136] =
#ifdef __cplusplus
extern "C"
{
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, 0x00, 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, 0x45, 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, 0x40, 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, 0x40, 0x46, 0x00, 0x00,
0x00, 0x40, 0x45, 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, 0x40, 0x46, 0x00, 0x00, 0x00, 0x40, 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
};
// 240x160 no 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, 0x45, 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, 0x40, 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, 0x40, 0x46, 0x00, 0x00, 0x00, 0x40, 0x45, 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,
0x40, 0x46, 0x00, 0x00, 0x00, 0x40, 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
};
#elif OAF_SCALE_SELECT == 1
// 240x160 with bilinear scaling to 360x240, 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
};
// 240x160 with bilinear scaling to 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, 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
};
#elif OAF_SCALE_SELECT == 2
// 360x240, 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, 0x02, 0x00, 0x02, 0x00, 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
};
// 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
};
#endif
#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

View File

@ -1,8 +1,6 @@
#pragma once
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* 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
@ -19,7 +17,9 @@
*/
#include "types.h"
#include "kernel.h"
void deinitCpu(void);
KHandle OAF_videoInit(void);
void OAF_videoExit(void);

View File

@ -22,6 +22,17 @@
#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

View File

@ -2,7 +2,7 @@
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* Copyright (C) 2022 spitzeqc
*
* 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,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "types.h"
#ifdef __cplusplus
extern "C"
{
#endif
//void WEAK __systemInit(void);
void WEAK __systemDeinit(void);
Result patchRom(const char *const gamePath, u32 *romSize);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -2,7 +2,7 @@
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* Copyright (C) 2023 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,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "types.h"
#include "kernel.h"
#include "arm11/config.h"
#ifdef __cplusplus
@ -29,21 +30,17 @@ extern "C"
typedef struct
{
u32 r4;
u32 r5;
u32 r6;
u32 r7;
u32 r8;
u32 r9;
u32 r10;
u32 r11;
u32 lr; // pc
} cpuRegs;
u8 sha1[20];
char serial[4];
u32 attr;
} GbaDbEntry;
static_assert(sizeof(GbaDbEntry) == 28, "Error: GBA DB entry struct is not packed!");
KRes switchContext(KRes res, uintptr_t *oldSp, uintptr_t newSp);
u16 detectSaveType(const u32 romSize, const u16 defaultSave);
u16 getSaveType(const OafConfig *const cfg, const u32 romSize, const char *const savePath);
#ifdef __cplusplus
}
#endif
} // extern "C"
#endif

View File

@ -2,7 +2,7 @@
/*
* This file is part of open_agb_firm
* Copyright (C) 2021 derrek, profi200
* Copyright (C) 2022 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,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kernel.h"
#include "error_codes.h"
#ifdef __cplusplus
@ -26,18 +26,28 @@ extern "C"
{
#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
/*KHandle createTimer(bool pulse);
void deleteTimer(KHandle const ktimer);
void startTimer(KHandle const ktimer, uint32_t usec);
void stopTimer(KHandle const ktimer);
KRes waitForTimer(KHandle const ktimer);*/
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
#endif

View File

@ -1,324 +0,0 @@
#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/>.
*/
#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, inst, ...) \
ALWAYS_INLINE void __##name(void) \
{ \
if(isVolatile == 1) \
__asm__ volatile(inst : : : __VA_ARGS__); \
else \
__asm__(inst : : : __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, "nop")
MAKE_INTR_NO_INOUT(1, wfi, "wfi", "memory")
MAKE_INTR_NO_INOUT(1, wfe, "wfe", "memory")
MAKE_INTR_NO_INOUT(1, sev, "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, "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_NO_INOUT(1, wfi, "mcr p15, 0, r0, 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__

View File

@ -1,47 +0,0 @@
/**
* @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);

View File

@ -1,192 +0,0 @@
#pragma once
/*
* This code is part of libctru (https://github.com/devkitPro/libctru)
*/
/**
* @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 "drivers/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

View File

@ -1,50 +0,0 @@
#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"
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" : :);
}*/

View File

@ -1,123 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define CFG11_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x40000)
typedef struct
{
vu8 sharedwram_32k_code[8]; // 0x000
vu8 sharedwram_32k_data[8]; // 0x008
u8 _0x10[0xf0];
vu32 nullpage_cnt; // 0x100
vu8 fiq_mask; // 0x104
vu8 unk105; // 0x105 Debug related? Mask?
u8 _0x106[2];
vu8 unk108; // 0x108 LGY gamecard related?
u8 _0x109[3];
vu8 cdma_cnt; // 0x10C
u8 _0x10d[3];
vu8 unk110; // 0x110 VRAM related?
u8 _0x111[0x2f];
vu16 gpuprot; // 0x140
u8 _0x142[0x3e];
vu8 wifi_power; // 0x180 Used for flight mode?
u8 _0x181[0x3f];
vu16 spi_cnt; // 0x1C0
u8 _0x1c2[0x3e];
vu32 unk200; // 0x200 GPIO3 related? 8x4 bits.
u8 _0x204[0x1fc];
vu8 gpu_n3ds_cnt; // 0x400 New3DS-only.
u8 _0x401[0xf];
vu32 cdma_peripherals; // 0x410 New3DS-only.
u8 _0x414[0xc];
vu8 bootrom_overlay_cnt; // 0x420 New3DS-only.
u8 _0x421[3];
vu32 bootrom_overlay_val; // 0x424 New3DS-only.
vu8 unk428; // 0x429 New3DS-only. 1 bit. Enable CPU core 1 access to overlay regs?
u8 _0x429[0xbd3];
const vu16 socinfo; // 0xFFC
} Cfg11;
static_assert(offsetof(Cfg11, socinfo) == 0xFFC, "Error: Member socinfo of Cfg11 is not at offset 0xFFC!");
ALWAYS_INLINE Cfg11* getCfg11Regs(void)
{
return (Cfg11*)CFG11_REGS_BASE;
}
// REG_CFG11_NULLPAGE_CNT
#define NULLPAGE_CNT_FAULT_EN (1u) // All data accesses to 0x000-0xFFF generate data aborts.
#define NULLPAGE_CNT_ACCESSED (1u<<16) // 0x000-0xFFF has been accessed flag. Write 0 to clear.
// REG_CFG11_FIQ_MASK
// Each bit 1 = masked/disabled.
#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_EN (1u)
#define CDMA_CNT_NTRCARD_EN (1u<<1)
#define CDMA_CNT_CAM1_EN (1u<<2)
#define CDMA_CNT_CAM2_EN (1u<<3)
#define CDMA_CNT_TOSHSD2_EN (1u<<4) // WiFi
#define CDMA_CNT_TOSHSD3_EN (1u<<5)
// REG_CFG11_GPUPROT
// When the lower FCRAM protection is set to non-zero,
// the first 0x800000 bytes of upper FCRAM are protected.
#define GPUPROT_FCRAM_LO(x) (x) // Protect lower 128 MiB of FCRAM (0x28000000-(0x800000*x)).
#define GPUPROT_FCRAM_UP(x) ((x)<<4) // Protect upper 128 MiB of FCRAM (0x30000000-(0x800000*x)) (New3DS-only).
#define GPUPROT_AXIWRAM (1u<<8) // Protect AXIWRAM.
#define GPUPROT_QTM(x) ((x)<<9) // Protect QTM RAM (0x1F400000-(0x100000*x)). 2 bits. TODO: Confirm this.
#define GPUPROT_NO_PROT (0u)
#define GPUPROT_PROT_ALL (GPUPROT_QTM(3u) | GPUPROT_AXIWRAM | \
GPUPROT_FCRAM_UP(15u) | GPUPROT_FCRAM_LO(15u))
// 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
// Each bit 1 = DMA requests go to CDMA2.
// TODO: Add individual periphals.
#define CDMA_PERIPHERALS_ALL (0x3FFFFu)
// REG_CFG11_BOOTROM_OVERLAY_CNT
#define BOOTROM_OVERLAY_CNT_EN (1u)
// REG_CFG11_SOCINFO
#define SOCINFO_CTR (1u) // Also set on New 3DS.
#define SOCINFO_LGR1 (1u<<1) // Never saw the daylight? Set on retail N3DS (LGR2).
#define SOCINFO_LGR2 (1u<<2) // Set on New 3DS.

View File

@ -1,56 +0,0 @@
#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"
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);

View File

@ -1,321 +0,0 @@
#pragma once
// Based on Texas Instruments TSC2117 SLAS550B.
// Adjusted for the custom Texas Instruments PAIC3010B, AIC3010B, AIC3010D
// and possibly other variants.
enum
{
CDC_REG_PAGE_CTRL = 0u, // Available on every page.
// ----------------------------------------------------------------------------------
// Control Registers, Page 0 (Default Page):
// Clock Multipliers, Dividers, Serial Interfaces, Flags, Interrupts, and GPIOs.
CDC_REG_SOFT_RST_TWL = 1u,
CDC_REG_0_2 = 2u, // Vendor and device ID?
CDC_REG_0_3 = 3u, // Revision?
CDC_REG_CLK_GEN_MUXING = 4u,
CDC_REG_PLL_P_R_VAL = 5u,
CDC_REG_PLL_J_VAL = 6u,
CDC_REG_PLL_D_VAL_MSB = 7u,
CDC_REG_PLL_D_VAL_LSB = 8u,
// 9-10 reserved.
CDC_REG_DAC_NDAC_VAL = 11u,
CDC_REG_DAC_MDAC_VAL = 12u,
// 13 DAC DOSR_VAL MSB?
// 14 DAC DOSR_VAL LSB?
// 15 DAC IDAC_VAL?
// 16 DAC miniDSP Engine Interpolation?
// 17 reserved.
CDC_REG_ADC_NADC_VAL = 18u,
CDC_REG_ADC_MADC_VAL = 19u,
// 20 ADC AOSR_VAL?
// 21 ADC IADC_VAL?
// 22 ADC miniDSP Engine Decimation?
// 23-24 reserved.
// 25 CLKOUT MUX?
// 26 CLKOUT M_VAL?
CDC_REG_INTERFACE_CTRL = 27u, // Audio
// 28 Data-Slot Offset Programmability?
// 29 Codec Interface Control 2?
// 30 BCLK N_VAL?
// 31 Codec Secondary Interface Control 1?
// 32 Codec Secondary Interface Control 2?
// 33 Codec Secondary Interface Control 3?
CDC_REG_I2C_BUS_COND = 34u, // I2C Bus Condition.
// 35 reserved.
CDC_REG_ADC_FLAG = 36u,
CDC_REG_DAC_FLAG1 = 37u, // TODO: Validate.
CDC_REG_DAC_FLAG2 = 38u, // TODO: Validate.
CDC_REG_OVERFLOW_FLAGS = 39u,
// 40-43 reserved.
CDC_REG_INT_FLAGS_DAC = 44u, // Interrupt Flags—DAC.
CDC_REG_INT_FLAGS_ADC = 45u, // Interrupt Flags—ADC.
// 46 Interrupt Flags DAC? Same as 44?
// 47 Interrupt Flags ADC? Same as 45?
// 48 INT1 Control Register?
// 49 INT2 Control Register?
CDC_REG_INT1_INT2_CTRL = 50u, // TODO: Validate.
CDC_REG_GPIO1_INOUT_PIN_CTRL = 51u, // TODO: Validate.
CDC_REG_GPIO2_INOUT_PIN_CTRL = 52u, // TODO: Validate.
CDC_REG_SDOUT_PIN_CTRL = 53u, // TODO: Validate.
// 54 SDIN (IN Pin) Control?
// 55 MISO (OUT Pin) Control?
// 56 SCLK (IN Pin) Control?
CDC_REG_GPI1_GPI2_PIN_CTRL = 57u, // TODO: Validate.
CDC_REG_GPI3_PIN_CTRL = 58u, // TODO: Validate.
// 59 reserved.
CDC_REG_DAC_INSTR_SET = 60u, // DAC Instruction Set.
CDC_REG_ADC_INSTR_SET = 61u, // ADC Instruction Set.
// 62 Programmable Instruction Mode-Control Bits?
CDC_REG_DAC_DATA_PATH_SETUP = 63u, // I2S1?
CDC_REG_DAC_VOLUME_CTRL = 64u, // I2S1?
CDC_REG_DAC_L_VOLUME_CTRL = 65u, // I2S1?
CDC_REG_DAC_R_VOLUME_CTRL = 66u, // I2S1?
// 67 Headset Detection?
// 68 DRC Control 1?
// 69 DRC Control 2?
// 70 DRC Control 3?
CDC_REG_L_BEEP_GEN = 71u, // Left Beep Generator.
CDC_REG_R_BEEP_GEN = 72u, // Right Beep Generator.
CDC_REG_BEEP_LEN_MSB = 73u,
CDC_REG_BEEP_LEN_MID_BITS = 74u, // Beep Length Middle Bits.
CDC_REG_BEEP_LEN_LSB = 75u,
CDC_REG_BEEP_SIN_X_MSB = 76u, // Beep Sin(x) MSB.
CDC_REG_BEEP_SIN_X_LSB = 77u, // Beep Sin(x) LSB.
CDC_REG_BEEP_COS_X_MSB = 78u, // Beep Cos(x) MSB.
CDC_REG_BEEP_COS_X_LSB = 79u, // Beep Cos(x) LSB.
// 80 reserved.
CDC_REG_ADC_DIGITAL_MIC = 81u, // TODO: Validate.
CDC_REG_ADC_DIG_VOL_FINE_ADJ = 82u, // TODO: Validate. ADC Digital Volume Control Fine Adjust.
// 83 ADC Digital Volume Control Coarse Adjust?
// 84-85 reserved.
CDC_REG_AGC_CTRL1 = 86u,
CDC_REG_AGC_CTRL2 = 87u,
CDC_REG_AGC_MAX_GAIN = 88u,
CDC_REG_AGC_ATTACK_TIME = 89u,
CDC_REG_AGC_DECAY_TIME = 90u,
CDC_REG_AGC_NOISE_DEBOUNCE = 91u,
CDC_REG_AGC_SIGNAL_DEBOUNCE = 92u,
CDC_REG_AGC_GAIN_APPLIED = 93u,
// 94-101 reserved.
// 102 ADC DC Measurement 1?
// 103 ADC DC Measurement 2?
// 104 ADC DC Measurement Output 1?
// 105 ADC DC Measurement Output 2?
// 106 ADC DC Measurement Output 3?
// 107-115 reserved.
CDC_REG_VOL_MICDET_PIN_SAR_ADC = 116u, // TODO: Validate.
// 117 VOL/MICDET-Pin Gain?
// 118-127 reserved.
// ----------------------------------------------------------------------------------
// Control Registers, Page 1:
// DAC and ADC Routing, PGA, Power-Controls and MISC Logic Related Programmabilities:
// 1-29 reserved.
// 30 Headphone and Speaker Amplifier Error Control?
CDC_REG_HEADPHONE_DRIVERS = 1u<<8 | 31u,
CDC_REG_CLASS_D_SPEAKER_AMP = 1u<<8 | 32u, // TODO: Validate.
CDC_REG_HP_POP_REM_SETTINGS = 1u<<8 | 33u, // HP Output Drivers POP Removal Settings.
CDC_REG_OUT_PGA_RD_PERIOD_CTRL = 1u<<8 | 34u, // Output Driver PGA Ramp-Down Period Control.
CDC_REG_DAC_LR_OUT_MIX_ROUTING = 1u<<8 | 35u, // DAC_L and DAC_R Output Mixer Routing.
CDC_REG_L_ANALOG_VOL_TO_HPL = 1u<<8 | 36u,
CDC_REG_R_ANALOG_VOL_TO_HPR = 1u<<8 | 37u,
CDC_REG_L_ANALOG_VOL_TO_SPL = 1u<<8 | 38u,
CDC_REG_R_ANALOG_VOL_TO_SPR = 1u<<8 | 39u,
CDC_REG_HPL_DRIVER = 1u<<8 | 40u,
CDC_REG_HPR_DRIVER = 1u<<8 | 41u,
CDC_REG_SPL_DRIVER = 1u<<8 | 42u,
CDC_REG_SPR_DRIVER = 1u<<8 | 43u,
// 44 HP Driver Control?
// 45 reserved.
CDC_REG_MICBIAS = 1u<<8 | 46u,
CDC_REG_MIC_PGA = 1u<<8 | 47u, // TODO: Validate.
CDC_REG_ADC_IN_SEL_FOR_P_TERMINAL = 1u<<8 | 48u, // TODO: Validate. Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal.
CDC_REG_ADC_IN_SEL_FOR_M_TERMINAL = 1u<<8 | 49u, // ADC Input Selection for M-Terminal.
CDC_REG_INPUT_CM_SETTINGS = 1u<<8 | 50u,
// 51-127 reserved.
// ----------------------------------------------------------------------------------
// Control Registers, Page 3: TSC Control and Data Programmabilities.
// 1 reserved.
CDC_REG_SAR_ADC_CTRL = 3u<<8 | 2u, // First ADC?
CDC_REG_SAR_ADC_CTRL2 = 3u<<8 | 3u, // TODO: Validate.
CDC_REG_PRECHARGE_AND_SENSE = 3u<<8 | 4u,
CDC_REG_PANEL_VOLT_STABIL = 3u<<8 | 5u, // Panel Voltage Stabilization.
CDC_REG_VOLT_REF = 3u<<8 | 6u, // TODO: Validate. Voltage Reference.
// 7-8 reserved.
CDC_REG_STATUS_BIT = 3u<<8 | 9u,
CDC_REG_STATUS_BIT2 = 3u<<8 | 10u, // TODO: Validate.
// 11-12 reserved.
// 13 Buffer Mode?
CDC_REG_RESERVED_3_14 = 3u<<8 | 14u, // Buffer mode moved here?
CDC_REG_SCAN_MODE_TIMER = 3u<<8 | 15u,
CDC_REG_SCAN_MODE_TIMER_CLK = 3u<<8 | 16u,
CDC_REG_SAR_ADC_CLK = 3u<<8 | 17u,
CDC_REG_DEBOUNCE_TIME_PEN_UP = 3u<<8 | 18u, // Debounce Time for Pen-Up Detection.
CDC_REG_AUTO_AUX_MEASURE_SEL = 3u<<8 | 19u, // Auto AUX Measurement Selection.
CDC_REG_TOUCH_PEN_DOWN = 3u<<8 | 20u, // TODO: Validate. Touch-Screen Pen Down.
CDC_REG_TRESHOLD_CHECK_FLAGS = 3u<<8 | 21u,
// 22 AUX1 Maximum Value Check (MSB)?
// 23 AUX1 Maximum Value Check (LSB)?
// 24 AUX1 Minimum Value Check (MSB)?
// 25 AUX1 Minimum Value Check (LSB)?
// 26 AUX2 Maximum Value Check (MSB)?
// 27 AUX2 Maximum Value Check (LSB)?
// 28 AUX2 Minimum Value Check (MSB)?
// 29 AUX2 Minimum Value Check (LSB)?
CDC_REG_TEMP_MAX_VAL_CHECK_MSB = 3u<<8 | 30u, // Temperature Maximum Value Check (MSB).
CDC_REG_TEMP_MAX_VAL_CHECK_LSB = 3u<<8 | 31u, // Temperature Maximum Value Check (LSB).
CDC_REG_TEMP_MIN_VAL_CHECK_MSB = 3u<<8 | 32u, // Temperature Minimum Value Check (MSB).
CDC_REG_TEMP_MIN_VAL_CHECK_LSB = 3u<<8 | 33u, // Temperature Minimum Value Check (LSB).
// 34-41 reserved.
CDC_REG_X_COORDINATE_DATA_MSB = 3u<<8 | 42u,
CDC_REG_X_COORDINATE_DATA_LSB = 3u<<8 | 43u,
CDC_REG_Y_COORDINATE_DATA_MSB = 3u<<8 | 44u,
CDC_REG_Y_COORDINATE_DATA_LSB = 3u<<8 | 45u,
// 46 Z1 MSB Register?
// 47 Z1 LSB Register?
// 48 Z2 MSB Register?
// 49 Z2 LSB Register
// 50-53 reserved.
CDC_REG_AUX1_DATA_MSB = 3u<<8 | 54u, // TODO: Validate.
CDC_REG_AUX1_DATA_LSB = 3u<<8 | 55u, // TODO: Validate.
CDC_REG_AUX2_DATA_MSB = 3u<<8 | 56u, // TODO: Validate.
CDC_REG_AUX2_DATA_LSB = 3u<<8 | 57u, // TODO: Validate.
CDC_REG_VBAT_DATA_MSB = 3u<<8 | 58u, // TODO: Validate.
CDC_REG_VBAT_DATA_LSB = 3u<<8 | 59u, // TODO: Validate.
// 60-65 reserved.
CDC_REG_TEMP1_MSB_DATA = 3u<<8 | 66u,
CDC_REG_TEMP1_LSB_DATA = 3u<<8 | 67u,
CDC_REG_TEMP2_MSB_DATA = 3u<<8 | 68u,
CDC_REG_TEMP2_LSB_DATA = 3u<<8 | 69u,
// 70-127 reserved.
// ----------------------------------------------------------------------------------
// Page 4.
// ----------------------------------------------------------------------------------
// Page 5.
// ----------------------------------------------------------------------------------
// Page 8.
// ----------------------------------------------------------------------------------
// Page 9.
// ----------------------------------------------------------------------------------
// Page 10.
// ----------------------------------------------------------------------------------
// Page 11.
// ----------------------------------------------------------------------------------
// Page 12.
// ----------------------------------------------------------------------------------
// Page 100 (only CTR).
CDC_REG_SOFT_RST_CTR = 100u<<8 | 1u,
// 2-33 reserved?
CDC_REG_100_34 = 100u<<8 | 34u,
// 35-36 reserved?
CDC_REG_100_37 = 100u<<8 | 37u,
CDC_REG_100_38 = 100u<<8 | 38u,
CDC_REG_100_39 = 100u<<8 | 39u,
// 40-43 reserved?
CDC_REG_100_44 = 100u<<8 | 44u,
CDC_REG_100_48 = 100u<<8 | 48u,
CDC_REG_100_49 = 100u<<8 | 49u,
// 50-66 reserved?
CDC_REG_100_67 = 100u<<8 | 67u,
CDC_REG_100_68 = 100u<<8 | 68u,
CDC_REG_HEADSET_SEL = 100u<<8 | 69u,
// 70-116 reserved?
CDC_REG_100_117 = 100u<<8 | 117u,
CDC_REG_100_118 = 100u<<8 | 118u,
CDC_REG_100_119 = 100u<<8 | 119u,
CDC_REG_100_120 = 100u<<8 | 120u,
CDC_REG_100_121 = 100u<<8 | 121u,
CDC_REG_100_122 = 100u<<8 | 122u,
CDC_REG_100_123 = 100u<<8 | 123u,
CDC_REG_100_124 = 100u<<8 | 124u,
// 125-128 reserved?
// ----------------------------------------------------------------------------------
// Page 101 (only CTR).
// 1-7 reserved?
CDC_REG_101_8 = 101u<<8 | 8u,
CDC_REG_101_9 = 101u<<8 | 9u,
CDC_REG_101_10 = 101u<<8 | 10u,
CDC_REG_101_11 = 101u<<8 | 11u,
CDC_REG_101_12 = 101u<<8 | 12u,
// 13-16 reserved?
CDC_REG_101_17 = 101u<<8 | 17u,
CDC_REG_101_18 = 101u<<8 | 18u,
CDC_REG_101_19 = 101u<<8 | 19u,
// 20-21 reserved?
CDC_REG_101_22 = 101u<<8 | 22u,
CDC_REG_101_23 = 101u<<8 | 23u,
// 24-26 reserved?
CDC_REG_101_27 = 101u<<8 | 27u,
CDC_REG_101_28 = 101u<<8 | 28u,
// 29-50 reserved?
CDC_REG_101_51 = 101u<<8 | 51u,
// 52-64 reserved?
CDC_REG_101_65 = 101u<<8 | 65u,
CDC_REG_101_66 = 101u<<8 | 66u,
// 67-69 reserved?
CDC_REG_101_70 = 101u<<8 | 70u,
CDC_REG_101_71 = 101u<<8 | 71u,
CDC_REG_101_72 = 101u<<8 | 72u,
// 73-118 reserved?
CDC_REG_101_119 = 101u<<8 | 119u,
CDC_REG_101_120 = 101u<<8 | 120u,
// 121 reserved?
CDC_REG_101_122 = 101u<<8 | 122u,
// 123-128 reserved?
// ----------------------------------------------------------------------------------
// Page 103 (only CTR).
// 1-22 reserved?
CDC_REG_103_23 = 103u<<8 | 23u,
CDC_REG_103_24 = 103u<<8 | 24u,
CDC_REG_103_25 = 103u<<8 | 25u,
CDC_REG_103_26 = 103u<<8 | 26u,
CDC_REG_103_27 = 103u<<8 | 27u,
// 28-35 reserved?
CDC_REG_103_36 = 103u<<8 | 36u,
CDC_REG_103_37 = 103u<<8 | 37u,
CDC_REG_103_38 = 103u<<8 | 38u,
CDC_REG_103_39 = 103u<<8 | 39u,
// 40-128 reserved?
// ----------------------------------------------------------------------------------
// Page 251 (only CTR).
// ----------------------------------------------------------------------------------
// Page 252.
// ----------------------------------------------------------------------------------
// Page 255 (only CTR).
// 1 reserved?
// 2 reserved?
// 3 reserved?
// 4 reserved?
CDC_REG_TWL_MODE = 255<<8 | 5u
};
// ----------------------------------------------------------------------------------
// CDC_REG_HEADSET_SEL (page 100 (0x64), reg 69 (0x45))
#define HEADSET_SEL_HP_SHIFT (4u)
#define HEADSET_SEL_SP (0u) // Force speaker output.
#define HEADSET_SEL_HP (1u<<HEADSET_SEL_HP_SHIFT) // Force headphone output.
#define HEADSET_SEL_HP_EN (1u<<5) // Enable headphone override.
#define HEADSET_SEL_MIC_SHIFT (6u)
#define HEADSET_SEL_INT_MIC (0u) // Force internal microphone input.
#define HEADSET_SEL_EXT_MIC (1u<<HEADSET_SEL_MIC_SHIFT) // Force external microphone input.
#define HEADSET_SEL_MIC_EN (1u<<7) // Enable microphone override.

View File

@ -1,235 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define CSND_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x3000)
typedef struct
{
vu16 cnt; // 0x00
vs16 sr; // 0x02 Samplerate.
union
{
struct
{
vu16 vol_r; // 0x04 Range 0-0x8000.
vu16 vol_l; // 0x06 Range 0-0x8000.
};
vu32 vol; // 0x04 R and L combined.
};
union
{
struct
{
vu16 capvol_r; // 0x08 Unconfirmed. Range 0-0x8000.
vu16 capvol_l; // 0x0A Unconfirmed. Range 0-0x8000.
};
vu32 capvol; // 0x08 R and L combined.
};
vu32 st_addr; // 0x0C Start address and playback position.
vu32 size; // 0x10 Size in bytes.
vu32 lp_addr; // 0x14 Loop restart address.
vu32 st_adpcm; // 0x18 Start IMA-ADPCM state.
vu32 lp_adpcm; // 0x1C Loop Restart IMA-ADPCM state.
} CsndCh;
static_assert(offsetof(CsndCh, lp_adpcm) == 0x1C, "Error: Member lp_adpcm of CsndCh is not at offset 0x1C!");
typedef struct
{
vu16 cnt; // 0x0
u8 _0x2[2];
vs16 sr; // 0x4 Samplerate.
u8 _0x6[2];
vu32 size; // 0x8 Capture length in bytes.
vu32 addr; // 0xC Address.
} CsndCap;
static_assert(offsetof(CsndCap, addr) == 0xC, "Error: Member addr of CsndCap is not at offset 0xC!");
typedef struct
{
vu16 master_vol; // 0x000 CSND master volume range 0-0x8000.
vu16 unk_cnt; // 0x002
u8 _0x4[0xc];
vu32 unk010; // 0x010 FIFO related?
vu8 unk014; // 0x014 FIFO related?
u8 _0x15[0x3eb];
CsndCh ch[32]; // 0x400 32 sound channels. PSG on channel 8-13 and noise 14-15.
CsndCap cap[2]; // 0x800 2 capture units for right and left side.
} Csnd;
static_assert(offsetof(Csnd, cap[1].addr) == 0x81C, "Error: Member cap[1].addr of Csnd is not at offset 0x81C!");
ALWAYS_INLINE Csnd* getCsndRegs(void)
{
return (Csnd*)CSND_REGS_BASE;
}
ALWAYS_INLINE CsndCh* getCsndChRegs(u8 ch)
{
return &getCsndRegs()->ch[ch];
}
ALWAYS_INLINE CsndCap* getCsndCapRegs(u8 ch)
{
return &getCsndRegs()->cap[ch];
}
// 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_LERP (1u<<6) // Linear interpolation.
#define CSND_CH_HOLD (1u<<7) // Hold last sample after one shot.
#define CSND_CH_RPT_MANUAL (0u<<10)
#define CSND_CH_RPT_LOOP (1u<<10)
#define CSND_CH_RPT_ONE_SHOT (2u<<10)
#define CSND_CH_FMT_PCM8 (0u<<12) // Signed PCM8.
#define CSND_CH_FMT_PCM16 (1u<<12) // Signed PCM16 little endian.
#define CSND_CH_FMT_IMA_ADPCM (2u<<12)
#define CSND_CH_FMT_PSG_NOISE (3u<<12)
#define CSND_CH_PLAYING (1u<<14)
#define CSND_CH_START (1u<<15)
// 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.f)<<16 | (u32)(rvol * 32768.f);
}
/**
* @brief Sets up a channel for sound playback (in paused state).
*
* @param[in] ch The sound channel. 0-31.
* @param[in] srFreq The sample rate/frequency.
* @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 srFreq, u32 vol, const u32 *const data, const u32 *const data2, u32 size, u16 flags);
/**
* @brief Sets the sample rate/frequency of a channel.
*
* @param[in] ch The sound channel. 0-31.
* @param[in] srFreq The sample rate/frequency.
*/
static inline void CSND_setSrFreq(u8 ch, s16 srFreq)
{
getCsndChRegs(ch)->sr = srFreq;
}
/**
* @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)
{
CsndCh *const csndCh = getCsndChRegs(ch);
csndCh->cnt = (csndCh->cnt & ~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 getCsndChRegs(ch)->st_addr;
}
/**
* @brief Stops a sound channel.
*
* @param[in] ch The sound channel. 0-31.
*/
static inline void CSND_stopCh(u8 ch)
{
getCsndChRegs(ch)->cnt = 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] sr The sample rate.
* @param data The output address.
* @param[in] size The size.
* @param[in] flags The flags.
*/
void CSND_startCap(u8 ch, s16 sr, 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 getCsndCapRegs(ch)->addr;
}
/**
* @brief Stops a capture channel.
*
* @param[in] ch The capture side. 0 = right, 1 = left.
*/
static inline void CSND_stopCap(u8 ch)
{
getCsndCapRegs(ch)->cnt = 0;
}

View File

@ -1,86 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.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 GIC_DIST_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x1000)
typedef struct
{
vu32 ctrl; // 0x00 Control Register.
vu32 primask; // 0x04 Priority Mask Register.
vu32 binpoint; // 0x08 Binary Point Register.
const vu32 intack; // 0x0C Interrupt Acknowledge Register.
vu32 eoi; // 0x10 End of Interrupt Register.
const vu32 runningpri; // 0x14 Running Priority Register.
const vu32 highpri; // 0x18 Highest Pending Interrupt Register.
} GicCpu;
static_assert(offsetof(GicCpu, highpri) == 0x18, "Error: Member highpri of GicCpu is not at offset 0x18!");
typedef struct
{
vu32 ctrl; // 0x000 Interrupt Distributor Control Register.
const vu32 ctr; // 0x004 Interrupt Controller Type Register.
u8 _0x8[0xf8];
vu32 enable_set[8]; // 0x100 Interrupt Enable set Registers.
u8 _0x120[0x60];
vu32 enable_clear[8]; // 0x180 Interrupt Enable clear Registers.
u8 _0x1a0[0x60];
vu32 pending_set[8]; // 0x200 Interrupt Pending set Registers.
u8 _0x220[0x60];
vu32 pending_clear[8]; // 0x280 Interrupt Pending clear Registers.
u8 _0x2a0[0x60];
const vu32 active_set[8]; // 0x300 Interrupt Active Bit Registers.
u8 _0x320[0xe0];
vu32 pri[64]; // 0x400 Interrupt Priority Registers.
u8 _0x500[0x300];
vu32 target[64]; // 0x800 Interrupt CPU targets Registers.
u8 _0x900[0x300];
vu32 config[16]; // 0xC00 Interrupt Configuration Registers.
u8 _0xc40[0xc0];
const vu32 line_level[8]; // 0xD00 Interrupt Line Level Registers.
u8 _0xd20[0x1e0];
vu32 softint; // 0xF00 Software Interrupt Register.
u8 _0xf04[0xdc];
const vu32 periph_ident0; // 0xFE0 Periphal Identification Register 0.
const vu32 periph_ident1; // 0xFE4 Periphal Identification Register 1.
const vu32 periph_ident2; // 0xFE8 Periphal Identification Register 2.
const vu32 periph_ident3; // 0xFEC Periphal Identification Register 3.
const vu32 primecell0; // 0xFF0 PrimeCell Identification Register 0.
const vu32 primecell1; // 0xFF4 PrimeCell Identification Register 1.
const vu32 primecell2; // 0xFF8 PrimeCell Identification Register 2.
const vu32 primecell3; // 0xFFC PrimeCell Identification Register 3.
} GicDist;
static_assert(offsetof(GicDist, primecell3) == 0xFFC, "Error: Member primecell3 of GicDist is not at offset 0xFFC!");
ALWAYS_INLINE GicCpu* getGicCpuRegs(void)
{
return (GicCpu*)GIC_CPU_REGS_BASE;
}
ALWAYS_INLINE GicDist* getGicDistRegs(void)
{
return (GicDist*)GIC_DIST_REGS_BASE;
}

View File

@ -1,120 +0,0 @@
#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"
#include "mem_map.h"
#define GPIO_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x47000)
// 3 GPIOs (bits 0-2)
#define REG_GPIO1_DAT *((const vu8*)(GPIO_REGS_BASE + 0x00)) // Read-only.
// 2 GPIOs (bits 0-1)
#define REG_GPIO2 *(( vu32*)(GPIO_REGS_BASE + 0x10))
#define REG_GPIO2_DAT *(( vu8*)(GPIO_REGS_BASE + 0x10))
#define REG_GPIO2_DIR *(( vu8*)(GPIO_REGS_BASE + 0x11)) // 0 = input, 1 = output.
#define REG_GPIO2_EDGE *(( vu8*)(GPIO_REGS_BASE + 0x12)) // IRQ edge 0 = falling, 1 = rising.
#define REG_GPIO2_IRQ *(( vu8*)(GPIO_REGS_BASE + 0x13)) // 1 = IRQ enable.
// 1 GPIO (bit 0)
#define REG_GPIO2_DAT2 *(( vu16*)(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable.
// 12 GPIOs (bits 0-11)
#define REG_GPIO3_H1 *(( vu32*)(GPIO_REGS_BASE + 0x20)) // First half.
#define REG_GPIO3_DAT *(( vu16*)(GPIO_REGS_BASE + 0x20))
#define REG_GPIO3_DIR *(( vu16*)(GPIO_REGS_BASE + 0x22))
#define REG_GPIO3_H2 *(( vu32*)(GPIO_REGS_BASE + 0x24)) // Second half.
#define REG_GPIO3_EDGE *(( vu16*)(GPIO_REGS_BASE + 0x24))
#define REG_GPIO3_IRQ *(( vu16*)(GPIO_REGS_BASE + 0x26))
// 1 GPIO (bit 0)
#define REG_GPIO3_DAT2 *(( vu16*)(GPIO_REGS_BASE + 0x28)) // WiFi.
#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. See defines above.
*/
void GPIO_config(Gpio gpio, u8 cfg);
/**
* @brief Reads a GPIO pin.
*
* @param[in] gpio The gpio.
*
* @return The state. Either 0 or 1.
*/
u8 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, u8 val);

View File

@ -1,769 +0,0 @@
// From https://github.com/devkitPro/libctru/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.
///@}

View File

@ -1,59 +0,0 @@
#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"
#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)))

View File

@ -1,105 +0,0 @@
#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/>.
*/
/*
* 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)) ^ 0xFFFu)
#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);

View File

@ -1,164 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define I2C1_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x61000)
#define I2C2_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x44000)
#define I2C3_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x48000)
typedef struct
{
vu8 data; // 0x0
vu8 cnt; // 0x1
vu16 cntex; // 0x2
vu16 scl; // 0x4
} I2cBus;
static_assert(offsetof(I2cBus, scl) == 4, "Error: Member scl of I2cBus is not at offset 4!");
enum
{
I2C_BUS1 = 0u,
I2C_BUS2 = 1u,
I2C_BUS3 = 2u
};
ALWAYS_INLINE I2cBus* getI2cBusRegs(u8 busId)
{
switch(busId)
{
case I2C_BUS1:
return (I2cBus*)I2C1_REGS_BASE;
case I2C_BUS2:
return (I2cBus*)I2C2_REGS_BASE;
case I2C_BUS3:
return (I2cBus*)I2C3_REGS_BASE;
default:
return NULL;
}
}
// 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_W (0u)
#define I2C_DIR_R (1u<<5)
#define I2C_IRQ_EN (1u<<6)
#define I2C_EN (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);

View File

@ -1,202 +0,0 @@
#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"
#include "arm.h"
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_TOSHSD2 = 64u, // Toshsd 2 SDIO controller (WiFi).
IRQ_TOSHSD2_IRQ = 65u, // Toshsd 2 SDIO IRQ pin (WiFi).
IRQ_TOSHSD3 = 66u, // Toshsd 3 SDIO controller.
IRQ_TOSHSD3_IRQ = 67u, // Toshsd 3 SDIO 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_softInterrupt(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

View File

@ -1,151 +0,0 @@
#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"
#include "mem_map.h"
#include "arm11/drivers/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);

View File

@ -1,102 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#include "kevent.h"
#define LGYFB_TOP_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x11000)
#define LGYFB_BOT_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x10000)
#define LGYFB_TOP_FIFO *((const vu32*)(0x10311000))
#define LGYFB_BOT_FIFO *((const vu32*)(0x10310000))
typedef struct
{
vu32 len; // 0x00
vu32 patt; // 0x04
u8 _0x8[0x38];
vu32 matrix[6][8]; // 0x40
} LgyFbScaler;
typedef struct
{
vu32 cnt; // 0x000
vu32 size; // 0x004
vu32 stat; // 0x008
vu32 irq; // 0x00C
vu32 flush; // 0x010 Write 0 to flush LgyFb FIFO.
u8 _0x14[0xc];
vu32 alpha; // 0x020 8 bit alpha for all pixels.
u8 _0x24[0xcc];
vu32 unkF0; // 0x0F0
u8 _0xf4[0xc];
vu32 dithpatt0[2]; // 0x100 2 u32 regs with 4x2 pattern bits (mask 0xCCCC) each.
vu32 dithpatt1[2]; // 0x108 2 u32 regs with 4x2 pattern bits (mask 0xCCCC) each.
u8 _0x110[0xf0];
LgyFbScaler v; // 0x200
LgyFbScaler h; // 0x300
} LgyFb;
static_assert(offsetof(LgyFb, h.matrix[5][7]) == 0x3FC, "Error: Member h.matrix[5][7] of LgyFb is not at offset 0x3FC!");
ALWAYS_INLINE LgyFb* getLgyFbRegs(bool top)
{
return (LgyFb*)(top ? LGYFB_TOP_REGS_BASE : LGYFB_BOT_REGS_BASE);
}
// REG_LGYFB_CNT
#define LGYFB_EN (1u)
#define LGYFB_VSCALE_EN (1u<<1)
#define LGYFB_HSCALE_EN (1u<<2)
#define LGYFB_SPATIAL_DITHER_EN (1u<<4) // Unset behaves like weight 0xCCCC in both pattern regs.
#define LGYFB_TEMPORAL_DITHER_EN (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_EN (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(KHandle frameReadyEvent);
void LGYFB_deinit(void);
#ifndef NDEBUG
void LGYFB_dbgDumpFrame(void);
#endif

View File

@ -1,132 +0,0 @@
#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"
#include "arm11/drivers/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];
}

View File

@ -1,151 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define PDN_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x41000)
typedef struct
{
vu16 cnt; // 0x000
u8 _0x2[6];
vu32 wake_enable; // 0x008
vu32 wake_reason; // 0x00C Write 1 to acknowledge and 0 to clear?
// Some LGY regs are located inbetween. See lgy.h/c.
u8 _0x10[0x1f0];
vu32 gpu_cnt; // 0x200
vu8 vram_cnt; // 0x204 This reg doesn't seem to exist on retail hardware.
u8 _0x205[3];
vu8 lcd_cnt; // 0x208 This reg doesn't seem to exist on retail hardware.
u8 _0x209[7];
vu8 fcram_cnt; // 0x210
u8 _0x211[0xf];
vu8 i2s_cnt; // 0x220
u8 _0x221[3];
vu8 cam_cnt; // 0x224
u8 _0x225[0xb];
vu8 dsp_cnt; // 0x230
u8 _0x231[0xF];
vu8 g1_cnt; // 0x240 Hantro G1 decoder aka MVD.
u8 _0x241[0xbf];
vu16 lgr_socmode; // 0x300
u8 _0x302[2];
vu16 lgr_cnt; // 0x304 Is this reg actually only vu8?
u8 _0x306[0xa];
vu8 lgr_cpu_cnt[4]; // 0x310
} Pdn;
static_assert(offsetof(Pdn, lgr_cpu_cnt[3]) == 0x313, "Error: Member lgr_cpu_cnt[3] of Pdn is not at offset 0x313!");
ALWAYS_INLINE Pdn* getPdnRegs(void)
{
return (Pdn*)PDN_REGS_BASE;
}
// 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
#define PDN_WAKE_PADCNT (1u)
#define PDN_WAKE_SHELL_OPENED (1u<<3)
#define PDN_WAKE_HEADPH_NOT_PLUGGED_IN (1u<<4) // Really?
#define PDN_WAKE_UNK6 (1u<<6) // DSi mode related.
#define PDN_WAKE_SDIO1 (1u<<7)
#define PDN_WAKE_SDIO2 (1u<<8)
#define PDN_WAKE_SDIO3 (1u<<16)
// 17-28 maybe GPIO3 0-11?
#define PDN_WAKE_GAMECARD_INSERT (1u<<29) // ?
#define PDN_WAKE_TOUCHPEN_DOWN (1u<<30)
#define PDN_WAKE_UNK31 (1u<<31) // Also shell related?
// REG_PDN_GPU_CNT
// Note: The resets are active low.
#define PDN_GPU_CNT_NORST_REGS (1u) // And more?
#define PDN_GPU_CNT_NORST_PSC (1u<<1) // ?
#define PDN_GPU_CNT_NORST_GEOSHADER (1u<<2) // ?
#define PDN_GPU_CNT_NORST_RASTERIZER (1u<<3) // ?
#define PDN_GPU_CNT_NORST_PPF (1u<<4)
#define PDN_GPU_CNT_NORST_PDC (1u<<5) // ?
#define PDN_GPU_CNT_NORST_PDC2 (1u<<6) // Maybe pixel pipeline or so?
#define PDN_GPU_CNT_NORST_ALL ((PDN_GPU_CNT_NORST_PDC2<<1) - 1)
#define PDN_GPU_CNT_CLK_EN (1u<<16)
// REG_PDN_VRAM_CNT
#define PDN_VRAM_CNT_CLK_EN (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_NORST (1u)
#define PDN_FCRAM_CNT_CLK_EN (1u<<1)
#define PDN_FCRAM_CNT_CLK_EN_ACK (1u<<2) // Gets set or unset depending on CLK_E.
// REG_PDN_I2S_CNT
#define PDN_I2S_CNT_I2S_CLK1_EN (1u) // ? Unused?
#define PDN_I2S_CNT_I2S_CLK2_EN (1u<<1)
// REG_PDN_CAM_CNT
#define PDN_CAM_CNT_CLK_EN (1u)
// REG_PDN_DSP_CNT
// Note: Reset is active low.
#define PDN_DSP_CNT_NORST (1u)
#define PDN_DSP_CNT_CLK_EN (1u<<1)
// REG_PDN_G1_CNT
// TODO: Active low or high?
#define PDN_G1_CNT_NORST (1u)
// REG_PDN_LGR_SOCMODE
typedef enum
{
SOCMODE_CTR_268MHZ = 0u,
SOCMODE_LGR2_268MHZ = 1u, // Also enables FCRAM extension.
SOCMODE_LGR1_268MHZ = 2u, // Also enables FCRAM extension?
SOCMODE_LGR1_536MHZ = 3u, // Also enables FCRAM extension?
SOCMODE_LGR2_804MHZ = 5u, // Also enables FCRAM extension.
SOCMODE_MASK = 7u
} PdnSocmode;
#define PDN_LGR_SOCMODE_ACK (1u<<15)
// REG_PDN_LGR_CNT
#define PDN_LGR_CNT_WRAM_EXT_EN (1u) // QTM WRAM enable.
#define PDN_LGR_CNT_L2C_EN (1u<<8) // L2C L2 cache enable.
// REGs_PDN_LGR_CPU_CNT
// Note: Reset is active low.
#define LGR_CPU_CNT_NORST (1u) // Core 2/3 only. Reset and instruction overlay enable.
#define LGR_CPU_CNT_D_OVERL_EN (1u<<1) // Core 2/3 only. Data overlay enable. Also used to signal a core booted.
#define LGR_CPU_CNT_RST_STAT (1u<<4) // Reset status.
#define LGR_CPU_CNT_UNK (1u<<5) // Something ready?
void PDN_core123Init(void);
void PDN_setSocmode(PdnSocmode socmode);
void PDN_poweroffCore23(void);

View File

@ -1,135 +0,0 @@
#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/>.
*/
// Based on ARM11 MPCore™ Processor Revision: r2p0 Technical Reference Manual (DDI0360F_arm11_mpcore_r2p0_trm.pdf).
#if !__ASSEMBLER__
#include "types.h"
#endif // #if !__ASSEMBLER__
// Performance Monitor Control Register (PMNC).
#define PM_EN (1u) // All three counters enabled.
#define PM_PMN01_RST (1u<<1) // Reset both Count Registers to 0x0.
#define PM_CCNT_RST (1u<<2) // Reset the Cycle Counter Register to 0x0.
#define PM_CCNT_NODIV (0u) // Cycle Counter Register counts every processor clock cycle.
#define PM_CCNT_DIV64 (1u<<3) // Cycle Counter Register counts every 64th processor clock cycle.
#define PM_PMN0_IRQ_EN (1u<<4) // Count Register 0 interrupt enable.
#define PM_PMN1_IRQ_EN (1u<<5) // Count Register 1 interrupt enable.
#define PM_CCNT_IRQ_EN (1u<<6) // Cycle Counter interrupt enable.
#define PM_PMN0_IRQ (1u<<8) // Count Register 0 overflow flag. Write 1 to clear.
#define PM_PMN1_IRQ (1u<<9) // Count Register 1 overflow flag. Write 1 to clear.
#define PM_CCNT_IRQ (1u<<10) // Cycle Counter Register overflow flag. Write 1 to clear.
#define PM_EVT(pmn1, pmn0) ((pmn0)<<20 | (pmn1)<<12) // Set what events PMN0/1 count. See events below.
// Performance monitor events.
#define PM_EVT_ICACHE_MISS (0x00u) // Instruction cache miss to a cachable location requires fetch from external memory.
#define PM_EVT_INST_BUF_STALL (0x01u) // Stall because instruction buffer cannot deliver an instruction. This can indicate an instruction cache miss or an instruction MicroTLB miss. This event occurs every cycle where the condition is present.
#define PM_EVT_DATA_DEP_STALL (0x02u) // Stall because of a data dependency. This event occurs every cycle where the condition is present.
#define PM_EVT_INST_MICROTLB_MISS (0x03u) // Instruction MicroTLB miss.
#define PM_EVT_DATA_MICROTLB_MISS (0x04u) // Data MicroTLB miss.
#define PM_EVT_BRANCH_EXEC (0x05u) // Branch instruction executed, branch might or might not have changed program flow.
#define PM_EVT_BRANCH_NOT_PRED (0x06u) // Branch not predicted.
#define PM_EVT_BRANCH_MISPRED (0x07u) // Branch mispredicted.
#define PM_EVT_INST_EXEC (0x08u) // Instruction executed.
#define PM_EVT_FOLD_INST_EXEC (0x09u) // Folded instruction executed.
#define PM_EVT_DCACHE_RD (0x0Au) // Data cache read access, not including cache operations. This event occurs for each non-sequential access to a cache line.
#define PM_EVT_DCACHE_RD_MISS (0x0Bu) // Data cache read miss, not including cache operations.
#define PM_EVT_DCACHE_WR (0x0Cu) // Data cache write access.
#define PM_EVT_DCACHE_WR_MISS (0x0Du) // Data cache write miss.
#define PM_EVT_DCACHE_LINE_EVICT (0x0Eu) // Data cache line eviction, not including cache operations.
#define PM_EVT_PC_CHANGE_NOT_MODE (0x0Fu) // Software changed the PC and there is not a mode change.
#define PM_EVT_TLB_MISS (0x10u) // Main TLB miss.
#define PM_EVT_EXT_MEM_REQ (0x11u) // External memory request (cache refill, noncachable, write-back).
#define PM_EVT_LD_ST_UNIT_STALL (0x12u) // Stall because of Load Store Unit request queue being full.
#define PM_EVT_ST_BUF_DRAIN (0x13u) // The number of times the Store buffer was drained because of LSU ordering constraints or CP15 operations.
#define PM_EVT_BUF_WR_MERGED (0x14u) // Buffered write merged in a store buffer slot.
#define PM_EVT_CYCLE (0xFFu) // An increment each cycle.
#if !__ASSEMBLER__
// Write Performance Monitor Control Register.
ALWAYS_INLINE void __setPmnc(u32 val)
{
__asm__ volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val) : "memory");
}
// Write Cycle Counter Register.
ALWAYS_INLINE void __setCcnt(u32 val)
{
__asm__ volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val) : "memory");
}
// Read Count Register 0.
ALWAYS_INLINE void __setPmn0(u32 val)
{
__asm__ volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val) : "memory");
}
// Read Count Register 1.
ALWAYS_INLINE void __setPmn1(u32 val)
{
__asm__ volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val) : "memory");
}
// Read Performance Monitor Control Register.
ALWAYS_INLINE u32 __getPmnc(void)
{
u32 tmp;
__asm__ volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (tmp) : : "memory");
return tmp;
}
// Read Cycle Counter Register.
ALWAYS_INLINE u32 __getCcnt(void)
{
u32 tmp;
__asm__ volatile("mrc p15, 0, %0, c15, c12, 1" : "=r" (tmp) : : "memory");
return tmp;
}
// Write Count Register 0.
ALWAYS_INLINE u32 __getPmn0(void)
{
u32 tmp;
__asm__ volatile("mrc p15, 0, %0, c15, c12, 2" : "=r" (tmp) : : "memory");
return tmp;
}
// Write Count Register 1.
ALWAYS_INLINE u32 __getPmn1(void)
{
u32 tmp;
__asm__ volatile("mrc p15, 0, %0, c15, c12, 3" : "=r" (tmp) : : "memory");
return tmp;
}
// Helpers.
// Note: Make sure the performance monitor is off
// before starting to count cycles to avoid
// misleading counter results.
ALWAYS_INLINE void perfMonitorCountCycles(void)
{
__setPmnc(PM_EVT(PM_EVT_INST_EXEC, PM_EVT_ICACHE_MISS) | PM_CCNT_IRQ | PM_PMN1_IRQ |
PM_PMN0_IRQ | PM_CCNT_NODIV | PM_CCNT_RST | PM_PMN01_RST | PM_EN);
}
#endif // #if !__ASSEMBLER__

View File

@ -1,58 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define PL301_REGS_BASE (IO_MEM_ARM11_ONLY + 0xF400)
typedef struct
{
struct
{
vu32 qos_tidemark; // 0x000 QoS tidemark.
vu32 qos_acs; // 0x004 QoS access control.
vu32 ar_arb; // 0x008 AR channel arbitration value.
vu32 aw_arb; // 0x00C AW channel arbitration value.
u8 _0x10[0x10];
} mi[64]; // Master interface.
u8 _0x800[0x7c0];
const vu32 primecell_cfg0; // 0xFC0 PrimeCell Configuration Register 0.
const vu32 primecell_cfg1; // 0xFC4 PrimeCell Configuration Register 1.
const vu32 primecell_cfg2; // 0xFC8 PrimeCell Configuration Register 2.
const vu32 primecell_cfg3; // 0xFCC PrimeCell Configuration Register 3.
u8 _0xfd0[0x10];
const vu32 primecell_periph0; // 0xFE0 PrimeCell Peripheral Register 0.
const vu32 primecell_periph1; // 0xFE4 PrimeCell Peripheral Register 1.
const vu32 primecell_periph2; // 0xFE8 PrimeCell Peripheral Register 2.
const vu32 primecell_periph3; // 0xFEC PrimeCell Peripheral Register 3.
const vu32 primecell_id0; // 0xFF0 PrimeCell ID Register 0.
const vu32 primecell_id1; // 0xFF4 PrimeCell ID Register 1.
const vu32 primecell_id2; // 0xFF8 PrimeCell ID Register 2.
const vu32 primecell_id3; // 0xFFC PrimeCell ID Register 3.
} Pl301;
static_assert(offsetof(Pl301, primecell_id3) == 0xFFC, "Error: Member primecell_id3 of Pl301 is not at offset 0xFFC!");
ALWAYS_INLINE Pl301* getPl301Regs(void)
{
return (Pl301*)PL301_REGS_BASE;
}

View File

@ -1,96 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define SCU_REGS_BASE (MPCORE_PRIV_REG_BASE)
typedef struct
{
vu32 ctrl; // 0x00 SCU Control Register.
const vu32 config; // 0x04 SCU Configuration Register.
vu32 cpu_stat; // 0x08 SCU CPU Status Register.
vu32 inval_all; // 0x0C SCU Invalidate All Register. (write-only)
vu32 pmc; // 0x10 Performance Monitor Control Register.
vu32 pme0; // 0x14 Performance monitor event register 0.
vu32 pme1; // 0x18 Performance monitor event register 1.
vu32 mn0; // 0x1C Count register 0.
vu32 mn1; // 0x20 Count register 1.
vu32 mn2; // 0x24 Count register 2.
vu32 mn3; // 0x28 Count register 3.
vu32 mn4; // 0x2C Count register 4.
vu32 mn5; // 0x30 Count register 5.
vu32 mn6; // 0x34 Count register 6.
vu32 mn7; // 0x38 Count register 7.
} Scu;
static_assert(offsetof(Scu, mn7) == 0x38, "Error: Member mn7 of Scu is not at offset 0x38!");
ALWAYS_INLINE Scu* getScuRegs(void)
{
return (Scu*)SCU_REGS_BASE;
}
// REG_SCU_CTRL
#define SCU_EN (1u) // SCU is enabled, coherency is maintained between MP11 CPUs Level 1 data side caches.
#define SCU_ACS(n) (1u<<((n) + 1)) // CPUn can write to SCU-specific registers.
#define SCU_INT_ALIAS_ACS(n) (1u<<((n) + 5)) // CPUn can access aliased interrupt interface registers in the offset range 0x0200 to 0x050FF of the MPCore private memory region.
#define SCU_TMR_ALIAS_ACS(n) (1u<<((n) + 9)) // CPUn can access aliased timer and watchdog registers in the offset range 0x0700 to 0x0A0FF of the MPCore private memory region.
#define SCU_PARITY_CHK_EN (1u<<13) // SCU parity checking enable bit.
#define SCU_CTRL_RST_VAL (SCU_TMR_ALIAS_ACS(3u) | SCU_TMR_ALIAS_ACS(2u) | \
SCU_TMR_ALIAS_ACS(1u) | SCU_TMR_ALIAS_ACS(0u) | \
SCU_INT_ALIAS_ACS(3u) | SCU_INT_ALIAS_ACS(2u) | \
SCU_INT_ALIAS_ACS(1u) | SCU_INT_ALIAS_ACS(0u) | \
SCU_ACS(3u) | SCU_ACS(2u) | SCU_ACS(1u) | SCU_ACS(0u))
// REG_SCU_CONFIG
#define SCU_CPU_NUM_1 (0u) // 1 MP11 CPU, CPU0.
#define SCU_CPU_NUM_2 (1u) // 2 MP11 CPUs, CPU0-CPU1.
#define SCU_CPU_NUM_3 (2u) // 3 MP11 CPUs, CPU0-CPU2.
#define SCU_CPU_NUM_4 (3u) // 4 MP11 CPUs, CPU0-CPU3.
#define SCU_CPU_NUM_MASK (SCU_CPU_NUM_4)
#define SCU_SMP(n) (1u<<((n) + 4)) // MP11 CPUn is in SMP mode taking part in coherency.
#define SCU_TRAM_16KB_64I(n) (0u) // CPUn 16KB cache, 64 indexes per tag RAM.
#define SCU_TRAM_32KB_128I(n) (1u<<((n) * 2 + 8)) // CPUn 32KB cache, 128 indexes per tag RAM.
#define SCU_TRAM_64KB_256I(n) (2u<<((n) * 2 + 8)) // CPUn 64KB cache, 256 indexes per tag RAM.
// REG_SCU_CPU_STAT
#define SCU_STAT_NORMAL(n) (0u) // CPUn Normal mode (Default).
// 1 reserved.
#define SCU_STAT_DORMANT(n) (2u<<((n) * 2)) // CPUn is about to enter (or is in) dormant mode. No CCB request is sent to the CPU.
#define SCU_STAT_PWROFF(n) (3u<<((n) * 2)) // CPUn is about to enter (or is in) powered-off mode, or is nonpresent. No CCB request is sent to the CPU.
#define SCU_STAT_MASK(n) (SCU_STAT_PWROFF(n))
// REG_SCU_INVAL_ALL
#define SCU_WAY_0(n) (1u<<((n) * 4)) // CPUn invalidate way 0.
#define SCU_WAY_1(n) (2u<<((n) * 4)) // CPUn invalidate way 1.
#define SCU_WAY_2(n) (4u<<((n) * 4)) // CPUn invalidate way 2.
#define SCU_WAY_3(n) (8u<<((n) * 4)) // CPUn invalidate way 3.
#define SCU_WAY_ALL (SCU_WAY_3(3u) | SCU_WAY_2(3u) | SCU_WAY_1(3u) | \
SCU_WAY_0(3u) | SCU_WAY_3(2u) | SCU_WAY_2(2u) | \
SCU_WAY_1(2u) | SCU_WAY_0(2u) | SCU_WAY_3(1u) | \
SCU_WAY_2(1u) | SCU_WAY_1(1u) | SCU_WAY_0(1u) | \
SCU_WAY_3(0u) | SCU_WAY_2(0u) | SCU_WAY_1(0u) | \
SCU_WAY_0(0u))
// TODO: SCU performance monitor bits.

View File

@ -1,178 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define NSPI1_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x60800)
#define NSPI2_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x42800)
#define NSPI3_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x43800)
typedef struct
{
vu32 cnt; // 0x00
vu8 cs; // 0x04 32 bit but can be accessed as u8.
u8 _0x5[3];
vu32 blklen; // 0x08
vu32 fifo; // 0x0C
vu8 fifo_stat; // 0x10 32 bit but can be accessed as u8.
u8 _0x11[3];
vu32 autopoll; // 0x14
vu32 int_mask; // 0x18
vu32 int_stat; // 0x1C
} NspiBus;
static_assert(offsetof(NspiBus, int_stat) == 0x1C, "Error: Member int_stat of NspiBus is not at offset 0x1C!");
enum
{
SPI_BUS1 = 0u,
SPI_BUS2 = 1u,
SPI_BUS3 = 2u
};
ALWAYS_INLINE NspiBus* getNspiBusRegs(u8 busId)
{
NspiBus *nspiBus;
switch(busId)
{
case SPI_BUS1:
nspiBus = (NspiBus*)NSPI1_REGS_BASE;
break;
case SPI_BUS2:
nspiBus = (NspiBus*)NSPI2_REGS_BASE;
break;
case SPI_BUS3:
nspiBus = (NspiBus*)NSPI3_REGS_BASE;
break;
default:
nspiBus = NULL;
}
return nspiBus;
}
// REG_NSPI_CNT
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
};
enum
{
NSPI_CS_0 = 0u<<6,
NSPI_CS_1 = 1u<<6,
NSPI_CS_2 = 2u<<6
};
#define NSPI_BUS_1BIT (0u)
#define NSPI_BUS_4BIT (1u<<12)
#define NSPI_DIR_R (0u) // Direction read.
#define NSPI_DIR_W (1u<<13) // Direction write.
#define NSPI_EN (1u<<15) // Enable.
// REG_NSPI_CS
#define NSPI_CS_HIGH (0u)
// NSPI_FIFO_STAT
#define NSPI_FIFO_BUSY (1u)
// REG_NSPI_AUTOPOLL
// Shifts.
#define NSPI_AP_TMOUT_SHIFT (16u) // Auto poll register timeout shift.
#define NSPI_AP_OFF_SHIFT (24u) // Auto poll register bit offset shift.
#define NSPI_AP_BIT_SHIFT (30u) // Auto poll register compare bit shift.
#define NSPI_AP_START (1u<<31) // Auto poll start.
// REG_NSPI_INT_MASK Bit set = disabled.
// REG_NSPI_INT_STAT Status and acknowledge.
#define NSPI_INT_TRAN_END (1u) // Transfer end. Also fires on each auto poll try.
#define NSPI_INT_AP_MATCH (1u<<1) // Auto poll bit match.
#define NSPI_INT_AP_TMOUT (1u<<2) // Auto poll timeout.
// TODO: Implement old SPI interfaces.
// 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.
};*/
typedef enum
{
NSPI_DEV_POWERMAN = 0u, // DS(i) mode power management.
NSPI_DEV_NVRAM = 1u, // WiFi SPI flash.
NSPI_DEV_TWL_CODEC = 2u, // DSi mode SPI interface.
NSPI_DEV_CTR_CODEC = 3u, // 3DS mode SPI interface.
//NSPI_DEV_UNUSED5 = 4u, // Unused.
//NSPI_DEV_UNUSED6 = 5u, // Unused.
//NSPI_DEV_UNUSED7 = 6u, // Debugger?
// Not a real device. Or with device number
// to set chip select high after transfer.
NSPI_DEV_CS_HIGH = 1u<<7
} SpiDevice;
// cmd Is the command byte to send.
// tmout Is the timeout. Must be 0-15. Tries = 31<<(NspiClk + timeout).
// off Is the bit offset in the response byte. Must be 0-7.
// cmpBit Is the bit to compare (0 or 1).
#define MAKE_AP_PARAMS(cmd, tmout, off, cmpBit) ((u32)(cmpBit)<<30 | (u32)(off)<<24 | (u32)(tmout)<<16 | (cmd))
/**
* @brief Initializes the SPI buses. Call this only once.
*/
void NSPI_init(void);
/**
* @brief Automatically polls a bit of the command response.
*
* @param[in] dev The device ID. See SpiDevice table.
* @param[in] apParams The parameters. Use the MAKE_AP_PARAMS macro.
*
* @return Returns false on timeout and true on bit match.
*/
bool NSPI_autoPollBit(SpiDevice dev, u32 apParams);
/**
* @brief Writes and/or reads data to/from a SPI device.
*
* @param[in] dev The device ID. See SpiDevice table.
* @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.
*/
void NSPI_writeRead(SpiDevice dev, const u32 *in, u32 *out, u32 inSize, u32 outSize);

View File

@ -1,31 +0,0 @@
#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"
#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);

View File

@ -1,116 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define TIMER_REGS_BASE (MPCORE_PRIV_REG_BASE + 0x600)
typedef struct
{
vu32 load; // 0x00
vu32 counter; // 0x04
vu32 cnt; // 0x08
vu32 int_stat; // 0x0C
u8 _0x10[0x10];
vu32 wd_load; // 0x20
vu32 wd_counter; // 0x24
vu32 wd_cnt; // 0x28
vu32 wd_int_stat; // 0x2C
vu32 wd_reset_stat; // 0x30
vu32 wd_disable; // 0x34
} Timer;
static_assert(offsetof(Timer, wd_disable) == 0x34, "Error: Member wd_disable of Timer is not at offset 0x34!");
ALWAYS_INLINE Timer* getTimerRegs(void)
{
return (Timer*)TIMER_REGS_BASE;
}
// REG_TIMER_CNT/REG_WD_CNT
#define TIMER_EN (1u)
#define TIMER_SINGLE_SHOT (0u)
#define TIMER_AUTO_RELOAD (1u<<1)
#define TIMER_IRQ_EN (1u<<2)
#define WD_TIMER_MODE (0u) // Watchdog only. Watchdog in timer mode.
#define WD_WD_MODE (1u<<3) // Watchdog only. Watchdog in watchdog mode.
#define TIMER_PRESC_SHIFT (8u) // Shift helper for the prescalers.
// REG_WD_DISABLE
#define WD_DISABLE_MAGIC1 (0x12345678u)
#define WD_DISABLE_MAGIC2 (0x87654321u)
#define TIMER_BASE_FREQ (268111856.f)
// p is the prescaler value and n the frequency.
// Note: With highest prescaler and sub-microsecond frequency
// this may give wrong results due to overflows.
#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 (1-256).
* @param[in] ticks The initial number of ticks. This is also the reload
* value in auto reload mode.
* @param[in] params The parameters. See /regs/timer.h "REG_TIMER_CNT" defines.
*/
void TIMER_start(u16 prescaler, u32 ticks, u8 params);
/**
* @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 given number of ticks.
* Use the function below for milliseconds.
*
* @param[in] ticks The number of ticks to sleep.
*/
void TIMER_sleepTicks(u32 ticks);
// Sleeps ms milliseconds. ms can be up to 32000.
// TODO: Should this be inline? Generates a bunch of vfp code.
ALWAYS_INLINE void TIMER_sleepMs(u32 ms)
{
TIMER_sleepTicks(TIMER_FREQ(1, 1000) * ms);
}

View File

@ -1,48 +0,0 @@
#pragma once
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include <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

View File

@ -1,24 +0,0 @@
#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/>.
*/
noreturn void power_off(void);
noreturn void power_reboot(void);

View File

@ -1,45 +0,0 @@
#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"
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");
}

View File

@ -1,149 +0,0 @@
/**
* @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

View File

@ -1,30 +0,0 @@
#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"
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[];

View File

@ -1,124 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define CFG9_REGS_BASE (IO_MEM_ARM9_ONLY)
typedef struct
{
vu8 sysprot9; // 0x00000
vu8 sysprot11; // 0x00001
vu8 unk00002; // 0x00002 Bit 0 bootrom write enable? Cleared immediately in boot9.
u8 _0x3;
vu16 unk00004; // 0x00004 JTAG related?
u8 _0x6[2];
vu8 xdma_req; // 0x00008 Enable requests for XDMA. Each bit 1 = enabled.
u8 _0x9[3];
vu16 cardctl; // 0x0000C
u8 _0xe[2];
vu8 card_power; // 0x00010
u8 _0x11;
vu16 card_insert_delay; // 0x00012 Insert delay in 0x400 cycle units.
vu16 card_pwroff_delay; // 0x00014 Power off delay in 0x400 cycle units.
u8 _0x16[0xa];
vu16 sdmmcctl; // 0x00020
u8 _0x22[0xde];
vu16 unk00100; // 0x00100 Similar to SCFG_EXT regs on DSi?
u8 _0x102[0xfe];
vu8 extmemcnt9; // 0x00200
u8 _0x201[0xdfb];
const vu16 socinfo; // 0x00FFC Same as REG_CFG11_SOCINFO.
u8 _0xffe[0xf002];
vu32 bootenv; // 0x10000
u8 _0x10004[0xc];
const vu8 unitinfo; // 0x10010
u8 _0x10011[3];
vu8 twlunitinfo; // 0x10014 Writable reg for TWL mode.
u8 _0x10015[0xb];
vu8 unk10020; // 0x10020 Bootrom related?
} Cfg9;
static_assert(offsetof(Cfg9, unk10020) == 0x10020, "Error: Member unk10020 of Cfg9 is not at offset 0x10020!");
ALWAYS_INLINE Cfg9* getCfg9Regs(void)
{
return (Cfg9*)CFG9_REGS_BASE;
}
// REG_CFG9_SYSPROT9
#define SYSPROT9_ROM_H2_LOCK (1u) // Disables access to the second half of the ARM9 bootrom. Also enables FCRAM access.
#define SYSPROT9_OTP_LOCK (1u<<1) // Disables access to the OTP.
// REG_CFG9_SYSPROT11
#define SYSPROT11_ROM_H2_LOCK (1u) // Disables access to the second half of the ARM11 bootrom. Also enables FCRAM access.
// REG_CFG9_XDMA_REQ
#define XDMA_REQ_TOSHSD1 (1u) // Toshsd controller 1 (SD/eMMC).
#define XDMA_REQ_TOSHSD3 (1u<<1) // Toshsd controller 3.
#define XDMA_REQ_AES_IN (1u<<2)
#define XDMA_REQ_AES_OUT (1u<<3)
// REG_CFG9_CARDCTL
#define CARDCTL_NTRCARD (0u) // Controller at 0x10164000.
#define CARDCTL_UNK1 (1u) // Unknown controller/function.
#define CARDCTL_CTRCARD1 (2u) // Controller at 0x10004000.
#define CARDCTL_CTRCARD2 (3u) // Controller at 0x10005000.
#define CARDCTL_SPIC_FIFO_MODE (1u<<4) // TODO: Confirm this. If set use regs at 0x1000D800 otherwise 0x1000D000.
#define CARDCTL_SPIC_SEL (1u<<8) // If set use regs at 0x1000D000/0x1000D800 otherwise regs at 0x10164000.
// REG_CFG9_CARD_POWER
#define CARD_POWER_EJECTED (1u) // No card inserted.
#define CARD_POWER_OFF (0u<<2) // Slot powered off.
#define CARD_POWER_ON_RESET (1u<<2) // Powered on and in reset.
#define CARD_POWER_ON (2u<<2) // Powered on.
#define CARD_POWER_OFF_REQ (3u<<2) // Power off request.
// REG_CFG9_SDMMCCTL
#define SDMMCCTL_SLOT_PWR_OFF (1u) // Controller 1/3 port 0 (MMC/SD card slot).
#define SDMMCCTL_eMMC_PWR_OFF (1u<<1) // Controller 1 port 1.
#define SDMMCCTL_WiFi_PWR_OFF (1u<<2) // Controller 2 port 0.
#define SDMMCCTL_UNK_PWR_OFF (1u<<3) // Controller 3 port 1 power off? Set at cold boot.
#define SDMMCCTL_UNK_BIT6 (1u<<6) // Wifi port related? Pull up? Set at cold boot.
#define SDMMCCTL_TOSHSD3_MAP9 (0u) // Controller 3 mapping ARM9 0x10007000.
#define SDMMCCTL_TOSHSD3_MAP11 (1u<<8) // Controller 3 mapping ARM11 0x10100000.
#define SDMMCCTL_SLOT_TOSHSD3_SEL (0u) // SD slot controller select TOSHSD3 0x10007000/0x10100000.
#define SDMMCCTL_SLOT_TOSHSD1_SEL (1u<<9) // SD slot controller select TOSHSD1 0x10006000.
// REG_CFG9_EXTMEMCNT9
#define EXTMEMCNT9_WRAM_EXT_E (1u) // Enables extra WRAM aka. ARM9 mem extension.
// REG_CFG9_SOCINFO
#define SOCINFO_CTR (1u) // Also set on New 3DS.
#define SOCINFO_LGR1 (1u<<1) // Never saw the daylight? Set on retail N3DS (LGR2).
#define SOCINFO_LGR2 (1u<<2) // Set on New 3DS.
// REG_CFG9_BOOTENV
#define BOOTENV_COLD_BOOT (0u)
#define BOOTENV_NATIVE_FIRM (1u)
#define BOOTENV_TWL_FIRM (3u)
#define BOOTENV_AGB_FIRM (7u)
// REG_CFG9_UNITINFO
// TODO: Collect all the possible values for this reg.
#define UNITINFO_RETAIL (0u)

View File

@ -1,34 +0,0 @@
#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);

View File

@ -1,99 +0,0 @@
#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 "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

View File

@ -1,148 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#include "util.h"
#define NDMA_REGS_BASE (IO_MEM_ARM9_ONLY + 0x2000)
#define REG_NDMA_GCNT *((vu32*)NDMA_REGS_BASE) // Global control.
// Note: The channel regs are offset by 4 (REG_NDMA_GLOBAL_CNT).
typedef struct
{
vu32 sad; // 0x00 Source address.
vu32 dad; // 0x04 Destination address.
vu32 tcnt; // 0x08 Total repeat length in words.
vu32 wcnt; // 0x0C Logical block size in words.
vu32 bcnt; // 0x10 Block transfer timing/interval.
vu32 fdata; // 0x14 Fill data.
vu32 cnt; // 0x18 Control.
} NdmaCh;
static_assert(offsetof(NdmaCh, cnt) == 0x18, "Error: Member cnt of NdmaCh is not at offset 0x18!");
ALWAYS_INLINE NdmaCh* getNdmaChRegs(u8 c)
{
return &((NdmaCh*)(NDMA_REGS_BASE + 4))[c];
}
// REG_NDMA_GCNT
#define NDMA_REG_READBACK (1u) // Show internal state on REG_NDMAx_SAD/DAD/TCNT/WCNT. 3DS mode only.
#define NDMA_ROUND_ROBIN(n) (1u<<31 | (intLog2(n) + 1)<<16) // DSP DMA/CPU cycles (power of 2). Maximum 16384.
#define NDMA_HIGHEST_PRIO (0u)
// REG_NDMA_BCNT
// TODO: When is the delay happening during transfers?
// TODO: Does NDMA run at 67 MHz in 3DS mode? We will assume so for now.
#define NDMA_CYCLES(n) (n) // Maximum 65535. 0 means no delay/interval.
#define NDMA_PRESCALER_1 (0u) // 67027964 Hz.
#define NDMA_PRESCALER_4 (1u<<16) // 16756991 Hz.
#define NDMA_PRESCALER_16 (2u<<16) // 4189247.75 Hz.
#define NDMA_PRESCALER_64 (3u<<16) // 1047311.9375 Hz.
#define NDMA_FASTEST (NDMA_PRESCALER_1 | NDMA_CYCLES(0)) // Convenience macro.
// REG_NDMA_CNT
#define NDMA_DAD_INC (0u) // Destination address increment.
#define NDMA_DAD_DEC (1u<<10) // Destination address decrement.
#define NDMA_DAD_FIX (2u<<10) // Destination address fixed.
#define NDMA_DAD_RELOAD (1u<<12) // Reload destination address on logical block end (REG_NDMAx_WCNT).
#define NDMA_SAD_INC (0u) // Source address increment.
#define NDMA_SAD_DEC (1u<<13) // Source address decrement.
#define NDMA_SAD_FIX (2u<<13) // Source address fixed.
#define NDMA_SAD_FILL (3u<<13) // Source is REG_NDMAx_FDATA.
#define NDMA_SAD_RELOAD (1u<<15) // Reload source address on logical block end (REG_NDMAx_WCNT).
#define NDMA_BURST_SHIFT (16u)
#define NDMA_BURST(n) (intLog2(n)<<NDMA_BURST_SHIFT) // Burst length is 2ⁿ words. Maximum 32768. Must be power of 2.
#define NDMA_TCNT_MODE (0u) // REG_NDMAx_TCNT mode.
#define NDMA_REPEAT_MODE (1u<<29) // Repeat transfer infinitely.
#define NDMA_IRQ_EN (1u<<30) // IRQ enable.
#define NDMA_EN (1u<<31) // Channel enable/active.
enum
{
NDMA_START_TIMER0 = 0u<<24,
NDMA_START_TIMER1 = 1u<<24,
NDMA_START_TIMER2 = 2u<<24,
NDMA_START_TIMER3 = 3u<<24,
NDMA_START_CTRCARD1 = 4u<<24, // Fires with SPICARD aswell but seems to be broken.
NDMA_START_CTRCARD2 = 5u<<24, // Fires with SPICARD aswell but seems to be broken.
NDMA_START_TOSHSD1 = 6u<<24,
NDMA_START_TOSHSD3 = 7u<<24,
NDMA_START_AES_IN = 8u<<24, // AES write fifo.
NDMA_START_AES_OUT = 9u<<24, // AES read fifo.
NDMA_START_SHA_IN = 10u<<24,
NDMA_START_SHA_OUT = 11u<<24, // For chaining.
NDMA_START_NTRCARD = 12u<<24,
// 13 and 14 unused?
NDMA_START_DEV2DEV = 15u<<24, // Needed for below startup modes.
// Direct device to device modes.
NDMA_START_CTRCARD1_AES = NDMA_START_DEV2DEV | 0u, // CTRCARD1 to AES.
NDMA_START_CTRCARD2_AES = NDMA_START_DEV2DEV | 1u, // CTRCARD2 to AES.
NDMA_START_AES_CTRCARD1 = NDMA_START_DEV2DEV | 2u, // AES to CTRCARD1.
NDMA_START_AES_CTRCARD2 = NDMA_START_DEV2DEV | 3u, // AES to CTRCARD2.
NDMA_START_CTRCARD1_SHA = NDMA_START_DEV2DEV | 4u, // CTRCARD1 to SHA.
NDMA_START_CTRCARD2_SHA = NDMA_START_DEV2DEV | 5u, // CTRCARD2 to SHA.
NDMA_START_SHA_CTRCARD1 = NDMA_START_DEV2DEV | 6u, // SHA to CTRCARD1.
NDMA_START_SHA_CTRCARD2 = NDMA_START_DEV2DEV | 7u, // SHA to CTRCARD2.
NDMA_START_TOSHSD1_AES = NDMA_START_DEV2DEV | 8u, // TOSHSD1 to AES.
NDMA_START_TOSHSD3_AES = NDMA_START_DEV2DEV | 9u, // TOSHSD3 to AES.
NDMA_START_AES_TOSHSD1 = NDMA_START_DEV2DEV | 10u, // AES to TOSHSD1.
NDMA_START_AES_TOSHSD3 = NDMA_START_DEV2DEV | 11u, // AES to TOSHSD3.
NDMA_START_TOSHSD1_SHA = NDMA_START_DEV2DEV | 12u, // TOSHSD1 to SHA.
NDMA_START_TOSHSD3_SHA = NDMA_START_DEV2DEV | 13u, // TOSHSD3 to SHA.
NDMA_START_SHA_TOSHSD1 = NDMA_START_DEV2DEV | 14u, // SHA to TOSHSD1.
NDMA_START_SHA_TOSHSD3 = NDMA_START_DEV2DEV | 15u, // SHA to TOSHSD3.
NDMA_START_AES_SHA = NDMA_START_DEV2DEV | 16u, // AES to SHA.
NDMA_START_SHA_AES = NDMA_START_DEV2DEV | 17u, // SHA to AES.
// 18-31 unused?
// This bit is technically not part of the startup modes.
NDMA_START_IMMEDIATE = 16u<<24
};
/**
* @brief Initializes all NDMA channels.
*/
void NDMA_init(void);
/**
* @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 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);

View File

@ -1,123 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define SPICARD_REGS_BASE (IO_MEM_ARM9_ONLY + 0xD800)
typedef struct
{
vu32 cnt; // 0x00
vu8 cs; // 0x04 32 bit but can be accessed as u8.
u8 _0x5[3];
vu32 blklen; // 0x08
vu32 fifo; // 0x0C
vu8 fifo_stat; // 0x10 32 bit but can be accessed as u8.
u8 _0x11[3];
vu32 autopoll; // 0x14
vu32 int_mask; // 0x18
vu32 int_stat; // 0x1C
} Spic;
static_assert(offsetof(Spic, int_stat) == 0x1C, "Error: Member int_stat of Spic is not at offset 0x1C!");
ALWAYS_INLINE Spic* getSpicRegs(void)
{
return (Spic*)SPICARD_REGS_BASE;
}
// REG_SPIC_CNT
typedef enum
{
SPIC_CLK_512KHz = 0u,
SPIC_CLK_1MHz = 1u,
SPIC_CLK_2MHz = 2u,
SPIC_CLK_4MHz = 3u,
SPIC_CLK_8MHz = 4u,
SPIC_CLK_16MHz = 5u,
// Not a real clock setting. Or with clock
// to set chip select high after transfer.
SPIC_CLK_CS_HIGH = 1u<<3
} SpicClk;
#define SPIC_BUS_1BIT (0u)
#define SPIC_BUS_4BIT (1u<<12)
#define SPIC_DIR_R (0u) // Direction read.
#define SPIC_DIR_W (1u<<13) // Direction write.
#define SPIC_EN (1u<<15) // Enable.
// REG_SPIC_CS
#define SPIC_CS_HIGH (0u)
// SPIC_FIFO_STAT
#define SPIC_FIFO_BUSY (1u)
// REG_SPIC_AUTOPOLL
// Shifts.
#define SPIC_AP_TMOUT_SHIFT (16u) // Auto poll register timeout shift.
#define SPIC_AP_OFF_SHIFT (24u) // Auto poll register bit offset shift.
#define SPIC_AP_BIT_SHIFT (30u) // Auto poll register compare bit shift.
#define SPIC_AP_START (1u<<31) // Auto poll start.
// REG_SPIC_INT_MASK Bit set = disabled.
// REG_SPIC_INT_STAT Status and acknowledge.
#define SPIC_INT_TRAN_END (1u) // Transfer end. Also fires on each auto poll try.
#define SPIC_INT_AP_MATCH (1u<<1) // Auto poll bit match.
#define SPIC_INT_AP_TMOUT (1u<<2) // Auto poll timeout.
// cmd Is the command byte to send.
// tmout Is the timeout. Must be 0-15. Tries = 31<<(SpicClk + timeout).
// off Is the bit offset in the response byte. Must be 0-7.
// cmpBit Is the bit to compare (0 or 1).
#define MAKE_AP_PARAMS(cmd, tmout, off, cmpBit) ((u32)(cmpBit)<<30 | (u32)(off)<<24 | (u32)(tmout)<<16 | (cmd))
/**
* @brief Initializes the SPI bus. Call this only once.
*/
void SPICARD_init(void);
/**
* @brief Automatically polls a bit of the command response.
*
* @param[in] clk The clock frequency to use.
* @param[in] apParams The parameters. Use the MAKE_AP_PARAMS macro.
*
* @return Returns false on timeout and true on bit match.
*/
bool SPICARD_autoPollBit(SpicClk clk, u32 apParams);
/**
* @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.
*/
void SPICARD_writeRead(SpicClk clk, const u32 *in, u32 *out, u32 inSize, u32 outSize);

View File

@ -1,98 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#define TIMER_REGS_BASE (IO_MEM_ARM9_ONLY + 0x3000)
typedef struct
{
vu16 val; // 0x0
vu16 cnt; // 0x2
} Timer;
static_assert(offsetof(Timer, cnt) == 2, "Error: Member cnt of Timer is not at offset 2!");
ALWAYS_INLINE Timer* getTimerRegs(u8 timer)
{
return &((Timer*)TIMER_REGS_BASE)[timer];
}
#define TIMER_BASE_FREQ (67027964)
// REG_TIMER_CNT
#define TIMER_PRESC_1 (0u)
#define TIMER_PRESC_64 (1u)
#define TIMER_PRESC_256 (2u)
#define TIMER_PRESC_1024 (3u)
#define TIMER_COUNT_UP (1u<<2) // For cascading at least 2 timers.
#define TIMER_IRQ_EN (1u<<6)
#define TIMER_EN (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))
/**
* @brief Resets/initializes the timer hardware. Should not be called manually.
*/
void TIMER_init(void);
/**
* @brief Starts a timer.
*
* @param[in] tmr The timer to start (0-3). Timer 3 is reserved.
* @param[in] ticks The initial number of ticks. This is also the reload
* value on overflow.
* @param[in] params The parameters. See REG_TIMER_CNT defines above.
*/
void TIMER_start(u8 tmr, u16 ticks, u8 params);
/**
* @brief Returns the current number of ticks of the timer.
*
* @param[in] tmr The timer get the ticks from (0-3). Timer 3 is reserved.
*
* @return The number of ticks.
*/
u16 TIMER_getTicks(u8 tmr);
/**
* @brief Stops a timer and returns the current number of ticks.
*
* @param[in] tmr The timer to stop (0-3). Timer 3 is reserved.
*
* @return The number of ticks.
*/
u16 TIMER_stop(u8 tmr);
/**
* @brief Halts the CPU for the given number of milliseconds.
*
* @param[in] ms The number of milliseconds to sleep.
*/
void TIMER_sleepMs(u32 ms);

View File

@ -1,265 +0,0 @@
#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

View File

@ -1,46 +0,0 @@
#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/>.
*/
#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

View File

@ -1,32 +0,0 @@
#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"
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);

View File

@ -1,228 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
//#define USE_NEW_CDMA 1
#ifdef ARM11
#ifdef USE_NEW_CDMA
#define DMA330_REGS_BASE (IO_MEM_ARM11_ONLY + 0x6000)
#else
#define DMA330_REGS_BASE (IO_MEM_ARM11_ONLY + 0x0000)
#endif // ifdef USE_NEW_CDMA
#elif ARM9
#define DMA330_REGS_BASE (IO_MEM_ARM9_ONLY + 0xC000)
#endif // ifdef ARM11
typedef struct
{
const vu32 dsr; // 0x000 DMA Manager Status Register.
const vu32 dpc; // 0x004 DMA Program Counter Register (manager).
u8 _0x8[0x18];
vu32 inten; // 0x020 Interrupt Enable Register.
const vu32 int_event_ris; // 0x024 Event-Interrupt Raw Status Register.
const vu32 intmis; // 0x028 Interrupt Status Register.
vu32 intclr; // 0x02C Interrupt Clear Register (write-only).
const vu32 fsrd; // 0x030 Fault Status DMA Manager Register.
const vu32 fsrc; // 0x034 Fault Status DMA Channel Register.
const vu32 ftrd; // 0x038 Fault Type DMA Manager Register.
u8 _0x3c[4];
const vu32 ftr[8]; // 0x040 Fault Type DMA Channel Registers.
u8 _0x60[0xa0];
struct // 0x100
{
const vu32 csr; // 0x0 Channel Status Register.
const vu32 cpc; // 0x4 Channel Program Counter Register.
} chStat[8];
u8 _0x140[0x2c0];
struct // 0x400
{
const vu32 sar; // 0x00 Source Address Register.
const vu32 dar; // 0x04 Destination Address Register.
const vu32 ccr; // 0x08 Channel Control Register.
const vu32 lc0; // 0x0C Loop Counter 0 Register.
const vu32 lc1; // 0x10 Loop Counter 1 Register.
u8 chCtrl_0x14[0xc];
} chCtrl[8];
u8 _0x500[0x800];
const vu32 dbgstatus; // 0xD00 Debug Status Register.
vu32 dbgcmd; // 0xD04 Debug Command Register (write-only).
vu32 dbginst0; // 0xD08 Debug Instruction-0 Register (write-only).
vu32 dbginst1; // 0xD0C Debug Instruction-1 Register (write-only).
u8 _0xd10[0xf0];
const vu32 cr0; // 0xE00 Configuration Register 0.
const vu32 cr1; // 0xE04 Configuration Register 1.
const vu32 cr2; // 0xE08 Configuration Register 2.
const vu32 cr3; // 0xE0C Configuration Register 3.
const vu32 cr4; // 0xE10 Configuration Register 4.
const vu32 crd; // 0xE14 DMA Configuration Register.
u8 _0xe18[0x68];
vu32 wd; // 0xE80 Watchdog Register (r1p0 only).
u8 _0xe84[0x15c];
const vu32 periph_id_0; // Peripheral Identification Register 0.
const vu32 periph_id_1; // Peripheral Identification Register 1.
const vu32 periph_id_2; // Peripheral Identification Register 2.
const vu32 periph_id_3; // Peripheral Identification Register 3.
const vu32 pcell_id_0; // Component Identification Register 0.
const vu32 pcell_id_1; // Component Identification Register 1.
const vu32 pcell_id_2; // Component Identification Register 2.
const vu32 pcell_id_3; // Component Identification Register 3.
} Dma330;
static_assert(offsetof(Dma330, pcell_id_3) == 0xFFC, "Error: Member pcell_id_3 of Dma330 is not at offset 0xFFC!");
ALWAYS_INLINE Dma330* getDma330Regs(void)
{
return (Dma330*)DMA330_REGS_BASE;
}
// 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) // 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

View File

@ -1,126 +0,0 @@
#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 "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

View File

@ -1,132 +0,0 @@
#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"
#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

View File

@ -1,165 +0,0 @@
#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/>.
*/
// Based on JEDEC eMMC Card Product Standard V4.41.
#include "drivers/toshsd.h"
// TODO: Make a wrapper so this is less controller dependedent?
// TODO: Add required bits/defines for cmds with data payload.
// Basic commands and read-stream command (class 0 and class 1).
#define MMC_GO_IDLE_STATE (CMD_RESP_NONE | 0u) // Arg [31:0] 0x00000000 GO_IDLE_STATE, 0xF0F0F0F0 GO_PRE_IDLE_STATE, 0xFFFFFFFA BOOT_INITIATION.
#define MMC_SEND_OP_COND (CMD_RESP_R3 | 1u) // Arg [31:0] OCR with-out busy.
#define MMC_ALL_SEND_CID (CMD_RESP_R2 | 2u) // Arg [31:0] stuff bits.
#define MMC_SET_RELATIVE_ADDR (CMD_RESP_R1 | 3u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_SET_DSR (CMD_RESP_NONE | 4u) // Arg [31:16] DSR [15:0] stuff bits.
#define MMC_SLEEP_AWAKE (CMD_RESP_R1b | 5u) // Arg [31:16] RCA [15] Sleep/Awake [14:0] stuff bits.
#define MMC_SWITCH (CMD_RESP_R1b | 6u) // Arg [31:26] Set to 0 [25:24] Access [23:16] Index [15:8] Value [7:3] Set to 0 [2:0] Cmd Set.
#define MMC_SELECT_CARD (CMD_RESP_R1 | 7u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_DESELECT_CARD (CMD_RESP_NONE | 7u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_SELECT_CARD_R1b (CMD_RESP_R1b | 7u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_SEND_EXT_CSD (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 8u) // Arg [31:0] stuff bits.
#define MMC_SEND_CSD (CMD_RESP_R2 | 9u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_SEND_CID (CMD_RESP_R2 | 10u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_READ_DAT_UNTIL_STOP (CMD_MBT | CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 11u) // Arg [31:0] data address.
#define MMC_STOP_TRANSMISSION_R (CMD_RESP_R1 | 12u) // Arg [31:16] RCA [15:1] stuff bits [0] HPI.
#define MMC_STOP_TRANSMISSION_W (CMD_RESP_R1b | 12u) // Arg [31:16] RCA [15:1] stuff bits [0] HPI.
#define MMC_SEND_STATUS (CMD_RESP_R1 | 13u) // Arg [31:16] RCA [15:1] stuff bits [0] HPI.
#define MMC_BUSTEST_R (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 14u) // Arg [31:0] stuff bits.
#define MMC_GO_INACTIVE_STATE (CMD_RESP_NONE | 15u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_BUSTEST_W (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 19u) // Arg [31:0] stuff bits.
// Block-oriented read commands (class 2).
#define MMC_SET_BLOCKLEN (CMD_RESP_R1 | 16u) // Arg [31:0] block length.
#define MMC_READ_SINGLE_BLOCK (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 17u) // Arg [31:0] data address.
#define MMC_READ_MULTIPLE_BLOCK (CMD_MBT | CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 18u) // Arg [31:0] data address.
// Stream write commands (class 3).
#define MMC_WRITE_DAT_UNTIL_STOP (CMD_MBT | CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 20u) // Arg [31:0] data address.
// Block-oriented write commands (class 4).
#define MMC_SET_BLOCK_COUNT (CMD_RESP_R1 | 23u) // Arg [31] Reliable Write Request [30:16] set to 0 [15:0] number of blocks.
#define MMC_WRITE_BLOCK (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 24u) // Arg [31:0] data address.
#define MMC_WRITE_MULTIPLE_BLOCK (CMD_MBT | CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 25u) // Arg [31:0] data address.
#define MMC_PROGRAM_CID (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 26u) // Arg [31:0] stuff bits.
#define MMC_PROGRAM_CSD (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 27u) // Arg [31:0] stuff bits.
// Block-oriented write protection commands (class 6).
#define MMC_SET_WRITE_PROT (CMD_RESP_R1b | 28u) // Arg [31:0] data address.
#define MMC_CLR_WRITE_PROT (CMD_RESP_R1b | 29u) // Arg [31:0] data address.
#define MMC_SEND_WRITE_PROT (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 30u) // Arg [31:0] write protect data address.
#define MMC_SEND_WRITE_PROT_TYPE (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 31u) // Arg [31:0] write protect data address.
// Erase commands (class 5).
#define MMC_ERASE_GROUP_START (CMD_RESP_R1 | 35u) // Arg [31:0] data address.
#define MMC_ERASE_GROUP_END (CMD_RESP_R1 | 36u) // Arg [31:0] data address.
#define MMC_ERASE (CMD_RESP_R1b | 38u) // Arg [31] Secure request [30:16] set to 0 [15] Force Garbage Collect request [14:1] set to 0 [0] Identify Write block for Erase.
// I/O mode commands (class 9).
#define MMC_FAST_IO (CMD_RESP_R4 | 39u) // Arg [31:16] RCA [15:15] register write flag [14:8] register address [7:0] register data.
#define MMC_GO_IRQ_STATE (CMD_RESP_R5 | 40u) // Arg [31:0] stuff bits.
// Lock card commands (class 7).
#define MMC_LOCK_UNLOCK (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 42u) // Arg [31:0] stuff bits.
// Application-specific commands (class 8).
#define MMC_APP_CMD (CMD_RESP_R1 | 55u) // Arg [31:16] RCA [15:0] stuff bits.
#define MMC_GEN_CMD_R (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 56u) // Arg [31:1] stuff bits [0] RD/WR = 1.
#define MMC_GEN_CMD_W (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 56u) // Arg [31:1] stuff bits [0] RD/WR = 0.
// MMC R1 card status.
// (S) = status bit.
// (E) = error bit.
// TODO: When do bits get set?
#define MMC_R1_APP_CMD (1u<<5) // (S) The card will expect ACMD, or indication that the command has been interpreted as ACMD.
#define MMC_R1_URGENT_BKOPS (1u<<6) // (S) If set, device needs to perform backgroundoperations urgently. Host can check EXT_CSD field BKOPS_STATUS for the detailed level.
#define MMC_R1_SWITCH_ERROR (1u<<7) // (E) If set, the card did not switch to the expected mode as requested by the SWITCH command.
#define MMC_R1_READY_FOR_DATA (1u<<8) // (S) Corresponds to buffer empty signalling on the bus.
#define MMC_R1_STATE_IDLE (0u<<9) // (S)
#define MMC_R1_STATE_READY (1u<<9) // (S)
#define MMC_R1_STATE_IDENT (2u<<9) // (S)
#define MMC_R1_STATE_STBY (3u<<9) // (S)
#define MMC_R1_STATE_TRAN (4u<<9) // (S)
#define MMC_R1_STATE_DATA (5u<<9) // (S)
#define MMC_R1_STATE_RCV (6u<<9) // (S)
#define MMC_R1_STATE_PRG (7u<<9) // (S)
#define MMC_R1_STATE_DIS (8u<<9) // (S)
#define MMC_R1_STATE_BTST (9u<<9) // (S)
#define MMC_R1_STATE_SLP (10u<<9) // (S)
#define MMC_R1_ERASE_RESET (1u<<13) // (E) An erase sequence was cleared before executing because an out of erase sequence command was received (commands other than CMD35, CMD36, CMD38 or CMD13.
#define MMC_R1_WP_ERASE_SKIP (1u<<15) // (E) Only partial address space was erased due to existing write protected blocks.
#define MMC_R1_CXD_OVERWRITE (1u<<16) // (E) Can be either one of the following errors: - The CID register has been already written and can not be overwritten - The read only section of the CSD does not match the card content. - An attempt to reverse the copy (set as original) or permanent WP (unprotected) bits was made.
#define MMC_R1_OVERRUN (1u<<17) // (E) The card could not sustain data programming in stream write mode.
#define MMC_R1_UNDERRUN (1u<<18) // (E) The card could not sustain data transfer in stream read mode.
#define MMC_R1_ERROR (1u<<19) // (E) (Undefined by the standard) A generic card error related to the (and detected during) execution of the last host command (e.g. read or write failures).
#define MMC_R1_CC_ERROR (1u<<20) // (E) (Undefined by the standard) A card error occurred, which is not related to the host command.
#define MMC_R1_CARD_ECC_FAILED (1u<<21) // (E) Card internal ECC was applied but failed to correct the data.
#define MMC_R1_ILLEGAL_COMMAND (1u<<22) // (E) Command not legal for the card state.
#define MMC_R1_COM_CRC_ERROR (1u<<23) // (E) The CRC check of the previous command failed.
#define MMC_R1_LOCK_UNLOCK_FAILED (1u<<24) // (E) Set when a sequence or password error has been detected in lock/unlock card command.
#define MMC_R1_CARD_IS_LOCKED (1u<<25) // (S) When set, signals that the card is locked by the host.
#define MMC_R1_WP_VIOLATION (1u<<26) // (E) Attempt to program a write protected block.
#define MMC_R1_ERASE_PARAM (1u<<27) // (E) An invalid selection of erase groups for erase occurred.
#define MMC_R1_ERASE_SEQ_ERROR (1u<<28) // (E) An error in the sequence of erase commands occurred.
#define MMC_R1_BLOCK_LEN_ERROR (1u<<29) // (E) Either the argument of a SET_BLOCKLEN command exceeds the maximum value allowed for the card, or the previously defined block length is illegal for the current command (e.g. the host issues a write command, the current block length is smaller than the cards maximum and write partial blocks is not allowed).
#define MMC_R1_ADDRESS_MISALIGN (1u<<30) // (E) The command s address argument (in accordance with the currently set block length) positions the first data block misaligned to the card physical blocks. A multiple block read/write operation (although started with a valid address/blocklength combination) is attempting to read or write a data block which does not align with the physical blocks of the card.
#define MMC_R1_ADDRESS_OUT_OF_RANGE (1u<<31) // (E) The commands address argument was out of the allowed range for this card. A multiple block or stream read/write operation is (although started in a valid address) attempting to read or write beyond the card capacity.
#define MMC_R1_ERR_ALL (MMC_R1_ADDRESS_OUT_OF_RANGE | MMC_R1_ADDRESS_MISALIGN | \
MMC_R1_BLOCK_LEN_ERROR | MMC_R1_ERASE_SEQ_ERROR | \
MMC_R1_ERASE_PARAM | MMC_R1_WP_VIOLATION | MMC_R1_LOCK_UNLOCK_FAILED | \
MMC_R1_COM_CRC_ERROR | MMC_R1_ILLEGAL_COMMAND | MMC_R1_CARD_ECC_FAILED | \
MMC_R1_CC_ERROR | MMC_R1_ERROR | MMC_R1_UNDERRUN | MMC_R1_OVERRUN | \
MMC_R1_CXD_OVERWRITE | MMC_R1_WP_ERASE_SKIP | MMC_R1_ERASE_RESET | \
MMC_R1_SWITCH_ERROR)
// Operation Conditions Register (OCR).
// Same bits for CMD1 argument.
#define MMC_OCR_1_7_1_95V (1u<<7) // 1.701.95V.
/*#define MMC_OCR_2_0_2_1V (1u<<8) // 2.0-2.1V.
#define MMC_OCR_2_1_2_2V (1u<<9) // 2.1-2.2V.
#define MMC_OCR_2_2_2_3V (1u<<10) // 2.2-2.3V.
#define MMC_OCR_2_3_2_4V (1u<<11) // 2.3-2.4V.
#define MMC_OCR_2_4_2_5V (1u<<12) // 2.4-2.5V.
#define MMC_OCR_2_5_2_6V (1u<<13) // 2.5-2.6V.
#define MMC_OCR_2_6_2_7V (1u<<14)*/ // 2.6-2.7V.
#define MMC_OCR_2_7_2_8V (1u<<15) // 2.7-2.8V.
#define MMC_OCR_2_8_2_9V (1u<<16) // 2.8-2.9V.
#define MMC_OCR_2_9_3_0V (1u<<17) // 2.9-3.0V.
#define MMC_OCR_3_0_3_1V (1u<<18) // 3.0-3.1V.
#define MMC_OCR_3_1_3_2V (1u<<19) // 3.1-3.2V.
#define MMC_OCR_3_2_3_3V (1u<<20) // 3.2-3.3V.
#define MMC_OCR_3_3_3_4V (1u<<21) // 3.3-3.4V.
#define MMC_OCR_3_4_3_5V (1u<<22) // 3.4-3.5V.
#define MMC_OCR_3_5_3_6V (1u<<23) // 3.5-3.6V.
#define MMC_OCR_BYTE_MODE (0u<<29) // Access mode = byte mode.
#define MMC_OCR_SECT_MODE (2u<<29) // Access mode = sector mode.
#define MMC_OCR_NOT_BUSY (1u<<31) // Card power up status bit (busy).
// 7.6.1 Command sets and extended settings.
#define MMC_SWITCH_ACC_CMD_SET (0u)
#define MMC_SWITCH_ACC_SET_BITS (1u)
#define MMC_SWITCH_ACC_CLR_BITS (2u)
#define MMC_SWITCH_ACC_WR_BYTE (3u)
#define MMC_SWITCH_ARG(acc, idx, val, cmdSet) (((acc)&3u)<<24 | ((idx)&0xFFu)<<16 | ((val)&0xFFu)<<8 | ((cmdSet)&7u))

View File

@ -1,187 +0,0 @@
#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/>.
*/
// Based on SD specification version 8.00.
#include "drivers/toshsd.h"
// TODO: Make a wrapper so this is less controller dependedent?
// TODO: Add required bits/defines for cmds with data payload.
// Basic Commands (class 0).
#define SD_GO_IDLE_STATE (CMD_RESP_NONE | 0u) // Arg [31:0] stuff bits.
#define SD_ALL_SEND_CID (CMD_RESP_R2 | 2u) // Arg [31:0] stuff bits.
#define SD_SEND_RELATIVE_ADDR (CMD_RESP_R6 | 3u) // Arg [31:0] stuff bits.
#define SD_SET_DSR (CMD_RESP_NONE | 4u) // Arg [31:16] DSR [15:0] stuff bits.
#define SD_SELECT_CARD (CMD_RESP_R1b | 7u) // Arg [31:16] RCA [15:0] stuff bits.
#define SD_DESELECT_CARD (CMD_RESP_NONE | 7u) // Arg [31:16] RCA [15:0] stuff bits.
#define SD_SEND_IF_COND (CMD_RESP_R7 | 8u) // Arg [31:12] reserved bits [11:8] supply voltage (VHS) [7:0] check pattern.
#define SD_SEND_CSD (CMD_RESP_R2 | 9u) // Arg [31:16] RCA [15:0] stuff bits.
#define SD_SEND_CID (CMD_RESP_R2 | 10u) // Arg [31:16] RCA [15:0] stuff bits.
#define SD_VOLTAGE_SWITCH (CMD_RESP_R1 | 11u) // Arg [31:0] reserved bits (all 0).
#define SD_STOP_TRANSMISSION (CMD_RESP_R1b | 12u) // Arg [31:0] stuff bits.
#define SD_SEND_STATUS (CMD_RESP_R1 | 13u) // Arg [31:16] RCA [15] Send Task Status Register [14:0] stuff bits.
#define SD_SEND_TASK_STATUS (CMD_RESP_R1 | 13u) // Arg [31:16] RCA [15] Send Task Status Register [14:0] stuff bits.
#define SD_GO_INACTIVE_STATE (CMD_RESP_NONE | 15u) // Arg [31:16] RCA [15:0] reserved bits.
// Block-Oriented Read Commands (class 2).
#define SD_SET_BLOCKLEN (CMD_RESP_R1 | 16u) // Arg [31:0] block length.
#define SD_READ_SINGLE_BLOCK (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 17u) // Arg [31:0] data address.
#define SD_READ_MULTIPLE_BLOCK (CMD_MBT | CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 18u) // Arg [31:0] data address.
#define SD_SEND_TUNING_BLOCK (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 19u) // Arg [31:0] reserved bits (all 0).
#define SD_SPEED_CLASS_CONTROL (CMD_RESP_R1b | 20u) // Arg [31:28] Speed Class Control [27:0] See command description.
#define SD_ADDRESS_EXTENSION (CMD_RESP_R1 | 22u) // Arg [31:6] reserved bits (all 0) [5:0] extended address.
#define SD_SET_BLOCK_COUNT (CMD_RESP_R1 | 23u) // Arg [31:0] Block Count.
// Block-Oriented Write Commands (class 4).
// SET_BLOCKLEN
// SPEED_CLASS_CONTROL
// ADDRESS_EXTENSION
// SET_BLOCK_COUNT
#define SD_WRITE_BLOCK (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 24u) // Arg [31:0] data address.
#define SD_WRITE_MULTIPLE_BLOCK (CMD_MBT | CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 25u) // Arg [31:0] data address.
#define SD_PROGRAM_CSD (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 27u) // Arg [31:0] stuff bits.
// Block Oriented Write Protection Commands (class 6).
#define SD_SET_WRITE_PROT (CMD_RESP_R1b | 28u) // Arg [31:0] data address.
#define SD_CLR_WRITE_PROT (CMD_RESP_R1b | 29u) // Arg [31:0] data address.
#define SD_SEND_WRITE_PROT (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 30u) // Arg [31:0] write protect data address.
// Erase Commands (class 5).
#define SD_ERASE_WR_BLK_START (CMD_RESP_R1 | 32u) // Arg [31:0] data address.
#define SD_ERASE_WR_BLK_END (CMD_RESP_R1 | 33u) // Arg [31:0] data address.
#define SD_ERASE (CMD_RESP_R1b | 38u) // Arg [31:0] Erase Function.
// Lock Card (class 7).
// SET_BLOCKLEN
// Command 40 "Defined by DPS Spec.".
#define SD_LOCK_UNLOCK (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 42u) // Arg [31:0] Reserved bits (Set all 0).
// Application-Specific Commands (class 8).
#define SD_APP_CMD (CMD_RESP_R1 | 55u) // Arg [31:16] RCA [15:0] stuff bits.
#define SD_GEN_CMD_R (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 56u) // Arg [31:1] stuff bits. [0]: RD/WR = 1.
#define SD_GEN_CMD_W (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 56u) // Arg [31:1] stuff bits. [0]: RD/WR = 0.
// Application Specific Commands used/reserved by SD Memory Card.
#define SD_APP_SET_BUS_WIDTH (CMD_RESP_R1 | CMD_ACMD | 6u) // Arg [31:2] stuff bits [1:0] bus width.
#define SD_APP_SD_STATUS (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | CMD_ACMD | 13u) // Arg [31:0] stuff bits.
#define SD_APP_SEND_NUM_WR_BLOCKS (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | CMD_ACMD | 22u) // Arg [31:0] stuff bits.
#define SD_APP_SET_WR_BLK_ERASE_COUNT (CMD_RESP_R1 | CMD_ACMD | 23u) // Arg [31:23] stuff bits [22:0]Number of blocks.
#define SD_APP_SD_SEND_OP_COND (CMD_RESP_R3 | CMD_ACMD | 41u) // Arg [31] reserved bit [30] HCS (OCR[30]) [29] reserved for eSD [28] XPC [27:25] reserved bits [24] S18R [23:0] VDD Voltage Window (OCR[23:0]).
#define SD_APP_SET_CLR_CARD_DETECT (CMD_RESP_R1 | CMD_ACMD | 42u) // Arg [31:1] stuff bits [0] set_cd.
#define SD_APP_SEND_SCR (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | CMD_ACMD | 51u) // Arg [31:0] stuff bits.
// Switch Function Commands (class 10).
#define SD_SWITCH_FUNC (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 6u) // Arg [31] Mode 0: Check function 1: Switch function [30:24] reserved (All '0') [23:20] reserved for function group 6 (0h or Fh) [19:16] reserved for function group 5 (0h or Fh) [15:12] function group 4 for PowerLimit [11:8] function group 3 for Drive Strength [7:4] function group 2 for Command System [3:0] function group 1 for Access Mode.
// Function Extension Commands (class 11).
#define SD_READ_EXTR_SINGLE (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 48u) // Arg [31] MIO0: Memory, 1: I/O [30:27] FNO[26] Reserved (=0) [25:9] ADDR [8:0] LEN.
#define SD_WRITE_EXTR_SINGLE (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 49u) // Arg [31] MIO0: Memory, 1: I/O [30:27] FNO [26] MW [25:9] ADDR [8:0] LEN/MASK.
#define SD_READ_EXTR_MULTI (CMD_MBT | CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 58u) // Arg [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
#define SD_WRITE_EXTR_MULTI (CMD_MBT | CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 59u) // Arg [31] MIO0: Memory, 1: I/O [30:27] FNO [26] BUS0: 512B, 1: 32KB [25:9] ADDR [8:0] BUC.
// Command Queue Function Commands (class 1).
#define SD_Q_MANAGEMENT (CMD_RESP_R1b | 43u) // Arg [31:21] Reserved [20:16]: Task ID [3:0]: Operation Code (Abort tasks etc.).
#define SD_Q_TASK_INFO_A (CMD_RESP_R1 | 44u) // Arg [31] Reserved [30] Direction [29:24] Extended Address [23] Priority [22:21] Reserved [20:16] Task ID [15:0] Number of Blocks.
#define SD_Q_TASK_INFO_B (CMD_RESP_R1 | 45u) // Arg [31:0] Start block address.
#define SD_Q_RD_TASK (CMD_DIR_R | CMD_DT | CMD_RESP_R1 | 46u) // Arg [31:21] Reserved [20:16] Task ID [15:0] Reserved.
#define SD_Q_WR_TASK (CMD_DIR_W | CMD_DT | CMD_RESP_R1 | 47u) // Arg [31:21] Reserved [20:16] Task ID [15:0] Reserved.
// SD R1 card status.
// (S) = status bit.
// (E) = error bit.
// TODO: When do bits get set?
#define SD_R1_AKE_SEQ_ERROR (1u<<3) // (E) Error in the sequence of the authentication process.
#define SD_R1_APP_CMD (1u<<5) // (S) The card will expect ACMD, or an indication that the command has been interpreted as ACMD.
#define SD_R1_FX_EVENT (1u<<6) // (S) ExtensionFunctions may set this bit to get host to deal with events.
#define SD_R1_READY_FOR_DATA (1u<<8) // (S) Corresponds to buffer empty signaling on the bus.
#define SD_R1_STATE_IDLE (0u<<9) // (S)
#define SD_R1_STATE_READY (1u<<9) // (S)
#define SD_R1_STATE_IDENT (2u<<9) // (S)
#define SD_R1_STATE_STBY (3u<<9) // (S)
#define SD_R1_STATE_TRAN (4u<<9) // (S)
#define SD_R1_STATE_DATA (5u<<9) // (S)
#define SD_R1_STATE_RCV (6u<<9) // (S)
#define SD_R1_STATE_PRG (7u<<9) // (S)
#define SD_R1_STATE_DIS (8u<<9) // (S)
#define SD_R1_ERASE_RESET (1u<<13) // (S) An erase sequence was cleared before executing because an out of erase sequence command was received.
#define SD_R1_CARD_ECC_DISABLED (1u<<14) // (S) The command has been executed without using the internal ECC.
#define SD_R1_WP_ERASE_SKIP (1u<<15) // (E) Set when only partial address space was erased due to existing write protected blocks or the temporary or permanent write protected cardwas erased.
#define SD_R1_CSD_OVERWRITE (1u<<16) // (E) Can be either one of the following errors: -The read only section of the CSD does not match the card content. -An attempt to reverse the copy (set as original) or permanent WP (unprotected) bits was made.
// 17 reserved for DEFERRED_RESPONSE (Refer to eSD Addendum)
#define SD_R1_ERROR (1u<<19) // (E) A general or an unknown error occurred during the operation.
#define SD_R1_CC_ERROR (1u<<20) // (E) Internal card controller error:
#define SD_R1_CARD_ECC_FAILED (1u<<21) // (E) Card internal ECC was applied but failed to correct the data.
#define SD_R1_ILLEGAL_COMMAND (1u<<22) // (E) Command not legal for the card state.
#define SD_R1_COM_CRC_ERROR (1u<<23) // (E) The CRC check of the previous command failed.
#define SD_R1_LOCK_UNLOCK_FAILED (1u<<24) // (E) Set when a sequence or password error has been detected in lock/unlock card command.
#define SD_R1_CARD_IS_LOCKED (1u<<25) // (S) When set, signals that the card is locked by the host.
#define SD_R1_WP_VIOLATION (1u<<26) // (E) Set when the host attempts to write to a protected block or to thetemporary or permanent write protected card.
#define SD_R1_ERASE_PARAM (1u<<27) // (E) An invalid selection of write-blocks for erase occurred.
#define SD_R1_ERASE_SEQ_ERROR (1u<<28) // (E) An error in the sequence of erase commands occurred.
#define SD_R1_BLOCK_LEN_ERROR (1u<<29) // (E) The transferred block length is not allowed for this card, or the number of transferred bytes does not match the block length.
#define SD_R1_ADDRESS_ERROR (1u<<30) // (E) A misaligned address which did not match the block length was used in the command.
#define SD_R1_OUT_OF_RANGE (1u<<31) // (E) The command's argument was out of the allowed range for this card.
#define SD_R1_ERR_ALL (SD_R1_OUT_OF_RANGE | SD_R1_ADDRESS_ERROR | SD_R1_BLOCK_LEN_ERROR | \
SD_R1_ERASE_SEQ_ERROR | SD_R1_ERASE_PARAM | SD_R1_WP_VIOLATION | \
SD_R1_LOCK_UNLOCK_FAILED | SD_R1_COM_CRC_ERROR | SD_R1_ILLEGAL_COMMAND | \
SD_R1_CARD_ECC_FAILED | SD_R1_CC_ERROR | SD_R1_ERROR | \
SD_R1_CSD_OVERWRITE | SD_R1_WP_ERASE_SKIP | SD_R1_AKE_SEQ_ERROR)
// Send Interface Condition Command argument bits.
#define SD_CMD8_CHK_PATT (0xAAu) // Check pattern.
#define SD_CMD8_VHS_2_7_3_6V (1u<<8) // Voltage supplied (VHS) 2.7-3.6V.
#define SD_CMD8_PCIe (1u<<12) // PCIe Avail-ability.
#define SD_CMD8_PCIe_1_2V (1u<<13) // PCIe 1.2V Support.
// Operation Conditions Register (OCR).
// Voltage bits also for ACMD41 argument.
#define SD_OCR_2_7_2_8V (1u<<15) // 2.7-2.8V.
#define SD_OCR_2_8_2_9V (1u<<16) // 2.8-2.9V.
#define SD_OCR_2_9_3_0V (1u<<17) // 2.9-3.0V.
#define SD_OCR_3_0_3_1V (1u<<18) // 3.0-3.1V.
#define SD_OCR_3_1_3_2V (1u<<19) // 3.1-3.2V.
#define SD_OCR_3_2_3_3V (1u<<20) // 3.2-3.3V.
#define SD_OCR_3_3_3_4V (1u<<21) // 3.3-3.4V.
#define SD_OCR_3_4_3_5V (1u<<22) // 3.4-3.5V.
#define SD_OCR_3_5_3_6V (1u<<23) // 3.5-3.6V.
#define SD_OCR_S18A (1u<<24) // S18A: Switching to 1.8V Accepted. 0b: Continues current voltage signaling, 1b: Ready for switching signal voltage.
#define SD_OCR_CO2T (1u<<27) // Over 2TB Card. CCS must also be 1 if this is 1.
#define SD_OCR_UHS_II (1u<<29) // UHS-II Card Status. 0b: Non UHS-II Card, 1b: UHS-II Card.
#define SD_OCR_CCS (1u<<30) // Card Capacity Status. 0b: SDSC, 1b: SDHC or SDXC.
#define SD_OCR_NOT_BUSY (1u<<31) // Busy Status. 0b: On Initialization, 1b: Initialization Complete.
// Argument bits for ACMD41.
#define SD_ACMD41_S18R (1u<<24) // S18R: Switching to 1.8V Request. 0b: Use current signal voltage, 1b: Switch to 1.8V signal voltage.
#define SD_ACMD41_HO2T (1u<<27) // Over 2TB Supported Host. HCS must also be 1 if this is 1.
#define SD_ACMD41_XPC (1u<<28) // SDXC Power Control. 0b: Power Saving, 1b: Maximum Performance.
#define SD_ACMD41_HCS (1u<<30) // Host Capacity Support. 0b: SDSC Only Host, 1b: SDHC or SDXC Supported.
// 4.3.10 Switch Function Command
// mode: 0 = check function, 1 = set function
// pwr: Function group 4 Power Limit.
// driver: Function group 3 Driver Strength.
// cmd: Function group 2 Command system.
// acc: Function group 1 Access mode.
#define SD_SWITCH_FUNC_ARG(mode, pwr, driver, cmd, acc) ((u32)(mode)<<31 | 0xFFu<<16 | ((pwr)&0xFu)<<12 | ((driver)&0xFu)<<8 | ((cmd)&0xFu)<<4 | ((acc)&0xFu))

View File

@ -1,139 +0,0 @@
#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"
enum
{
SDMMC_ERR_NONE = 0, // No error.
SDMMC_ERR_INVAL_PARAM = 1, // Invalid parameter.
SDMMC_ERR_INITIALIZED = 2, // Card is already initialized.
SDMMC_ERR_GO_IDLE_STATE = 3, // GO_IDLE_STATE CMD error.
SDMMC_ERR_SEND_IF_COND = 4, // SEND_IF_COND CMD error.
SDMMC_ERR_IF_COND_RESP = 5, // IF_COND response pattern mismatch or unsupported voltage.
SDMMC_ERR_SEND_OP_COND = 6, // SEND_OP_COND CMD error.
SDMMC_ERR_OP_COND_TMOUT = 7, // Card initialization timeout.
SDMMC_ERR_VOLT_SUPPORT = 8, // Voltage not supported.
SDMMC_ERR_ALL_SEND_CID = 9, // ALL_SEND_CID CMD error.
SDMMC_ERR_SET_SEND_RCA = 10, // SEND/SET_RELATIVE_ADDR CMD error.
SDMMC_ERR_SEND_CSD = 11, // SEND_CSD CMD error.
SDMMC_ERR_SELECT_CARD = 12, // SELECT_CARD CMD error.
SDMMC_ERR_LOCKED = 13, // Card is locked with a password.
SDMMC_ERR_SET_CLR_CD = 14, // SET_CLR_CARD_DETECT CMD error.
SDMMC_ERR_SET_BUS_WIDTH = 15, // Error on switching to a different bus width.
SDMMC_ERR_SWITCH_HS = 16, // Error on switching to high speed mode.
SDMMC_ERR_SET_BLOCKLEN = 17, // SET_BLOCKLEN CMD error.
SDMMC_ERR_SEND_STATUS = 18, // SEND_STATUS CMD error.
SDMMC_ERR_CARD_STATUS = 19, // The card returned an error via its status.
SDMMC_ERR_NO_CARD = 20, // Card unitialized or not inserted.
SDMMC_ERR_SECT_RW = 21, // Sector read/write error.
SDMMC_ERR_WRITE_PROT = 22 // Can't write. The write protection slider is locked.
};
// SD/MMC device numbers.
enum
{
SDMMC_DEV_SLOT = 0, // SD card/MMC slot.
SDMMC_DEV_eMMC = 1 // Builtin eMMC.
};
typedef struct
{
u8 type; // 0 = none, 1 = SDSC, 2 = SDHC/SDXC, 3 = SDUC, 4 = (e)MMC, 5 = High capacity (e)MMC.
u8 spec_vers; // (e)MMC only SPEC_VERS from CSD. 0 for SD.
u16 rca; // Relative Card Address (RCA).
u32 sectors; // Size in 512 byte units.
u32 clock; // The current clock frequency in Hz.
u32 cid[4]; // Raw CID with the CRC zeroed out.
u16 ccc; // SD/(e)MMC command class support from CSD. One per bit starting at 0.
u8 busWidth; // The current bus width used to talk to the card.
} SdmmcInfo;
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_init(u8 devNum);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_deinit(u8 devNum);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
* @param infoOut The information out
*/
void SDMMC_getCardInfo(u8 devNum, SdmmcInfo *const infoOut);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
* @param cidOut The cid out
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_getCid(u8 devNum, u32 *const cidOut);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_getSectors(u8 devNum);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
* @param[in] sect The sect
* @param buf The buffer
* @param[in] count The count
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_readSectors(u8 devNum, u32 sect, u32 *const buf, u16 count);
/**
* @brief { function_description }
*
* @param[in] devNum The dev number
* @param[in] sect The sect
* @param[in] buf The buffer
* @param[in] count The count
*
* @return { description_of_the_return_value }
*/
u32 SDMMC_writeSectors(u8 devNum, u32 sect, const u32 *const buf, u16 count);

View File

@ -1,98 +0,0 @@
#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 <assert.h>
#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 // #ifdef ARM9
typedef struct
{
union
{
struct
{
vu8 sync_recvd; // 0x0 Received. Set by remote CPU via SENT.
vu8 sync_sent; // 0x1 Write-only, sent.
u8 _0x2;
vu8 sync_irq; // 0x3
};
vu32 sync; // 0x0
};
vu32 cnt; // 0x4
vu32 send; // 0x8 Send FIFO.
const vu32 recv; // 0xC Receive FIFO.
} Pxi;
static_assert(offsetof(Pxi, recv) == 0xC, "Error: Member recv of Pxi is not at offset 0xC!");
ALWAYS_INLINE Pxi* getPxiRegs(void)
{
return (Pxi*)PXI_REGS_BASE;
}
// REG_PXI_SYNC
// Note: SENT and RECV in REG_PXI_SYNC do not count
// the amount of bytes sent or received through the FIFOs!
// They are simply CPU read-/writable fields.
#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) // Trigger interrupt on ARM11.
#define PXI_SYNC_IRQ2 (1u<<30) // Another, separate interrupt trigger for ARM11.
#elif ARM11
// 29 unused unlike ARM9 side.
#define PXI_SYNC_IRQ (1u<<30) // Trigger interrupt on ARM9.
#endif // #ifdef ARM9
#define PXI_SYNC_IRQ_EN (1u<<31) // Enable interrupt(s) from remote CPU.
// REG_PXI_SYNC_IRQ (byte 3 of REG_PXI_SYNC)
#ifdef ARM9
#define PXI_SYNC_IRQ_IRQ (1u<<5) // Trigger interrupt on ARM11.
#define PXI_SYNC_IRQ_IRQ2 (1u<<6) // Another, separate interrupt trigger for ARM11.
#elif ARM11
// 29 unused unlike ARM9 side.
#define PXI_SYNC_IRQ_IRQ (1u<<6) // Trigger interrupt on ARM9.
#endif // #ifdef ARM9
#define PXI_SYNC_IRQ_IRQ_EN (1u<<7) // Enable interrupt(s) from remote CPU.
// REG_PXI_CNT
// Status bits: 0 = no, 1 = yes.
#define PXI_CNT_SEND_EMPTY (1u<<0) // Send FIFO empty status.
#define PXI_CNT_SEND_FULL (1u<<1) // Send FIFO full status.
#define PXI_CNT_SEND_NOT_FULL_IRQ_EN (1u<<2) // Send FIFO not full interrupt enable. TODO: Test the behavior.
#define PXI_CNT_FLUSH_SEND (1u<<3) // Flush send FIFO.
#define PXI_CNT_RECV_EMPTY (1u<<8) // Receive FIFO empty status.
#define PXI_CNT_RECV_FULL (1u<<9) // Receive FIFO full status.
#define PXI_CNT_RECV_NOT_EMPTY_IRQ_EN (1u<<10) // Receive FIFO not empty interrupt enable. TODO: Test the behavior.
#define PXI_CNT_FIFO_ERROR (1u<<14) // Receive FIFO underrun or send FIFO overrun error flag. Acknowledge by writing 1.
#define PXI_CNT_EN_FIFOS (1u<<15) // Enables REG_PXI_SEND and REG_PXI_RECV FIFOs.
void PXI_init(void);
u32 PXI_sendCmd(u32 cmd, const u32 *buf, u32 words);
void PXI_sendPanicCmd(u32 cmd); // Not intended for normal use!

View File

@ -1,126 +0,0 @@
#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 <assert.h>
#include "types.h"
#include "mem_map.h"
#ifdef ARM11
#define SHA_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x1000)
#elif ARM9
#define SHA_REGS_BASE (IO_MEM_ARM9_ONLY + 0xA000)
#endif // #ifdef ARM11
typedef struct
{
vu32 cnt; // 0x00
vu32 blkcnt; // 0x04
u8 _0x8[0x38];
vu32 hash[8]; // 0x40
u8 _0x60[0x20];
volatile _u512 fifo; // 0x80 The FIFO is in the DMA region instead on ARM11.
} Sha;
static_assert(offsetof(Sha, fifo) == 0x80, "Error: Member fifo of Sha is not at offset 0x80!");
ALWAYS_INLINE Sha* getShaRegs(void)
{
return (Sha*)SHA_REGS_BASE;
}
ALWAYS_INLINE volatile _u512* getShaFifo(Sha *const regs)
{
#if (_3DS && ARM11)
return (volatile _u512*)((uintptr_t)regs + 0x200000);
#else
return &regs->fifo;
#endif // #if (_3DS && ARM11)
}
// REG_SHA_CNT
#define SHA_EN (1u) // Also used as busy flag.
#define SHA_FINAL_ROUND (1u<<1)
#define SHA_I_DMA_EN (1u<<2) // Input DMA enable.
#define SHA_IN_BIG (1u<<3)
#define SHA_IN_LITTLE (0u)
#define SHA_OUT_BIG (SHA_IN_BIG)
#define SHA_OUT_LITTLE (SHA_IN_LITTLE)
#define SHA_256_MODE (0u)
#define SHA_224_MODE (1u<<4)
#define SHA_1_MODE (2u<<4)
#define SHA_MODE_MASK (SHA_1_MODE | SHA_224_MODE | SHA_256_MODE)
#define SHA_RB_MODE (1u<<8) // Readback mode.
#define SHA_RB_FIFO_NE (1u<<9) // Readback mode FIFO not empty status.
#define SHA_O_DMA_EN (1u<<10) // Output DMA enable (readback mode).
/**
* @brief Sets input mode, endianess and starts the hash operation.
*
* @param[in] params Extra parameters like endianess. See REG_SHA_CNT defines above.
*/
void SHA_start(u16 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, u16 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 Extra parameters like endianess. See REG_SHA_CNT defines above.
* @param[in] hashEndianess Endianess bitmask for the hash.
*/
void sha(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess);
/**
* @brief Hashes a single block of data with DMA and outputs the hash.
*
* @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 Extra parameters like endianess. See REG_SHA_CNT defines above.
* @param[in] hashEndianess Endianess bitmask for the hash.
*/
//void sha_dma(const u32 *data, u32 size, u32 *const hash, u16 params, u16 hashEndianess);

View File

@ -1,324 +0,0 @@
#pragma once
#include <assert.h>
#include "types.h"
// For simplicity we will name the accessible 2 controllers 1 and 2.
// The real controller number is in the comment.
#ifdef _3DS
#ifdef ARM9
#define TOSHSD1_REGS_BASE (0x10006000u) // Controller 1.
#define TOSHSD2_REGS_BASE (0x10007000u) // Controller 3. Remappable.
#elif ARM11
#define TOSHSD1_REGS_BASE (0x10122000u) // Controller 2.
#define TOSHSD2_REGS_BASE (0x10100000u) // Controller 3. Remappable.
#endif // #ifdef ARM9
#define TOSHSD_HCLK (67027964u) // In Hz.
#elif TWL
#define TOSHSD1_REGS_BASE (0x04004800u) // Controller 1.
#define TOSHSD2_REGS_BASE (0x04004A00u) // Controller 2.
#define TOSHSD_HCLK (33513982u) // In Hz.
#endif // #ifdef _3DS
typedef struct
{
vu16 sd_cmd; // 0x000
vu16 sd_portsel; // 0x002
vu32 sd_arg; // 0x004 SD_ARG0 and SD_ARG1 combined.
vu16 sd_stop; // 0x008
vu16 sd_blockcount; // 0x00A
const vu32 sd_resp[4]; // 0x00C SD_RESP0-7 16 bit reg pairs combined.
vu32 sd_status; // 0x01C SD_STATUS1 and SD_STATUS2 combined.
vu32 sd_status_mask; // 0x020 SD_STATUS1_MASK and SD_STATUS2_MASK combined.
vu16 sd_clk_ctrl; // 0x024
vu16 sd_blocklen; // 0x026
vu16 sd_option; // 0x028 Data timeout: 0x2000<<12 / (67027964 / 2) = 1.001206959 sec. Card detect: 0x400<<9 / 67027964 = 0.007821929 sec.
u8 _0x2a[2];
const vu32 sd_err_status; // 0x02C SD_ERR_STATUS1 and SD_ERR_STATUS2 combined.
vu16 sd_fifo; // 0x030
u8 _0x32[2];
vu16 sdio_mode; // 0x034
vu16 sdio_status; // 0x036
vu16 sdio_status_mask; // 0x038
u8 _0x3a[0x9e];
vu16 dma_ext_mode; // 0x0D8
u8 _0xda[6];
vu16 soft_rst; // 0x0E0
const vu16 revision; // 0x0E2 Controller version/revision?
u8 _0xe4[0xe];
vu16 unkF2; // 0x0F2 Power related? Default 0. Other values do nothing?
vu16 unkF4; // 0x0F4 Unknwon. SDIO IRQ related.
const vu16 ext_wrprot; // 0x0F6 Apparently for eMMC.
vu16 ext_cdet; // 0x0F8 Card detect status.
vu16 ext_cdet_dat3; // 0x0FA DAT3 card detect status.
vu16 ext_cdet_mask; // 0x0FC Card detect mask (IRQ).
vu16 ext_cdet_dat3_mask; // 0x0FE DAT3 card detect mask (IRQ).
vu16 sd_fifo32_cnt; // 0x100
u8 _0x102[2];
vu16 sd_blocklen32; // 0x104
u8 _0x106[2];
vu16 sd_blockcount32; // 0x108
u8 _0x10a[2];
vu32 sd_fifo32; // 0x10C Note: This is in the FIFO region on ARM11 (3DS).
} Toshsd;
static_assert(offsetof(Toshsd, sd_fifo32) == 0x10C, "Error: Member sd_fifo32 of Toshsd is not at offset 0x10C!");
ALWAYS_INLINE Toshsd* getToshsdRegs(u8 controller)
{
Toshsd *regs;
switch(controller)
{
case 0:
regs = (Toshsd*)TOSHSD1_REGS_BASE;
break;
case 1:
regs = (Toshsd*)TOSHSD2_REGS_BASE;
break;
default:
regs = (Toshsd*)NULL;
}
return regs;
}
ALWAYS_INLINE vu32* getToshsdFifo(Toshsd *const regs)
{
#if (_3DS && ARM11)
return (vu32*)((uintptr_t)regs + 0x200000u);
#else
return &regs->sd_fifo32;
#endif // #if (_3DS && ARM11)
}
// REG_SD_CMD
// Bit 0-5 command index.
#define CMD_ACMD (1u<<6) // Application command.
#define CMD_RESP_AUTO (0u) // Response type auto. Really?
#define CMD_RESP_NONE (3u<<8) // Response type none.
#define CMD_RESP_R1 (4u<<8) // Response type R1 48 bit.
#define CMD_RESP_R5 (CMD_RESP_R1) // Response type R5 48 bit.
#define CMD_RESP_R6 (CMD_RESP_R1) // Response type R6 48 bit.
#define CMD_RESP_R7 (CMD_RESP_R1) // Response type R7 48 bit.
#define CMD_RESP_R1b (5u<<8) // Response type R1b 48 bit + busy.
#define CMD_RESP_R5b (CMD_RESP_R1b) // Response type R5b 48 bit + busy.
#define CMD_RESP_R2 (6u<<8) // Response type R2 136 bit.
#define CMD_RESP_R3 (7u<<8) // Response type R3 48 bit OCR without CRC.
#define CMD_RESP_R4 (CMD_RESP_R3) // Response type R4 48 bit OCR without CRC.
#define CMD_RESP_MASK (CMD_RESP_R3)
#define CMD_DT (1u<<11) // Data transfer enable.
#define CMD_DIR_W (0u) // Data transfer direction write.
#define CMD_DIR_R (1u<<12) // Data transfer direction read.
#define CMD_MBT (1u<<13) // Multi block transfer (auto STOP_TRANSMISSION).
#define CMD_SEC_SDIO (1u<<14) // Security/SDIO command.
// REG_SD_PORTSEL
#define PORTSEL_P0 (0u) // Controller port 0.
#define PORTSEL_P1 (1u) // Controller port 1.
#define PORTSEL_P2 (2u) // Controller port 2.
#define PORTSEL_P3 (3u) // Controller port 3.
#define PORTSEL_MASK (PORTSEL_P3)
// Bit 8-9 number of supported ports?
#define PORTSEL_UNK10 (1u<<10) // Unknown writable bit 10?
// REG_SD_STOP
#define STOP_STOP (1u) // Stop/abort a transfer.
#define STOP_AUTO_STOP (1u<<8) // Automatically send CMD12 on block transfer end.
// REG_SD_STATUS1/2 and REG_SD_STATUS1/2_MASK
// (M) = Maskable bit. 1 = disabled.
// Unmaskable bits act as status only, don't trigger IRQs and can't be acknowledged.
#define STATUS_RESP_END (1u) // (M) Response end.
#define STATUS_DATA_END (1u<<2) // (M) Data transfer end (triggers after last block).
#define STATUS_REMOVE (1u<<3) // (M) Card got removed.
#define STATUS_INSERT (1u<<4) // (M) Card got inserted. Set at the same time as DETECT.
#define STATUS_DETECT (1u<<5) // Card detect status (SD_OPTION detection timer). 1 = inserted.
#define STATUS_NO_WRPROT (1u<<7) // Write protection slider unlocked (low).
#define STATUS_DAT3_REMOVE (1u<<8) // (M) Card DAT3 got removed (low).
#define STATUS_DAT3_INSERT (1u<<9) // (M) Card DAT3 got inserted (high).
#define STATUS_DAT3_DETECT (1u<<10) // Card DAT3 status. 1 = inserted.
#define STATUS_ERR_CMD_IDX (1u<<16) // (M) Bad CMD index in response.
#define STATUS_ERR_CRC (1u<<17) // (M) Bad CRC in response.
#define STATUS_ERR_STOP_BIT (1u<<18) // (M) Stop bit error. Failed to recognize response frame end?
#define STATUS_ERR_DATA_TMOUT (1u<<19) // (M) Response data timeout.
#define STATUS_ERR_RX_OVERF (1u<<20) // (M) Receive FIFO overflow.
#define STATUS_ERR_TX_UNDERF (1u<<21) // (M) Send FIFO underflow.
#define STATUS_ERR_CMD_TMOUT (1u<<22) // (M) Response start bit timeout.
#define STATUS_SD_BUSY (1u<<23) // SD card signals busy if this bit is 0 (DAT0 held low).
#define STATUS_RX_RDY (1u<<24) // (M) FIFO ready for read.
#define STATUS_TX_REQ (1u<<25) // (M) FIFO write request.
// Bit 27 is maskable. Purpose unknown.
// Bit 29 exists (not maskable). Unknown purpose.
#define STATUS_CMD_BUSY (1u<<30) // Command register busy.
#define STATUS_ERR_ILL_ACC (1u<<31) // (M) Illegal access error. TODO: What does that mean?
#define STATUS_MASK_ALL (STATUS_ERR_ILL_ACC | (1u<<27) | STATUS_TX_REQ | STATUS_RX_RDY | \
STATUS_ERR_CMD_TMOUT | STATUS_ERR_TX_UNDERF | STATUS_ERR_RX_OVERF | \
STATUS_ERR_DATA_TMOUT | STATUS_ERR_STOP_BIT | STATUS_ERR_CRC | \
STATUS_ERR_CMD_IDX | STATUS_DAT3_INSERT | STATUS_DAT3_REMOVE | \
STATUS_INSERT | STATUS_REMOVE | STATUS_DATA_END | STATUS_RESP_END)
#define STATUS_MASK_DEFAULT ((1u<<27) | STATUS_TX_REQ | STATUS_RX_RDY | \
STATUS_DAT3_INSERT | STATUS_DAT3_REMOVE | STATUS_DATA_END)
#define STATUS_MASK_ERR (STATUS_ERR_ILL_ACC | STATUS_ERR_CMD_TMOUT | STATUS_ERR_TX_UNDERF | \
STATUS_ERR_RX_OVERF | STATUS_ERR_DATA_TMOUT | STATUS_ERR_STOP_BIT | \
STATUS_ERR_CRC | STATUS_ERR_CMD_IDX)
// REG_SD_CLK_CTRL
#define SD_CLK_DIV_2 (0u) // Clock divider 2.
#define SD_CLK_DIV_4 (1u) // Clock divider 4.
#define SD_CLK_DIV_8 (1u<<1) // Clock divider 8.
#define SD_CLK_DIV_16 (1u<<2) // Clock divider 16.
#define SD_CLK_DIV_32 (1u<<3) // Clock divider 32.
#define SD_CLK_DIV_64 (1u<<4) // Clock divider 64.
#define SD_CLK_DIV_128 (1u<<5) // Clock divider 128.
#define SD_CLK_DIV_256 (1u<<6) // Clock divider 256.
#define SD_CLK_DIV_512 (1u<<7) // Clock divider 512.
#define SD_CLK_EN (1u<<8) // Clock enable.
#define SD_CLK_AUTO_OFF (1u<<9) // Disables clock on idle.
// Bit 10 is writable... at least according to gbatek (can't confirm). Purpose unknown.
// REG_SD_OPTION
// TODO: Bit 0-3 card detect timer 0x400<<x HCLKs. 0xF timer test.
// TODO: Bit 4-7 data timeout 0x2000<<x (HCLK / divider). 0xF timeout test.
#define OPTION_UNK14 (1u<<14) // "no C2 module" What the fuck is a C2 module?
#define OPTION_BUS_WIDTH4 (0u) // 4 bit bus width.
#define OPTION_BUS_WIDTH1 (1u<<15) // 1 bit bus width.
// REG_SD_ERR_STATUS1/2
// TODO: Are all of these actually supported on this controller?
#define ERR_RESP_CMD_IDX (1u) // Manual command index error in response.
#define ERR_RESP_CMD12_IDX (1u<<1) // Auto command index error in response.
#define ERR_RESP_STOP_BIT (1u<<2) // Manual command response stop bit error.
#define ERR_RESP_STOP_BIT_CMD12 (1u<<3) // Auto command response stop bit error.
#define ERR_STOP_BIT_DATA_READ (1u<<4) // Stop bit error in read data.
#define ERR_STOP_BIT_WR_CRC (1u<<5) // Stop bit error for write CRC status. What the hell does that mean?
#define ERR_CMD_RESP_CRC (1u<<8) // Manual command response CRC error.
#define ERR_CMD12_RESP_CRC (1u<<9) // Auto command response CRC error.
#define ERR_DATA_READ_CRC (1u<<10) // CRC error for read data.
#define ERR_WR_CRC_STAT (1u<<11) // "CRC error for Write CRC status for a write command". What the hell does that mean?
// Bit 13 always 1.
#define ERR_CMD_RESP_TMOUT (1u<<16) // Manual command response timeout.
#define ERR_CMD12_RESP_TMOUT (1u<<17) // Auto command response timeout.
// TODO: Add the correct remaining ones.
// REG_SDIO_MODE
// REG_SDIO_STATUS and REG_SDIO_STATUS_MASK
// REG_DMA_EXT_MODE
#define DMA_EXT_CPU_MODE (0u) // Disables DMA requests. Actually also turns off the 32 bit FIFO.
#define DMA_EXT_DMA_MODE (1u<<1) // Enables DMA requests.
#define DMA_EXT_UNK5 (1u<<5) // "Buffer status mode"?
// REG_SOFT_RST
#define SOFT_RST_RST (0u) // Reset.
#define SOFT_RST_NORST (1u) // No reset.
// REG_EXT_WRPROT
// 1 = Write protected unlike SD_STATUS.
#define EXT_WRPROT_PORT1 (1u)
#define EXT_WRPROT_PORT2 (1u<<1)
#define EXT_WRPROT_PORT3 (1u<<2)
// REG_EXT_CDET and REG_EXT_CDET_MASK
// (M) = Maskable bit. 1 = disabled (no IRQ).
#define EXT_CDET_P1_REMOVE (1u) // (M) Port 1 card got removed.
#define EXT_CDET_P1_INSERT (1u<<1) // (M) Port 1 card got inserted. TODO: With detection timer?
#define EXT_CDET_P1_DETECT (1u<<2) // Port 1 card detect status. 1 = inserted. TODO: With detection timer?
#define EXT_CDET_P2_REMOVE (1u<<3) // (M) Port 2 card got removed.
#define EXT_CDET_P2_INSERT (1u<<4) // (M) Port 2 card got inserted. TODO: With detection timer?
#define EXT_CDET_P2_DETECT (1u<<5) // Port 2 card detect status. 1 = inserted. TODO: With detection timer?
#define EXT_CDET_P3_REMOVE (1u<<6) // (M) Port 3 card got removed.
#define EXT_CDET_P3_INSERT (1u<<7) // (M) Port 3 card got inserted. TODO: With detection timer?
#define EXT_CDET_P3_DETECT (1u<<8) // Port 3 card detect status. 1 = inserted. TODO: With detection timer?
#define EXT_CDET_MASK_ALL (EXT_CDET_P3_INSERT | EXT_CDET_P3_REMOVE | EXT_CDET_P2_INSERT | \
EXT_CDET_P2_REMOVE | EXT_CDET_P1_INSERT | EXT_CDET_P1_REMOVE)
// REG_EXT_CDET_DAT3 and REG_EXT_CDET_DAT3_MASK
// (M) = Maskable bit. 1 = disabled (no IRQ).
#define EXT_CDET_DAT3_P1_REMOVE (1u) // (M) Port 1 card DAT3 got removed (low).
#define EXT_CDET_DAT3_P1_INSERT (1u<<1) // (M) Port 1 card DAT3 got inserted (high).
#define EXT_CDET_DAT3_P1_DETECT (1u<<2) // Port 1 card DAT3 status. 1 = inserted.
#define EXT_CDET_DAT3_P2_REMOVE (1u<<3) // (M) Port 2 card DAT3 got removed (low).
#define EXT_CDET_DAT3_P2_INSERT (1u<<4) // (M) Port 2 card DAT3 got inserted (high).
#define EXT_CDET_DAT3_P2_DETECT (1u<<5) // Port 2 card DAT3 status. 1 = inserted.
#define EXT_CDET_DAT3_P3_REMOVE (1u<<6) // (M) Port 3 card DAT3 got removed (low).
#define EXT_CDET_DAT3_P3_INSERT (1u<<7) // (M) Port 3 card DAT3 got inserted (high).
#define EXT_CDET_DAT3_P3_DETECT (1u<<8) // Port 3 card DAT3 status. 1 = inserted.
#define EXT_CDET_DAT3_MASK_ALL (EXT_CDET_DAT3_P3_INSERT | EXT_CDET_DAT3_P3_REMOVE | EXT_CDET_DAT3_P2_INSERT | \
EXT_CDET_DAT3_P2_REMOVE | EXT_CDET_DAT3_P1_INSERT | EXT_CDET_DAT3_P1_REMOVE)
// REG_SD_FIFO32_CNT
#define FIFO32_UNK1 (1u) // Unknown bit.
#define FIFO32_EN (1u<<1) // Enables the 32 bit FIFO.
#define FIFO32_FULL (1u<<8) // FIFO is full.
#define FIFO32_NOT_EMPTY (1u<<9) // FIFO is not empty. Inverted bit. 0 means empty.
#define FIFO32_CLEAR (1u<<10) // Clears the FIFO.
#define FIFO32_FULL_IE (1u<<11) // FIFO full IRQ enable.
#define FIFO32_NOT_EMPTY_IE (1u<<12) // FIFO not empty IRQ enable.
typedef struct
{
u8 portNum;
u16 sd_clk_ctrl;
u16 sd_blocklen; // Also sd_blocklen32.
u16 sd_option;
u32 *buf;
u16 blocks;
u32 resp[4]; // Little endian, MSB first.
} ToshsdPort;
// See status defines in regs/toshsd.h for details.
#define TSD_ERR_CMD_IDX (1u<<16)
#define TSD_ERR_CRC (1u<<17)
#define TSD_ERR_STOP_BIT (1u<<18)
#define TSD_ERR_DATA_TMOUT (1u<<19)
#define TSD_ERR_RX_OVERF (1u<<20)
#define TSD_ERR_TX_UNDERF (1u<<21)
#define TSD_ERR_CMD_TMOUT (1u<<22)
#define TSD_ERR_ILL_ACC (1u<<31)
void TOSHSD_init(void);
void TOSHSD_deinit(void);
void TOSHSD_initPort(ToshsdPort *const port, u8 portNum);
bool TOSHSD_cardDetected(void);
bool TOSHSD_cardSliderUnlocked(void);
void TOSHSD_setClock(ToshsdPort *const port, u16 clk);
u32 TOSHSD_sendCommand(ToshsdPort *const port, u16 cmd, u32 arg);
ALWAYS_INLINE void TOSHSD_setBlockLen(ToshsdPort *const port, u16 blockLen)
{
if(blockLen > 512) blockLen = 512;
if(blockLen < 16) blockLen = 0;
if((blockLen % 16) != 0) blockLen = 0;
port->sd_blocklen = blockLen;
}
ALWAYS_INLINE void TOSHSD_setBusWidth(ToshsdPort *const port, u8 width)
{
// TODO: Make this more readable.
if(width == 4) port->sd_option = 1u<<14 | 0xE9;
else port->sd_option = 1u<<15 | 1u<<14 | 0xE9u;
}
ALWAYS_INLINE void TOSHSD_setBuffer(ToshsdPort *const port, u32 *buf, u16 blocks)
{
port->buf = buf;
port->blocks = blocks;
}
#ifdef ARM11
void TOSHSD_dbgPrint(ToshsdPort *const port);
#endif

View File

@ -1,45 +0,0 @@
#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/>.
*/
// Note on port numbers:
// To make things easier 2 ports are assigned to each controller.
// There are a maximum of 2 controllers mapped at the same time
// and 3 (on DSi 2) controllers in total.
// Also see /regs/toshsd.h.
//
// Examples:
// Port 0 is port 0 on controller 1, port 3 is port 1 on controller 2.
#ifdef _3DS
#define TOSHSD_C3_MAP (0u) // Controller 3 memory mapping. 0=ARM9 0x10007000 or 1=ARM11 0x10100000.
#ifdef ARM9
#define TOSHSD_SLOT_PORT (2u) // Can be on port 0 or 2.
#define TOSHSD_eMMC_PORT (1u) // Port 1 only.
#elif ARM11
#define TOSHSD_SLOT_PORT (2u) // Port 2 only.
#define TOSHSD_eMMC_PORT (3u) // Not connected/accessible.
#endif // #ifdef ARM9
#elif TWL
#define TOSHSD_SLOT_PORT (0u)
#define TOSHSD_eMMC_PORT (1u)
#endif // #ifdef _3DS

View File

@ -1,75 +0,0 @@
#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"
#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

View File

@ -1,32 +0,0 @@
#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 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);

View File

@ -1,64 +0,0 @@
#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"
#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

View File

@ -1,28 +0,0 @@
#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"
#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);

View File

@ -1,92 +0,0 @@
#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"
#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_SEND_BUFS_MASK(cmd) ((cmd)>>6 & 3u) // Max 3
#define IPC_CMD_RECV_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(sendBufs, recvBufs, params) ((__COUNTER__ - _CMD9_C_BASE)<<8 | (sendBufs)<<6 | (recvBufs)<<4 | params)
#define MAKE_CMD11(sendBufs, recvBufs, params) ((__COUNTER__ - _CMD11_C_BASE)<<8 | (sendBufs)<<6 | (recvBufs)<<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 sendBufs, u32 recvBufs, const u32 *const buf);

View File

@ -1,153 +0,0 @@
#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/>.
*/
#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

View File

@ -1,28 +0,0 @@
#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);

View File

@ -1,77 +0,0 @@
#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 <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;

View File

@ -1,97 +0,0 @@
#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"
#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));
}

View File

@ -1,40 +0,0 @@
#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/>.
*/
// 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.
// TODO: More checks. For example slabheap.
#if (MAX_PRIO_BITS < 3 || MAX_PRIO_BITS > 32)
#error "Invalid number of maximum task priorities!"
#endif

View File

@ -1,78 +0,0 @@
#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 <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);

View File

@ -1,35 +0,0 @@
#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);

View File

@ -1,103 +0,0 @@
#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))

View File

@ -1,63 +0,0 @@
#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 <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);

View File

@ -1,45 +0,0 @@
#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"
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");
}

View File

@ -1,23 +0,0 @@
#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/>.
*/
#define LIKELY(expr) __builtin_expect((expr), true)
#define UNLIKELY(expr) __builtin_expect((expr), false)

View File

@ -1,78 +0,0 @@
#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 <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() implementation.
typedef uintptr_t KHandle;
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 KHandle for the created task or NULL on error.
*/
KHandle 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

View File

@ -1,85 +0,0 @@
#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 <stdbool.h>
#include "kernel.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Creates a new kernel event.
*
* @param[in] oneShot Event fires only once and auto clears if true.
*
* @return The KHandle for the event or NULL on error.
*/
KHandle createEvent(bool oneShot);
/**
* @brief Deletes an kernel event.
*
* @param[in] kevent The KHandle of the event to delete.
*/
void deleteEvent(KHandle const kevent);
/**
* @brief Binds the given kernel event to an interrupt.
*
* @param[in] kevent The KHandle of the event.
* @param[in] id The interrupt id.
* @param[in] prio The interrupt priority.
*/
void bindInterruptToEvent(KHandle const kevent, uint8_t id, uint8_t prio);
void unbindInterruptEvent(uint8_t id);
/**
* @brief Waits for a kernel event to be signaled.
*
* @param[in] kevent The KHandle of the event.
*
* @return Returns the result. See Kres in kernel.h.
*/
KRes waitForEvent(KHandle const kevent);
/**
* @brief Signals an kernel event.
*
* @param[in] kevent The KHandle of the event.
* @param[in] reschedule Set to true to immediately reschedule.
*/
void signalEvent(KHandle const kevent, bool reschedule);
/**
* @brief Clears an kernel event.
*
* @param[in] kevent The KHandle of the event.
*/
void clearEvent(KHandle const kevent);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -1,68 +0,0 @@
#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 "kernel.h"
#ifdef __cplusplus
extern "C"
{
#endif
// TODO: Implement this using semaphores?
/**
* @brief Creates a new kernel mutex.
*
* @return The KHandle of the mutex or NULL on error.
*/
KHandle createMutex(void);
/**
* @brief Deletes a kernel mutex.
*
* @param[in] kmutex The KHandle of the mutex.
*/
void deleteMutex(KHandle const kmutex);
/**
* @brief Locks a kernel mutex.
*
* @param[in] kmutex The KHandle of the mutex.
*
* @return Returns the result. See Kres in kernel.h.
*/
KRes lockMutex(KHandle const kmutex);
/**
* @brief Unlocks a kernel mutex.
*
* @param[in] kmutex The KHandle of the mutex.
*
* @return Returns KRES_NO_PERMISSIONS immediately if the current task
* @return is not the owner. Otherwise KRES_OK.
*/
KRes unlockMutex(KHandle const kmutex);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -1,78 +0,0 @@
#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 <stdint.h>
#include <stdbool.h>
#include "kernel.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Creates a new kernel semaphore.
*
* @param[in] count The initial count of the semaphore.
*
* @return The KHandle of the semaphore or NULL on error.
*/
KHandle createSemaphore(int32_t count);
/**
* @brief Deletes a kernel semaphore.
*
* @param[in] ksema The KHandle of the semaphore.
*/
void deleteSemaphore(KHandle const ksema);
/**
* @brief Polls a kernel semaphore.
*
* @param[in] ksema The KHandle of the semaphore.
*
* @return Returns KRES_OK or KRES_WOULD_BLOCK.
*/
KRes pollSemaphore(KHandle const ksema);
/**
* @brief Decreases the kernel semaphore and blocks if <=0.
*
* @param[in] ksema The KHandle of the semaphore.
*
* @return Returns the result. See Kres in kernel.h.
*/
KRes waitForSemaphore(KHandle const ksema);
/**
* @brief Increases the kernel semaphore and wakes up signalCount waiting tasks if any.
*
* @param[in] ksema The KHandle of the semaphore.
* @param[in] signalCount The number of tasks to wake up..
* @param[in] reschedule Set to true to immediately reschedule.
*/
void signalSemaphore(KHandle const ksema, uint32_t signalCount, bool reschedule);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -1,67 +0,0 @@
/*
* 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 "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

View File

@ -1,276 +0,0 @@
/*
* 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 <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;
}
KHandle createTask(size_t stackSize, uint8_t priority, TaskFunc entry, void *taskArg)
{
if(priority > MAX_PRIO_BITS - 1u) return 0;
// 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 0;
}
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 (uintptr_t)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);
}

View File

@ -1,136 +0,0 @@
/*
* 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 <stdbool.h>
#include <stdlib.h>
#include "types.h"
#include "internal/list.h"
#include "arm11/drivers/interrupt.h"
#include "internal/kernel_private.h"
#include "internal/slabheap.h"
#include "internal/config.h"
typedef struct
{
bool signaled;
const bool oneShot;
ListNode waitQueue;
} KEvent;
static SlabHeap g_eventSlab = {0};
static KHandle g_irqEventTable[128 - 32] = {0}; // 128 - 32 private interrupts.
void signalEvent(KHandle const kevent, bool reschedule);
void _eventSlabInit(void)
{
slabInit(&g_eventSlab, sizeof(KEvent), MAX_EVENTS);
}
static void eventIrqHandler(u32 intSource)
{
signalEvent(g_irqEventTable[intSource - 32], false);
}
KHandle createEvent(bool oneShot)
{
KEvent *const event = (KEvent*)slabAlloc(&g_eventSlab);
event->signaled = false;
*(bool*)&event->oneShot = oneShot;
listInit(&event->waitQueue);
return (KHandle)event;
}
void deleteEvent(KHandle const kevent)
{
KEvent *const event = (KEvent*)kevent;
kernelLock();
waitQueueWakeN(&event->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
slabFree(&g_eventSlab, event);
}
// TODO: Critical sections needed for bind/unbind?
void bindInterruptToEvent(KHandle 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] = 0;
IRQ_unregisterIsr(id);
}
// TODO: Timeout.
KRes waitForEvent(KHandle const kevent)
{
KEvent *const event = (KEvent*)kevent;
KRes res;
kernelLock();
if(event->signaled)
{
if(event->oneShot) event->signaled = false;
kernelUnlock();
res = KRES_OK;
}
else res = waitQueueBlock(&event->waitQueue);
return res;
}
void signalEvent(KHandle const kevent, bool reschedule)
{
KEvent *const event = (KEvent*)kevent;
kernelLock();
if(!event->signaled)
{
if(event->oneShot)
{
if(!waitQueueWakeN(&event->waitQueue, 1, KRES_OK, reschedule))
event->signaled = true;
}
else
{
event->signaled = true;
waitQueueWakeN(&event->waitQueue, (u32)-1, KRES_OK, reschedule);
}
}
else kernelUnlock();
}
void clearEvent(KHandle const kevent)
{
kernelLock(); // TODO: Can we do this without locks?
((KEvent*)kevent)->signaled = false;
kernelUnlock();
}

View File

@ -1,101 +0,0 @@
/*
* 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

View File

@ -1,109 +0,0 @@
/*
* 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 <stdlib.h>
#include "types.h"
#include "internal/list.h"
#include "internal/kernel_private.h"
#include "internal/util.h"
#include "internal/slabheap.h"
#include "internal/config.h"
typedef struct
{
const TaskCb *owner;
ListNode waitQueue;
} KMutex;
static SlabHeap g_mutexSlab = {0};
void _mutexSlabInit(void)
{
slabInit(&g_mutexSlab, sizeof(KMutex), MAX_MUTEXES);
}
// TODO: Test mutex with multiple cores.
KHandle createMutex(void)
{
KMutex *const kmutex = (KMutex*)slabAlloc(&g_mutexSlab);
kmutex->owner = NULL;
listInit(&kmutex->waitQueue);
return (KHandle)kmutex;
}
void deleteMutex(KHandle const kmutex)
{
KMutex *const mutex = (KMutex*)kmutex;
kernelLock();
waitQueueWakeN(&mutex->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
slabFree(&g_mutexSlab, mutex);
}
KRes lockMutex(KHandle const kmutex)
{
KMutex *const mutex = (KMutex*)kmutex;
KRes res;
do
{
kernelLock();
if(UNLIKELY(mutex->owner != NULL))
{
res = waitQueueBlock(&mutex->waitQueue);
if(UNLIKELY(res != KRES_OK)) break;
}
else
{
mutex->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(KHandle const kmutex)
{
KMutex *const mutex = (KMutex*)kmutex;
KRes res = KRES_OK;
kernelLock();
if(LIKELY(mutex->owner != NULL))
{
if(LIKELY(mutex->owner == getCurrentTask()))
{
mutex->owner = NULL;
waitQueueWakeN(&mutex->waitQueue, 1, KRES_OK, true);
}
else res = KRES_NO_PERMISSIONS;
}
else kernelUnlock();
return res;
}

View File

@ -1,101 +0,0 @@
/*
* 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 <stdbool.h>
#include <stdlib.h>
#include "types.h"
#include "internal/list.h"
#include "internal/kernel_private.h"
#include "internal/util.h"
#include "internal/slabheap.h"
#include "internal/config.h"
typedef struct
{
s32 count;
ListNode waitQueue;
} KSema;
static SlabHeap g_semaSlab = {0};
void _semaphoreSlabInit(void)
{
slabInit(&g_semaSlab, sizeof(KSema), MAX_SEMAPHORES);
}
// TODO: Test semaphore with multiple cores.
KHandle createSemaphore(int32_t count)
{
KSema *const ksema = (KSema*)slabAlloc(&g_semaSlab);
ksema->count = count;
listInit(&ksema->waitQueue);
return (KHandle)ksema;
}
void deleteSemaphore(KHandle const ksema)
{
KSema *const sema = (KSema*)ksema;
kernelLock();
waitQueueWakeN(&sema->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
slabFree(&g_semaSlab, sema);
}
KRes pollSemaphore(KHandle const ksema)
{
KSema *const sema = (KSema*)ksema;
KRes res;
// TODO: Plain spinlocks instead?
kernelLock();
if(UNLIKELY(sema->count <= 0)) res = KRES_WOULD_BLOCK;
else {sema->count--; res = KRES_OK;}
kernelUnlock();
return res;
}
KRes waitForSemaphore(KHandle const ksema)
{
KSema *const sema = (KSema*)ksema;
KRes res;
kernelLock();
if(UNLIKELY(--sema->count < 0)) res = waitQueueBlock(&sema->waitQueue);
else {kernelUnlock(); res = KRES_OK;}
return res;
}
void signalSemaphore(KHandle const ksema, uint32_t signalCount, bool reschedule)
{
KSema *const sema = (KSema*)ksema;
kernelLock();
//if(UNLIKELY(++sema->count <= 0))
if(UNLIKELY((sema->count += signalCount) <= 0))
waitQueueWakeN(&sema->waitQueue, signalCount, KRES_OK, reschedule);
else kernelUnlock();
}

View File

@ -1,134 +0,0 @@
/*
* 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 <stdbool.h>
#include <stdlib.h>
#include "types.h"
#include "ktimer.h"
#include "internal/list.h"
#include "arm11/drivers/interrupt.h"
//#include "arm11/drivers/timer.h"
#include "internal/kernel_private.h"
#include "internal/slabheap.h"
#include "internal/config.h"
//#include "arm11/fmt.h"
typedef struct
{
ListNode node;
u32 delta;
u32 ticks;
const bool pulse;
ListNode waitQueue;
} KTimer;
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);
}
KHandle createTimer(bool pulse)
{
KTimer *const ktimer = (KTimer*)slabAlloc(&g_timerSlab);
*(bool*)&ktimer->pulse = pulse;
listInit(&ktimer->waitQueue);
return (KHandle)ktimer;
}
void deleteTimer(KHandle const ktimer)
{
KTimer *const timer = (KTimer*)ktimer;
kernelLock();
waitQueueWakeN(&timer->waitQueue, (u32)-1, KRES_HANDLE_DELETED, true);
slabFree(&g_timerSlab, timer);
}
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(KHandle const ktimer, uint32_t usec)
{
KTimer *const timer = (KTimer*)ktimer;
const u32 ticks = TIMER_FREQ(1, 1000000) * usec;
timer->ticks = ticks;
kernelLock();
const bool firstTimer = listEmpty(&g_deltaQueue);
addToDeltaQueue(timer, ticks);
kernelUnlock();
if(firstTimer) TIMER_start(1, ticks, false, true);
}
void stopTimer(KHandle const ktimer)
{
}
KRes waitForTimer(KHandle const ktimer)
{
KTimer *const timer = (KTimer*)ktimer;
kernelLock();
return waitQueueBlock(&timer->waitQueue);
}*/

View File

@ -1,62 +0,0 @@
/*
* 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 <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);
}

View File

@ -1,48 +0,0 @@
#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);
}

View File

@ -1,154 +0,0 @@
#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;
}

View File

@ -1,90 +0,0 @@
#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();
};

View File

@ -1,95 +0,0 @@
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();
}

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