Line 230: |
Line 230: |
| ! REGISTER | | ! REGISTER |
| ! WIDTH | | ! WIDTH |
| + | ! INFO |
| ! DESCRIPTION | | ! DESCRIPTION |
| |- | | |- |
| | 0x00 | | | 0x00 |
− | | 1 | + | | s |
| + | | ro |
| | Version high | | | Version high |
| |- | | |- |
| | 0x01 | | | 0x01 |
− | | 1 | + | | s |
| + | | ro |
| | Version low | | | Version low |
− | |-
| |
− | | 0x03
| |
− | | 8
| |
− | | ?
| |
| |- | | |- |
| | 0x04 | | | 0x04 |
− | | 8 | + | | s |
− | | ? | + | | rw |
| + | | Top screen flicker |
| |- | | |- |
| | 0x05 | | | 0x05 |
− | | 0x4003? | + | | s / 0x4003? |
− | | Danger zone - [[MCU_Services#MCU_firmware_versions|MCU firmware]] is uploaded here | + | | rw / ? |
| + | | Bottom screen flicker or Danger zone - [[MCU_Services#MCU_firmware_versions|MCU firmware]] is uploaded here (???) |
| |- | | |- |
| | 0x08 | | | 0x08 |
− | | 1 | + | | s |
− | | 3D slider position 0x9..0xFB | + | | ro |
| + | | Raw 3D slider position |
| |- | | |- |
| | 0x09 | | | 0x09 |
− | | 1 | + | | s |
− | | Sound volume: 0x0..0x3F. | + | | ro |
| + | | Volume slider state (0x00 - 0x3F) |
| + | This is the same value returned by [[MCUHWC:GetSoundVolume|MCUHWC:GetSoundVolume]] |
| |- | | |- |
− | | 0xB | + | | 0x0B |
− | | 1 | + | | s |
− | | Battery level: 0x0..0x40. | + | | ro |
| + | | Battery percentage |
| |- | | |- |
− | | 0xF | + | | 0x0D |
− | | 1 | + | | s |
| + | | ro |
| + | | System voltage |
| + | |- |
| + | | 0x0F |
| + | | s |
| + | | ro |
| | Flags: bit7-5 are read via [[MCU_Services|mcu::GPU]]. The rest of these are read via [[MCU_Services|mcu::RTC]]: bit4 = BatteryChargeState. bit3 = AdapterState. bit1 = ShellState. | | | Flags: bit7-5 are read via [[MCU_Services|mcu::GPU]]. The rest of these are read via [[MCU_Services|mcu::RTC]]: bit4 = BatteryChargeState. bit3 = AdapterState. bit1 = ShellState. |
| |- | | |- |
| | 0x10 | | | 0x10 |
− | | 1 | + | | s |
| + | | ro |
| | Special HID status flags: bit0 = power button pressed, bit1 = power button pressed long, bit2 = home button pressed, bit3 = home button released, bit4 = wifi slider enabled, bit5 = shell got closed, bit6 = shell got opened. If nothing has changed this register is 0. | | | Special HID status flags: bit0 = power button pressed, bit1 = power button pressed long, bit2 = home button pressed, bit3 = home button released, bit4 = wifi slider enabled, bit5 = shell got closed, bit6 = shell got opened. If nothing has changed this register is 0. |
| |- | | |- |
| | 0x12 | | | 0x12 |
− | | 1 | + | | s |
| + | | ro |
| | 0x40 if volume slider position changed | | | 0x40 if volume slider position changed |
− | |-
| |
− | | 0x18
| |
− | | 8
| |
− | | ?
| |
| |- | | |- |
| | 0x20 | | | 0x20 |
− | | 8 | + | | s |
| + | | wo(?) |
| | System power control - bit0 = power off, bit1 = reboot (unused?). bit2 = reboot (used by mcu-module and LgyBg). bit3 = used by LgyBg to power off, causes hangs in 3DS-mode. bit4 = doesn't seem to do anything, but an mcu::RTC command uses this. Other bits are unused, and seem to do nothing. | | | System power control - bit0 = power off, bit1 = reboot (unused?). bit2 = reboot (used by mcu-module and LgyBg). bit3 = used by LgyBg to power off, causes hangs in 3DS-mode. bit4 = doesn't seem to do anything, but an mcu::RTC command uses this. Other bits are unused, and seem to do nothing. |
| |- | | |- |
| | 0x22 | | | 0x22 |
− | | 8 | + | | s |
| + | | rw(?) |
| | Used to set LCD states. bit0 = don't push to LCDs, bit1 = push to LCDs, bit2 = bottom screen backlight off, bit3 = bottom screen backlight on, bit4 = top screen backlight off, bit5 = top screen backlight on | | | Used to set LCD states. bit0 = don't push to LCDs, bit1 = push to LCDs, bit2 = bottom screen backlight off, bit3 = bottom screen backlight on, bit4 = top screen backlight off, bit5 = top screen backlight on |
− | |-
| |
− | | 0x23
| |
− | | 8
| |
− | | ?
| |
| |- | | |- |
| | 0x24 | | | 0x24 |
− | | 8 | + | | s |
| + | | ?? |
| | Watchdog timer. This must be set *before* the timer is triggered, otherwise the old value is used. Value zero disables the watchdog. | | | Watchdog timer. This must be set *before* the timer is triggered, otherwise the old value is used. Value zero disables the watchdog. |
| + | |- |
| + | | 0x27 |
| + | | s |
| + | | ro |
| + | | Raw volume slider state |
| |- | | |- |
| | 0x28 | | | 0x28 |
− | | 8 | + | | s |
| + | | rw |
| | Brightness of the WiFi/Power LED | | | Brightness of the WiFi/Power LED |
| |- | | |- |
| | 0x29 | | | 0x29 |
− | | 8 | + | | dynamic(?) |
− | | ? | + | | rw |
| + | | Repeat register, any byte written here gets repeated indefinitely(?) |
| |- | | |- |
| | 0x2A | | | 0x2A |
− | | 8 | + | | s |
− | | Setting bits 0-7 enables the WiFi LED | + | | rw |
| + | | WiFi LED state, non-0 value turns on the WiFi LED, capped at 0x0F |
| |- | | |- |
| | 0x2B | | | 0x2B |
− | | 8 | + | | s |
− | | Camera LED, setting bit 0 makes the LED blink, setting bit 1 makes the LED stay on | + | | rw |
| + | | Camera LED state, 0, 3, 6-0xF = off, 1 = slowly blinking, 2 = constantly on, 4 = flash once, 5 = delay before changing to 2 |
| |- | | |- |
| | 0x2C | | | 0x2C |
− | | 8 | + | | s |
− | | Setting bits 0-7 turns on the 3D LED on the original 3ds | + | | rw |
| + | | 3D LED state, capped at 0x0F |
| |- | | |- |
| | 0x2D | | | 0x2D |
| | 0x64 | | | 0x64 |
− | | This is used for [[MCURTC:SetInfoLEDPattern|controlling]] the notification LED(see [[MCURTC:SetInfoLEDPatternHeader]] as well), when this register is written. | + | | wo |
| + | | This is used for [[MCURTC:SetInfoLEDPattern|controlling]] the notification LED (see [[MCURTC:SetInfoLEDPatternHeader]] as well), when this register is written. It's possible to write data here with size less than 0x64, and only that portion of the pattern data will get overwritten. Reading from this register only returns zeroes, so it's considered write-only. |
| |- | | |- |
| | 0x2E | | | 0x2E |
− | | 1 | + | | s |
| + | | ro |
| | This [[MCURTC:GetInfoLEDStatus|returns]] the notification LED status when read. | | | This [[MCURTC:GetInfoLEDStatus|returns]] the notification LED status when read. |
| |- | | |- |
| | 0x30 | | | 0x30 |
− | | 8 | + | - 0x37 |
| + | | s |
| + | | rw |
| | RTC time (system clock). 7 bytes are read from this. The upper nibble of each byte encodes 10s (BCD), so each byte is post-processed with (byte & 0xF) + (10 * (byte >> 4)). Byte 0 encodes seconds, byte 1 minutes, byte 2 hours, byte *4* days, byte 5 months and byte 6 years (byte 3 is unused?) | | | RTC time (system clock). 7 bytes are read from this. The upper nibble of each byte encodes 10s (BCD), so each byte is post-processed with (byte & 0xF) + (10 * (byte >> 4)). Byte 0 encodes seconds, byte 1 minutes, byte 2 hours, byte *4* days, byte 5 months and byte 6 years (byte 3 is unused?) |
| |- | | |- |
− | | 0x31 | + | | 0x3D |
− | | 8 | + | | s (2) |
− | | ? | + | | ro |
| + | | RTC tick counter (resets to 0 when the seconds increase) |
| + | It seems to bug out register 0x3E due to having a size of 2 in the shared register pool |
| |- | | |- |
− | | 0x32 | + | | 0x3F |
− | | 8 | + | | s |
− | | ? | + | | rw(?) |
| + | | Peripheral power related? bit0 seems to depower everything, pressing the power key afterwards instantly turns the whole 3DS off |
| |- | | |- |
− | | 0x33 | + | | 0x46 |
− | | 8 | + | | s |
− | | ? | + | | ro |
| + | | Gyro Y(?) axis rotation (0x00 = flat, 0x40 = 3DS standing on right side, 0xBE = 3DS standing on left side) |
| |- | | |- |
− | | 0x34 | + | | 0x48 |
− | | 8 | + | | s |
− | | ? | + | | ro |
| + | | Gyro Z(?) axis rotation (0x00 = flat, 0x40 = 3DS standing horizontally, 0xBE = 3DS base is horizontally upside-down) |
| |- | | |- |
− | | 0x35 | + | | 0x4A |
− | | 8 | + | | s |
− | | ? | + | | ro |
| + | | Gyro X(?) axis rotation (0x00 = 3DS base facing upwards, 0x40 = face-down flat, 0xBE = standing(?) flat) |
| |- | | |- |
− | | 0x36 | + | | 0x4F |
− | | 8 | + | | 6(?) |
− | | ? | + | | ro |
| + | | Unkonwn. Reading past the 6th byte is FF-filled, so register size of 6 is assumed. |
| |- | | |- |
− | | 0x37 | + | | 0x60 |
− | | 8 | + | | 0x100(?) |
− | | ? | + | | ro(?) |
| + | first byte is wo |
| + | | Looping queue register |
| + | Writing to first byte resets the queue position to the nth element |
| + | Reading from this register causes the values to shift up by `readsize-1`(needs confirmation) bytes after returning `readsize-1` bytes from the top of the stack (first byte is read-only, so is always zero) |
| |- | | |- |
− | | 0x38 | + | | 0x61 |
− | | 8 | + | | 0x100(?) |
− | | ? | + | | rw |
| + | | Writing to this register pushes values on top of register 0x60's stack. Reading from this register doesn't advance the stack. |
| + | The first byte is used to store flags for managing FIRM/NS state - bit0 = "WirelessDisabled", bit1 = "SoftwareClosed", bit2 = "PowerOffInitiated", bit4 = "LegacyJumpProhibited". This register survives power-off, but does not seem to be saved to non-volatile storage (does not survive battery pulls). This register doesn't seem to actually control MCU behaviour by itself, it just seems to be used for storing arbitrary data. |
| |- | | |- |
− | | 0x39 | + | | 0x7F |
− | | 8 | + | | 19(?) |
− | | ? | + | | ro |
| + | | Unknown. |
| + | byte 06: battery related? (seems to decrease while charging and increase while discharging) |
| + | byte 10: power LED related? 0 is off, 1 is red |
| + | byte 13: RGB LED red factor |
| + | byte 14: RGB LED green factor |
| + | byte 15: RGB LED blue factor |
| + | byte 17: WiFi LED brightness |
| + | byte 18: raw button states? |
| + | bit0: unset while power button is held, |
| + | bit1: unset while home button is held, |
| + | bit2: unset while Wifi slider is held, |
| + | bit4: unset when charger is plugged in, |
| + | bit6: unset when charging LED is active |
| + | |
| + | this byte is reset to 0 before an svcBreak takes effect |
| |- | | |- |
− | | 0x3A | + | | 0x80 |
− | | 8
| + | - 0xFF |
− | | ?
| + | | s |
− | |-
| + | | invalid (ro) |
− | | 0x3B
| + | | These registers don't exist at all, thus reading them will yield 0xFF |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x3C
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x41
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x43
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x4E
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x50
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x51
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x58
| |
− | | 8
| |
− | | ?
| |
− | |-
| |
− | | 0x60 | |
− | | 8
| |
− | | Offset in u8 array accessed via address 0x61 (written before any read/write below) | |
− | |- | |
− | | 0x61
| |
− | | 0x100
| |
− | | Reads/writes to an MCU u8 array, repeats after 0x100 bytes? The first byte is used to store flags for managing FIRM/NS state - bit0 = "WirelessDisabled", bit1 = "SoftwareClosed", bit2 = "PowerOffInitiated", bit4 = "LegacyJumpProhibited". This register survives power-off, but does not seem to be saved to non-volatile storage (does not survive battery pulls). This register doesn't seem to actually control MCU behaviour by itself, it just seems to be used for storing arbitrary data.
| |
| |} | | |} |
| + | |
| + | Note: the letter "s" in the size field means that the given register is in a "shared register pool", meaning if you read/write with size more than 1 you can read the next `readamount-1` of shared registers. It's possible to corrupt the shared value of a "non-shared" register by writing into a shared register with a size bigger than one. Writing more than 0x100 bytes into a shared register will corrupt all writable registers, including the shared portion of "non-shared" registers. |
| + | |
| + | Non-shared register: it's a register separate from the shared register pool. Messing with these registers will not affect the shared register pool at all. |
| | | |
| == Device 5 & 6 == | | == Device 5 & 6 == |