Compare commits
119 Commits
alpha_2021
...
master
Author | SHA1 | Date |
---|---|---|
![]() |
6b882e9395 | |
![]() |
4e4c2aa2b5 | |
![]() |
dd90d498c4 | |
![]() |
877f7c61d0 | |
![]() |
7a7190baea | |
![]() |
edd43a6fcc | |
![]() |
50e2f30e0d | |
![]() |
79b2457e8b | |
![]() |
5356e5c89a | |
![]() |
67ce019b36 | |
![]() |
41db8760a6 | |
![]() |
3a70cdc27f | |
![]() |
b1c66e24a2 | |
![]() |
f7efd62ea9 | |
![]() |
073daac2bb | |
![]() |
15436e02a7 | |
![]() |
3e91716c80 | |
![]() |
f9786b14a1 | |
![]() |
bd5b207106 | |
![]() |
7c8c3d6fe8 | |
![]() |
6cf6059023 | |
![]() |
1ad621d4f4 | |
![]() |
9f331c24f7 | |
![]() |
3ffb706f3b | |
![]() |
c85a4b1b57 | |
![]() |
6db20e190c | |
![]() |
d7f701f02a | |
![]() |
2bca9b04b6 | |
![]() |
678cbd9ae3 | |
![]() |
479069d039 | |
![]() |
99cf0fdacc | |
![]() |
9d13ad3722 | |
![]() |
07bdaf521d | |
![]() |
e14704181c | |
![]() |
63e4422db1 | |
![]() |
b554c7c35c | |
![]() |
5f46a967a8 | |
![]() |
dc5ac1749f | |
![]() |
855f6b131a | |
![]() |
e77b04f089 | |
![]() |
ddba28b226 | |
![]() |
8db77d523e | |
![]() |
4377d28d14 | |
![]() |
1ca27c22f6 | |
![]() |
6766b224dc | |
![]() |
a3c8f76e82 | |
![]() |
92c591da22 | |
![]() |
0f55ad941c | |
![]() |
cf7d1915e0 | |
![]() |
8ecc7ce458 | |
![]() |
4f96bae9d3 | |
![]() |
014c341e67 | |
![]() |
726a4f3355 | |
![]() |
30351188a4 | |
![]() |
cecd0d31f3 | |
![]() |
3d8a24769d | |
![]() |
1e5e1ea6a9 | |
![]() |
5e103deecc | |
![]() |
80f48ca43e | |
![]() |
a70673dea7 | |
![]() |
99d6b1e1ea | |
![]() |
6298503e6b | |
![]() |
cdacbc7dc5 | |
![]() |
edaa5fb2cb | |
![]() |
d80588ffc4 | |
![]() |
93d5cdf045 | |
![]() |
45830c8c68 | |
![]() |
c171c4da1d | |
![]() |
b1739994a2 | |
![]() |
6bfccaee80 | |
![]() |
b710d8e326 | |
![]() |
834c0ffbbf | |
![]() |
b1d2b5a84a | |
![]() |
09622b88f8 | |
![]() |
48448c749c | |
![]() |
a13499c49e | |
![]() |
1fe529f4c5 | |
![]() |
bd6bc4fd54 | |
![]() |
ee21e3edb0 | |
![]() |
6b5abf383d | |
![]() |
56bf27a026 | |
![]() |
3183839120 | |
![]() |
5ab356a248 | |
![]() |
9bd9497315 | |
![]() |
25b1f794c2 | |
![]() |
9e44587f1c | |
![]() |
dbaad7d09c | |
![]() |
4e86b0c6bf | |
![]() |
b128dd4575 | |
![]() |
a588af0b3c | |
![]() |
dd4f51334f | |
![]() |
97bdad5710 | |
![]() |
f486ba2b9f | |
![]() |
8f86f79461 | |
![]() |
78fd101c66 | |
![]() |
c139ceb720 | |
![]() |
92f3208daa | |
![]() |
f9f47df59e | |
![]() |
9d54442c42 | |
![]() |
b8b75d784c | |
![]() |
5714b5eb16 | |
![]() |
dc0320615b | |
![]() |
3a31110673 | |
![]() |
1c680e7d52 | |
![]() |
4a6603d110 | |
![]() |
2222e54f0f | |
![]() |
782596facd | |
![]() |
a9fcf853bb | |
![]() |
9756e2eafc | |
![]() |
15cf1bffd5 | |
![]() |
247cb19cb5 | |
![]() |
35243abed0 | |
![]() |
37f3df4a52 | |
![]() |
d7baad122a | |
![]() |
b09e3a0eee | |
![]() |
6129451b75 | |
![]() |
f59f596a2b | |
![]() |
434f714ef1 | |
![]() |
82d54b341c |
|
@ -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
|
|
@ -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*.*
|
|
@ -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
|
56
Makefile
56
Makefile
|
@ -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
191
README.md
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -22,4 +22,13 @@
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
Result browseFiles(const char *const basePath, char selected[512]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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__
|
|
@ -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);
|
|
@ -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
|
|
@ -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" : :);
|
||||
}*/
|
|
@ -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.
|
|
@ -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);
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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.
|
||||
///@}
|
|
@ -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)))
|
|
@ -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);
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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];
|
||||
}
|
|
@ -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);
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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);
|
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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[];
|
|
@ -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)
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 card’s 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 command’s 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.70–1.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))
|
|
@ -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))
|
|
@ -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);
|
|
@ -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!
|
|
@ -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 ®s->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);
|
|
@ -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 ®s->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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
|
@ -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;
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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);
|
|
@ -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);
|
|
@ -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))
|
|
@ -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);
|
|
@ -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");
|
||||
}
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}*/
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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
Loading…
Reference in New Issue