Gbatek
Gbatek
GBATEK
Gameboy Advance / Nintendo DS Technical Info
Extracted from no$gba version 3.05
-------------------------------------------------------------------------
GBA Reference
-------------
Overview
--> GBA Technical Data
--> GBA Memory Map
--> GBA I/O Map
Hardware Programming
--> GBA LCD Video Controller
--> GBA Sound Controller
--> GBA Timers
--> GBA DMA Transfers
--> GBA Communication Ports
--> GBA Keypad Input
--> GBA Interrupt Control
--> GBA System Control
--> GBA Cartridges
--> GBA Unpredictable Things
Other
--> ARM CPU Reference
--> BIOS Functions
--> External Connectors
NDS Reference
-------------
Overview
--> DS Technical Data
--> DS I/O Maps
--> DS Memory Maps
Hardware Programming
--> DS Memory Control
--> DS Video
--> DS 3D Video
--> DS Sound
--> DS System and Built-in Peripherals
--> DS Cartridges, Encryption, Firmware
--> DS Xboo
--> DS Wireless Communications
Other
--> BIOS Functions
--> ARM CPU Reference
--> External Connectors
DSi Reference
-------------
General Info
--> ARM CPU Reference
--> BIOS Functions
--> External Connectors
3DS Reference
-------------
CPU Reference
-------------
Further Information
--> ARM Pseudo Instructions and Directives
--> ARM CP15 System Control Coprocessor
--> ARM CPU Instruction Cycle Times
--> ARM CPU Versions
--> ARM CPU Data Sheet
About GBATEK
------------
About
--> About this Document
GBA Reference
-------------
Overview
--> GBA Technical Data
--> GBA Memory Map
--> GBA I/O Map
Hardware Programming
--> GBA LCD Video Controller
--> GBA Sound Controller
--> GBA Timers
--> GBA DMA Transfers
--> GBA Communication Ports
--> GBA Keypad Input
--> GBA Interrupt Control
--> GBA System Control
--> GBA Cartridges
--> GBA Unpredictable Things
Other
--> ARM CPU Reference
--> BIOS Functions
--> External Connectors
CPU Modes
ARM Mode ARM7TDMI 32bit RISC CPU, 16.78MHz, 32bit opcodes (GBA)
THUMB Mode ARM7TDMI 32bit RISC CPU, 16.78MHz, 16bit opcodes (GBA)
CGB Mode Z80/8080-style 8bit CPU, 4.2MHz or 8.4MHz (CGB compatibility)
DMG Mode Z80/8080-style 8bit CPU, 4.2MHz (monochrome gameboy compatib.)
Internal Memory
BIOS ROM 16 KBytes
Work RAM 288 KBytes (Fast 32K on-chip, plus Slow 256K on-board)
VRAM 96 KBytes
OAM 1 KByte (128 OBJs 3x16bit, 32 OBJ-Rotation/Scalings 4x16bit)
Palette RAM 1 KByte (256 BG colors, 256 OBJ colors)
Video
Display 240x160 pixels (2.9 inch TFT color LCD display)
BG layers 4 background layers
BG types Tile/map based, or Bitmap based
BG colors 256 colors, or 16 colors/16 palettes, or 32768 colors
OBJ colors 256 colors, or 16 colors/16 palettes
OBJ size 12 types (in range 8x8 up to 64x64 dots)
OBJs/Screen max. 128 OBJs of any size (up to 64x64 dots each)
OBJs/Line max. 128 OBJs of 8x8 dots size (under best circumstances)
Priorities OBJ/OBJ: 0-127, OBJ/BG: 0-3, BG/BG: 0-3
Effects Rotation/Scaling, alpha blending, fade-in/out, mosaic, window
Backlight GBA SP only (optionally by light on/off toggle button)
Sound
Analogue 4 channel CGB compatible (3x square wave, 1x noise)
Digital 2 DMA sound channels
Output Built-in speaker (mono), or headphones socket (stereo)
Controls
Gamepad 4 Direction Keys, 6 Buttons
Communication Ports
Serial Port Various transfer modes, 4-Player Link, Single Game Pak play
External Memory
GBA Game Pak max. 32MB ROM or flash ROM + max 64K SRAM
CGB Game Pak max. 32KB ROM + 8KB SRAM (more memory requires banking)
Case Dimensions
Size (mm) GBA: 145x81x25 - GBA SP: 82x82x24 (closed), 155x82x24 (stretch)
Power Supply
Battery GBA GBA: 2x1.5V DC (AA), Life-time approx. 15 hours
Battery SP GBA SP: Built-in rechargeable Lithium ion battery, 3.7V 600mAh
External GBA: 3.3V DC 350mA - GBA SP: 5.2V DC 320mA
----------------------------------------------------------------------------
Nintendo DS (NDS)
_____________________________________
| _____________________ |
| | | |
| | 3" TFT SCREEN | |
| | 256x192pix 61x46mm | |
| | BACKLIGHT | |
| ::::: | Original NDS | ::::: |
| ::::: |_____________________| ::::: |
_| _ ______ _ |_ <-- gap between screens: 22mm
|L|_______| |________| |_| |_______|R| (equivalent to 90 pixels)
|_______ _____________________ _______|
| PWR | | | |SEL STA|
| _ | | 3" TFT SCREEN | | |
| _| |_ | | 256x192pix 61x46mm | | X |
||_ _|| | BACKLIGHT | | Y A |
| |_| | | TOUCH SCREEN | | B |
| | |_____________________| | |
|_______| NintendoDS |_______|
| MIC LEDS |
|_________________________________________|
VOL SLOT2(GBA) MIC/PHONES
Nintendo DSi XL
As DSi, but bigger case, and bigger 4.2" screens
GBA SP Notes
Deluxe version of the original GBA. With backlight, new folded laptop-style
case, and built-in rechargeable battery. Appears to be 100% compatible with
GBA, there seems to be no way to detect SPs by software.
iQue Notes
iQue is a brand name used by Nintendo in China, iQue GBA and iQue DS are
essentially same as Nintendo GBA and Nintendo DS.
The iQue DS contains a larger firmware chip (the charset additionally contains
about 6700 simplified chinese characters), the bootmenu still allows to select
(only) six languages (japanese has been replaced by chinese). The iQue DS can
play normal international NDS games, plus chinese dedicated games. The latter
ones won't work on normal NDS consoles (that, reportedly simply due to a
firmware-version check contained in chinese dedicated games, aside from that
check, the games should be fully compatible with NDS consoles).
GamePak Memory
Only DMA3 (and the CPU of course) may access GamePak ROM. GamePak SRAM can be
accessed by the CPU only - restricted to bytewise 8bit transfers. The SRAM
region is supposed for as external FLASH backup memory, or for battery-backed
SRAM.
For details about configuration of GamePak Waitstates, see:
--> GBA System Control
Data Format
Even though the ARM CPU itself would allow to select between Little-Endian and
Big-Endian format by using an external circuit, in the GBA no such circuit
exists, and the data format is always Little-Endian. That is, when accessing
16bit or 32bit data in memory, the least significant bits are stored in the
first byte (smallest address), and the most significant bits in the last byte.
(Ie. same as for 80x86 and Z80 CPUs.)
All further addresses at 4XXXXXXh are unused and do not contain mirrors of the
I/O area, with the only exception that 4000800h is repeated each 64K (ie.
mirrored at 4010800h, 4020800h, etc.)
Registers
--> LCD I/O Display Control
--> LCD I/O Interrupts and Status
--> LCD I/O BG Control
--> LCD I/O BG Scrolling
--> LCD I/O BG Rotation/Scaling
--> LCD I/O Window Feature
--> LCD I/O Mosaic Function
--> LCD I/O Color Special Effects
VRAM
--> LCD VRAM Overview
--> LCD VRAM Character Data
--> LCD VRAM BG Screen Data Format (BG Map)
--> LCD VRAM Bitmap BG Modes
Sprites
--> LCD OBJ - Overview
--> LCD OBJ - OAM Attributes
--> LCD OBJ - OAM Rotation/Scaling Parameters
--> LCD OBJ - VRAM Character (Tile) Mapping
Other
--> LCD Color Palettes
--> LCD Dimensions and Timings
LCD I/O Display Control
-----------------------
The table summarizes the facilities of the separate BG modes (video modes).
Mode Rot/Scal Layers Size Tiles Colors Features
0 No 0123 256x256..512x515 1024 16/16..256/1 SFMABP
1 Mixed 012- (BG0,BG1 as above Mode 0, BG2 as below Mode 2)
2 Yes --23 128x128..1024x1024 256 256/1 S-MABP
3 Yes --2- 240x160 1 32768 --MABP
4 Yes --2- 240x160 2 256/1 --MABP
5 Yes --2- 160x128 2 32768 --MABP
Features: S)crolling, F)lip, M)osaic, A)lphaBlending, B)rightness, P)riority.
BG Modes 0-2 are Tile/Map-based. BG Modes 3-5 are Bitmap-based, in these modes
1 or 2 Frames (ie. bitmaps, or 'full screen tiles') exists, if two frames
exist, either one can be displayed, and the other one can be redrawn in
background.
Blanking Bits
Setting Forced Blank (Bit 7) causes the video controller to display white
lines, and all VRAM, Palette RAM, and OAM may be accessed.
"When the internal HV synchronous counter cancels a forced blank during a
display period, the display begins from the beginning, following the display of
two vertical lines." What ?
Setting H-Blank Interval Free (Bit 5) allows to access OAM during H-Blank time
- using this feature reduces the number of sprites that can be displayed per
line.
Frame Selection
In BG Modes 4 and 5 (Bitmap modes), either one of the two bitmaps/frames may be
displayed (Bit 4), allowing the user to update the other (invisible) frame in
background. In BG Mode 3, only one frame exists.
In BG Modes 0-2 (Tile/Map based modes), a similar effect may be gained by
altering the base address(es) of BG Map and/or BG Character data.
In 'Text Modes', the screen size is organized as follows: The screen consists
of one or more 256x256 pixel (32x32 tiles) areas. When Size=0: only 1 area
(SC0), when Size=1 or Size=2: two areas (SC0,SC1 either horizontally or
vertically arranged next to each other), when Size=3: four areas (SC0,SC1 in
upper row, SC2,SC3 in lower row). Whereas SC0 is defined by the normal BG Map
base address (Bit 8-12 of BGxCNT), SC1 uses same address +2K, SC2 address +4K,
SC3 address +6K. When the screen is scrolled it'll always wraparound.
The above BG scrolling registers are exclusively used in Text modes, ie. for
all layers in BG Mode 0, and for the first two layers in BG mode 1.
In other BG modes (Rotation/Scaling and Bitmap modes) above registers are
ignored. Instead, the screen may be scrolled by modifying the BG
Rotation/Scaling Reference Point registers.
The Window Feature may be used to split the screen into four regions. The
BG0-3,OBJ layers and Color Special Effects can be separately enabled or
disabled in each of these regions.
400004Ah - WINOUT - Control of Outside of Windows & Inside of OBJ Window (R/W)
Bit Expl.
0-3 Outside BG0-BG3 Enable Bits (0=No Display, 1=Display)
4 Outside OBJ Enable Bit (0=No Display, 1=Display)
5 Outside Color Special Effect (0=Disable, 1=Enable)
6-7 Not used
8-11 OBJ Window BG0-BG3 Enable Bits (0=No Display, 1=Display)
12 OBJ Window OBJ Enable Bit (0=No Display, 1=Display)
13 OBJ Window Color Special Effect (0=Disable, 1=Enable)
14-15 Not used
Window Priority
In case that more than one window is enabled, and that these windows do
overlap, Window 0 is having highest priority, Window 1 medium, and Obj Window
lowest priority. Outside of Window is having zero priority, it is used for all
dots which are not inside of any window region.
Semi-Transparent OBJs
OBJs that are defined as 'Semi-Transparent' in OAM memory are always selected
as 1st Target (regardless of BLDCNT Bit 4), and are always using Alpha Blending
mode (regardless of BLDCNT Bit 6-7).
The BLDCNT register may be used to perform Brightness effects on the OBJ
(and/or other BG/BD layers). However, if a semi-transparent OBJ pixel does
overlap a 2nd target pixel, then semi-transparency becomes priority, and the
brightness effect will not take place (neither on 1st, nor 2nd target).
Note
Additionally to the above VRAM, the GBA also contains 1 KByte Palette RAM (at
05000000h) and 1 KByte OAM (at 07000000h) which are both used by the display
controller as well.
Each character (tile) consists of 8x8 dots (64 dots in total). The color depth
may be either 4bit or 8bit (see BG0CNT-BG3CNT).
The display background consists of 8x8 dot tiles, the arrangement of these
tiles is specified by the BG Screen Data (BG Map). The separate entries in this
map are as follows:
In BG modes 4,5, one Frame may be displayed (selected by DISPCNT Bit 4), the
other Frame is invisible and may be redrawn in background.
General
Objects (OBJs) are moveable sprites. Up to 128 OBJs (of any size, up to 64x64
dots each) can be displayed per screen, and under best circumstances up to 128
OBJs (of small 8x8 dots size) can be displayed per horizontal display line.
OBJ Attributes
There are 128 entries in OAM for each OBJ0-OBJ127. Each entry consists of 6
bytes (three 16bit Attributes). Attributes for OBJ0 are located at 07000000,
for OBJ1 at 07000008, OBJ2 at 07000010, and so on.
As you can see, there are blank spaces at 07000006, 0700000E, 07000016, etc. -
these 16bit values are used for OBJ Rotation/Scaling (as described in the next
chapter) - they are not directly related to the separate OBJs.
Notes:
OBJ Mode
The OBJ Mode may be Normal, Semi-Transparent, or OBJ Window.
Semi-Transparent means that the OBJ is used as 'Alpha Blending 1st Target'
(regardless of BLDCNT register, for details see chapter about Color Special
Effects).
OBJ Window means that the OBJ is not displayed, instead, dots with non-zero
color are used as mask for the OBJ Window, see DISPCNT and WINOUT for details.
1. When using the 256 Colors/1 Palette mode, only each second tile may be used,
the lower bit of the tile number should be zero (in 2-dimensional mapping mode,
the bit is completely ignored).
2. When using BG Mode 3-5 (Bitmap Modes), only tile numbers 512-1023 may be
used. That is because lower 16K of OBJ memory are used for BG. Attempts to use
tiles 0-511 are ignored (not displayed).
Priority
In case that the 'Priority relative to BG' is the same than the priority of one
of the background layers, then the OBJ becomes higher priority and is displayed
on top of that BG layer.
Caution: Take care not to mess up BG Priority and OBJ priority. For example,
the following would cause garbage to be displayed:
OBJ No. 0 with Priority relative to BG=1 ;hi OBJ prio, lo BG prio
OBJ No. 1 with Priority relative to BG=0 ;lo OBJ prio, hi BG prio
That is, OBJ0 is always having priority above OBJ1-127, so assigning a lower BG
Priority to OBJ0 than for OBJ1-127 would be a bad idea.
As described in the previous chapter, there are blank spaces between each of
the 128 OBJ Attribute Fields in OAM memory. These 128 16bit gaps are used to
store OBJ Rotation/Scaling Parameters.
Location of Rotation/Scaling Parameters in OAM
Four 16bit parameters (PA,PB,PC,PD) are required to define a complete group of
Rotation/Scaling data. These are spread across OAM as such:
1st Group - PA=07000006, PB=0700000E, PC=07000016, PD=0700001E
2nd Group - PA=07000026, PB=0700002E, PC=07000036, PD=0700003E
etc.
By using all blank space (128 x 16bit), up to 32 of these groups (4 x 16bit
each) can be defined in OAM.
Each OBJ tile consists of 8x8 dots, however, bigger OBJs can be displayed by
combining several 8x8 tiles. The horizontal and vertical size for each OBJ may
be separately defined in OAM, possible H/V sizes are 8,16,32,64 dots - allowing
'square' OBJs to be used (such like 8x8, 16x16, etc) as well as 'rectangular'
OBJs (such like 8x32, 64x16, etc.)
When displaying an OBJ that contains of more than one 8x8 tile, one of the
following two mapping modes can be used. In either case, the tile number of the
upperleft tile must be specified in OAM memory.
Transparent Colors
Color 0 of all BG and OBJ palettes is transparent. Even though palettes are
described as 16 (256) color palettes, only 15 (255) colors are actually
visible.
Backdrop Color
Color 0 of BG Palette 0 is used as backdrop color. This color is displayed if
an area of the screen is not covered by any non-transparent BG or OBJ dots.
Color Definitions
Each color occupies two bytes (same as for 32768 color BG modes):
Bit Expl.
0-4 Red Intensity (0-31)
5-9 Green Intensity (0-31)
10-14 Blue Intensity (0-31)
15 Not used
Intensities
Under normal circumstances (light source/viewing angle), the intensities 0-14
are practically all black, and only intensities 15-31 are resulting in visible
medium..bright colors.
Note: The intensity problem appears in the 8bit CGB "compatibility" mode
either. The original CGB display produced the opposite effect: Intensities 0-14
resulted in dark..medium colors, and intensities 15-31 resulted in bright
colors. Any "medium" colors of CGB games will appear invisible/black on GBA
hardware, and only very bright colors will be visible.
Horizontal Dimensions
The drawing time for each dot is 4 CPU cycles.
Visible 240 dots, 57.221 us, 960 cycles - 78% of h-time
H-Blanking 68 dots, 16.212 us, 272 cycles - 22% of h-time
Total 308 dots, 73.433 us, 1232 cycles - ca. 13.620 kHz
VRAM and Palette RAM may be accessed during H-Blanking. OAM can accessed only
if "H-Blank Interval Free" bit in DISPCNT register is set.
Vertical Dimensions
Visible (*) 160 lines, 11.749 ms, 197120 cycles - 70% of v-time
V-Blanking 68 lines, 4.994 ms, 83776 cycles - 30% of v-time
Total 228 lines, 16.743 ms, 280896 cycles - ca. 59.737 Hz
All VRAM, OAM, and Palette RAM may be accessed during V-Blanking.
Note that no H-Blank interrupts are generated within V-Blank period.
System Clock
The system clock is 16.78MHz (16*1024*1024 Hz), one cycle is thus approx.
59.59ns.
(*) Even though vertical screen size is 160 lines, the upper 8 lines are not
<really> visible, these lines are covered by a shadow when holding the GBA
orientated towards a light source, the lines are effectively black - and should
not be used to display important information.
Interlace
The LCD display is using some sort of interlace in which even scanlines are
dimmed in each second frame, and odd scanlines are dimmed in each other frame
(it does always render ALL lines in ALL frames, but half of them are dimmed).
The effect can be seen when displaying some horizontal lines in each second
frame, and hiding them in each other frame: the hardware will randomly show the
lines in dimmed or non-dimmed form (depending on whether the test was started
in an even or odd frame).
Unknown if it's possible to determine the even/off frame state by software (or
possibly to reset the hardware to this or that state by software).
Note: The NDS is applying some sort of frameskip to GBA games, about every 3
seconds there will by a missing (or maybe: inserted) frame, ie. a GBA game that
is updating the display in sync with GBA interlace will get offsync on NDS
consoles.
The GBA supplies four 'analogue' sound channels for Tone and Noise (mostly
compatible to CGB sound), as well as two 'digital' sound channels (which can be
used to replay 8bit DMA sample data).
The GBA includes only a single (mono) speaker built-in, each channel may be
output to either left and/or right channels by using the external line-out
connector (for stereo headphones, etc).
This sound channel works exactly as channel 1, except that it doesn't have a
Tone Envelope/Sweep Register.
This channel can be used to output digital sound, the length of the sample
buffer (Wave RAM) can be either 32 or 64 digits (4bit samples). This sound
channel can be also used to output normal tones when initializing the Wave RAM
by a square wave. This channel doesn't have a volume envelope register.
In the GBA, two Wave Patterns exists (each 32 x 4bits), either one may be
played (as selected in NR30 register), the other bank may be accessed by the
users. After all 32 samples have been played, output of the same bank (or other
bank, as specified in NR30) will be automatically restarted.
This channel is used to output white noise. This is done by randomly switching
the amplitude between high and low at a given frequency. Depending on the
frequency the noise will appear 'harder' or 'softer'.
The GBA contains two DMA sound channels (A and B), each allowing to replay
digital sound (signed 8bit data, ie. -128..+127). Data can be transferred from
INTERNAL memory (not sure if EXTERNAL memory works also ?) to FIFO by using DMA
channel 1 or 2, the sample rate is generated by using one of the Timers.
The GBA sound controller is mostly the same than that of older monochrome
gameboy and CGB. The following changes have been done:
GBA Timers
----------
Overview
The GBA includes four DMA channels, the highest priority is assigned to DMA0,
followed by DMA1, DMA2, and DMA3. DMA Channels with lower priority are paused
until channels with higher priority have completed.
The CPU is paused when DMA transfers are active, however, the CPU is operating
during the periods when Sound/Blanking DMA transfers are paused.
When accessing OAM (7000000h) or OBJ VRAM (6010000h) by HBlank Timing, then the
"H-Blank Interval Free" bit in DISPCNT register must be set.
Transfer End
The DMA Enable flag (Bit 15) is automatically cleared upon completion of the
transfer. The user may also clear this bit manually in order to stop the
transfer (obviously this is possible for Sound/Blanking DMAs only, in all other
cases the CPU is stopped until the transfer completes by itself).
Transfer Rate/Timing
Except for the first data unit, all units are transferred by sequential reads
and writes. For n data units, the DMA transfer time is:
2N+2(n-1)S+xI
Of which, 1N+(n-1)S are read cycles, and the other 1N+(n-1)S are write cycles,
actual number of cycles depends on the waitstates and bus-width of the source
and destination areas (as described in CPU Instruction Cycle Times chapter).
Internal time for DMA processing is 2I (normally), or 4I (if both source and
destination are in gamepak memory area).
The GBAs Serial Port may be used in various different communication modes.
Normal mode may exchange data between two GBAs (or to transfer data from master
GBA to several slave GBAs in one-way direction).
Multi-player mode may exchange data between up to four GBAs. UART mode works
much like a RS232 interface. JOY Bus mode uses a standardized Nintendo
protocol. And General Purpose mode allows to mis-use the 'serial' port as
bi-directional 4bit parallel port.
Note: The Nintendo DS does not include a Serial Port.
Initialization
First, initialize RCNT register. Second, set mode/clock bits in SIOCNT with
startbit cleared. For master: select internal clock, and (in most cases)
specify 256KHz as transfer rate. For slave: select external clock, the local
transfer rate selection is then ignored, as the transfer rate is supplied by
the remote GBA (or other computer, which might supply custom transfer rates).
Third, set the startbit in SIOCNT with mode/clock bits unchanged.
Cable Protocol
During inactive transfer, the shift clock (SC) is high. The transmit (SO) and
receive (SI) data lines may be manually controlled as described above.
When master sends SC=LOW, each master and slave must output the next outgoing
data bit to SO. When master sends SC=HIGH, each master and slave must read out
the opponents data bit from SI. This is repeated for each of the 8 or 32 bits,
and when completed SC will be kept high again.
Transfer Rates
Either 256KHz or 2MHz rates can be selected for SC, so max 32KBytes (256Kbit)
or 128KBytes (2Mbit) can be transferred per second. However, the software must
process each 8bit or 32bit of transmitted data separately, so the actual
transfer rate will be reduced by the time spent on handling each data unit.
Only 256KHz provides stable results in most cases (such like when linking
between two GBAs). The 2MHz rate is intended for special expansion hardware
(with very short wires) only.
Initialization
- Initialize RCNT Bit 14-15 and SIOCNT Bit 12-13 to select Multi-Player mode.
- Read SIOCNT Bit 3 to verify that all GBAs are in Multi-Player mode.
- Read SIOCNT Bit 2 to detect whether this is the Parent/Master unit.
Transfer Protocol
Beginning
- The masters SI pin is always LOW.
- When all GBAs are in Multiplayer mode (ready) SD is HIGH.
- When master starts the transfer, it sets SC=LOW, slaves receive Busy bit.
Step A
- ID Bits in master unit are set to 0.
- Master outputs Startbit (LOW), 16bit Data, Stopbit (HIGH) through SD.
- This data is written to SIOMULTI0 of all GBAs (including master).
- Master forwards LOW from its SO to 1st childs SI.
- Transfer ends if next child does not output data after certain time.
Step B
- ID Bits in 1st child unit are set to 1.
- 1st Child outputs Startbit (LOW), 16bit Data, Stopbit (HIGH) through SD.
- This data is written to SIOMULTI1 of all GBAs (including 1st child).
- 1st child forwards LOW from its SO to 2nd childs SI.
- Transfer ends if next child does not output data after certain time.
Step C
- ID Bits in 2nd child unit are set to 2.
- 2nd Child outputs Startbit (LOW), 16bit Data, Stopbit (HIGH) through SD.
- This data is written to SIOMULTI2 of all GBAs (including 2nd child).
- 2nd child forwards LOW from its SO to 3rd childs SI.
- Transfer ends if next child does not output data after certain time.
Step D
- ID Bits in 3rd child unit are set to 3.
- 3rd Child outputs Startbit (LOW), 16bit Data, Stopbit (HIGH) through SD.
- This data is written to SIOMULTI3 of all GBAs (including 3rd child).
- Transfer ends (this was the last child).
Transfer end
- Master sets SC=HIGH, all GBAs set SO=HIGH.
- The Start/Busy bits of all GBAs are automatically cleared.
- Interrupts are requested in all GBAs (as far as enabled).
Error Bit
This bit is set when a slave did not receive SI=LOW even though SC=LOW
signalized a transfer (this might happen when connecting more than 4 GBAs, or
when the previous child is not connected). Also, the bit is set when a Stopbit
wasn't HIGH.
The error bit may be undefined during active transfer - read only after
transfer completion (the transfer continues and completes as normal even if
errors have occurred for some or all GBAs).
Don't know: The bit is automatically reset/initialized with each transfer, or
must be manually reset?
Transmission Time
The transmission time depends on the selected Baud rate. And on the amount of
Bits (16 data bits plus start/stop bits for each GBA), delays between data for
each GBA, plus final timeout (if less than 4 GBAs). That is, depending on the
number of connected GBAs:
GBAs Bits Delays Timeout
1 18 None Yes
2 36 1 Yes
3 54 2 Yes
4 72 3 None
(The average Delay and Timeout periods are unknown?)
Above is not counting the additional CPU time that must be spent on initiating
and processing each transfer.
This mode works much like a RS232 port, however, the voltages are unknown,
probably 0/3V rather than +/-12V ?. SI and SO are data lines (with crossed
wires), SC and SD signalize Clear to Send (with crossed wires also, which
requires special cable when linking between two GBAs ?)
Error Flag
The error flag is set when a bad stop bit has been received (stop bit must be
0), when a parity error has occurred (if enabled), or when new data has been
completely received while the receive data register (or receive FIFO) is
already full.
The error flag is automatically reset when reading from SIOCNT register.
This communication mode uses Nintendo's standardized JOY Bus protocol. When
using this communication mode, the GBA is always operated as SLAVE!
Below are the four possible commands which can be received by the GBA. Note
that the GBA (slave) cannot send any commands itself, all it can do is to read
incoming data, and to provide 'reply' data which may (or may not) be read out
by the master unit.
In this mode, the SIO is 'misused' as a 4bit bi-directional parallel port, each
of the SI,SO,SC,SD pins may be directly controlled, each can be separately
declared as input (with internal pull-up) or as output signal.
4000134h - RCNT (R) - SIO Mode, usage in GENERAL-PURPOSE Mode (R/W)
Interrupts can be requested when SI changes from HIGH to LOW, as General
Purpose mode does not require a serial shift clock, this interrupt may be
produced even when the GBA is in Stop (low power standby) state.
Bit Expl.
0 SC Data Bit (0=Low, 1=High)
1 SD Data Bit (0=Low, 1=High)
2 SI Data Bit (0=Low, 1=High)
3 SO Data Bit (0=Low, 1=High)
4 SC Direction (0=Input, 1=Output)
5 SD Direction (0=Input, 1=Output)
6 SI Direction (0=Input, 1=Output, but see below)
7 SO Direction (0=Input, 1=Output)
8 SI Interrupt Enable (0=Disable, 1=Enable)
9-13 Not used
14 Must be "0" for General-Purpose Mode
15 Must be "1" for General-Purpose or JOYBUS Mode
SI should be always used as Input to avoid problems with other hardware which
does not expect data to be output there.
SIOCNT
Bit 0 1 2 3 4 5 6 7 8 9 10 11
Normal Master Rate SI/In SO/Out - - - Start - - - -
Multi Baud Baud SI/In SD/In ID# Err Start - - - -
UART Baud Baud CTS Parity S R Err Bits FIFO Parity Send Recv
Wireless Commands
Cmd Para Reply Name
10h - - Hello (send immediately after login)
11h - 1 Good/Bad response to cmd 16h ?
12h
13h - 1
14h
15h
16h 6 - Introduce (send game/user name)
17h 1 - Config (send after Hello) (eg. param=003C0420h or 003C043Ch)
18h
19h
1Ah
1Bh
1Ch - -
1Dh - NN Get Directory? (receive list of game/user names?)
1Eh - NN Get Directory? (receive list of game/user names?)
1Fh 1 - Select Game for Download (send 16bit Game_ID)
20h - 1
21h - 1 Good/Bad response to cmd 1Fh ?
22h
23h
24h - -
25h ;use EXT clock!
26h - -
27h - - Begin Download ? ;use EXT clock!
28h
29h
2Ah
2Bh
2Ch
2Dh
2Eh
2Fh
30h 1 -
31h
32h
33h
34h
35h ;use EXT clock!
36h
37h ;use EXT clock!
38h
39h
3Ah
3Bh
3Ch
3Dh - - Bye (return to language select)
3Eh
3Fh
Special Response 996601EEh for error or so? (only at software side?)
Main Chipset
U1 32pin Freescale MC13190 (2.4 GHz ISM band transceiver)
U2 48pin Freescale CT3000 or CT3001 (depending on adapter version)
X3 2pin 9.5MHz crystal
The MC13190 is a Short-Range, Low-Power 2.4 GHz ISM band transceiver.
The processor is Motorola's 32-bit M-Core RISC engine. (?) MCT3000 (?)
See also: http://www.eetimes.com/document.asp?doc_id=1271943
Major Differences
Sticker "N/A" vs "Grossosteim P/AGB-A-WA-EUR-2 E3"
PCB-markings "19-C046-03, A-1, 3204" vs "19-C046-04, A-7, 3104"
U1 "CT3000, XAB0425" vs "CT3001, XAC0445"
Transistors One transistor (Q70) vs Two transistors (both nameless)
U70/U72 U70 "AAG" (6pin) vs U72 "BMs" (4pin)
Purpose of the changes is unknown (either older/newer revisions, or different
regions with different FCC regulations).
Early GBA prototypes have been intended to include a built-in IR port for
sending and receiving IR signals. Among others, this port could have been used
to communicate with other GBAs, or older CGB models, or TV Remote Controls,
etc.
Keep in mind that the IR signal may be interrupted by whatever objects moved
between sender and receiver - the IR port isn't recommended for programs that
require realtime data exchange (such like action games).
Transmission Notes
When transmitting an IR signal, note that it'd be not a good idea to keep the
LED turned On for a very long period (such like sending a 1 second
synchronization pulse). The recipient's circuit would treat such a long signal
as "normal IR pollution which is in the air" after a while, and thus ignore the
signal.
Reception Notes
Received data is internally latched. Latched data may be read out by setting
both READ and AMP bits.
Note: Provided that you don't want to receive your own IR signal, be sure to
set Bit 0 to zero before attempting to receive data.
Power-consumption
After using the IR port, be sure to reset the register to zero in order to
reduce battery power consumption.
Notes
In 8bit gameboy compatibility mode, L and R Buttons are used to toggle the
screen size between normal 160x144 pixels and stretched 240x144 pixels.
The GBA SP is additionally having a * Button used to toggle the backlight on
and off (controlled by separate hardware logic, there's no way to detect or
change the current backlight state by software).
NOTES:
The GBA forcefully uses non-sequential timing at the beginning of each
128K-block of gamepak ROM, eg. "LDMIA [801fff8h],r0-r7" will have
non-sequential timing at 8020000h.
The PHI Terminal output (PHI Pin of Gamepak Bus) should be disabled.
Prefetch Enable
For GamePak ROM opcodes, prefetch may occur in two situations:
1) opcodes with internal cycles (I) which do not change R15, shift/rotate
register-by-register, load opcodes (ldr,ldm,pop,swp), multiply opcodes
2) opcodes that load/store memory (ldr,str,ldm,stm,etc.)
ROM
--> GBA Cartridge Header
--> GBA Cartridge ROM
Backup Media
Aside from ROM, cartridges may also include one of the following backup medias,
used to store game positions, highscore tables, options, or other data.
--> GBA Cart Backup IDs
--> GBA Cart Backup SRAM/FRAM
--> GBA Cart Backup EEPROM
--> GBA Cart Backup Flash ROM
--> GBA Cart Backup DACS
Add-Ons
--> GBA Cart I/O Port (GPIO)
--> GBA Cart Real-Time Clock (RTC)
--> GBA Cart Solar Sensor
--> GBA Cart Tilt Sensor
--> GBA Cart Gyro Sensor
--> GBA Cart Rumble
--> GBA Cart e-Reader
--> GBA Cart Unknown Devices
--> GBA Cart Protections
Other Accessoires
--> GBA Flashcards
--> GBA Cheat Devices
The first 192 bytes at 8000000h-80000BFh in ROM are used as cartridge header.
The same header is also used for Multiboot images at 2000000h-20000BFh (plus
some additional multiboot entries at 20000C0h and up).
Header Overview
Address Bytes Expl.
000h 4 ROM Entry Point (32bit ARM branch opcode, eg. "B rom_start")
004h 156 Nintendo Logo (compressed bitmap, required!)
0A0h 12 Game Title (uppercase ascii, max 12 characters)
0ACh 4 Game Code (uppercase ascii, 4 characters)
0B0h 2 Maker Code (uppercase ascii, 2 characters)
0B2h 1 Fixed value (must be 96h, required!)
0B3h 1 Main unit code (00h for current GBA models)
0B4h 1 Device type (usually 00h) (bit7=DACS/debug related)
0B5h 7 Reserved Area (should be zero filled)
0BCh 1 Software version (usually 00h)
0BDh 1 Complement check (header checksum, required!)
0BEh 2 Reserved Area (should be zero filled)
--- Additional Multiboot Header Entries ---
0C0h 4 RAM Entry Point (32bit ARM branch opcode, eg. "B ram_start")
0C4h 1 Boot mode (init as 00h - BIOS overwrites this value!)
0C5h 1 Slave ID Number (init as 00h - BIOS overwrites this value!)
0C6h 26 Not used (seems to be unused)
0E0h 4 JOYBUS Entry Pt. (32bit ARM branch opcode, eg. "B joy_start")
Note: With all entry points, the CPU is initially set into system mode.
Below required for Multiboot/slave programs only. For Multiboot, the above 192
bytes are required to be transferred as header-block (loaded to
2000000h-20000BFh), and some additional header-information must be located at
the beginning of the actual program/data-block (loaded to 20000C0h and up).
This extended header consists of Multiboot Entry point(s) which must be set up
correctly, and of two reserved bytes which are overwritten by the boot
procedure:
ROM Size
The games F-ZERO and Super Mario Advance use ROMs of 4 MBytes each. Zelda uses
8 MBytes. Not sure if other sizes are manufactured.
ROM Waitstates
The GBA starts the cartridge with 4,2 waitstates (N,S) and prefetch disabled.
The program may change these settings by writing to WAITCNT, the games F-ZERO
and Super Mario Advance use 3,1 waitstates (N,S) each, with prefetch enabled.
Third-party flashcards are reportedly running unstable with these settings.
Also, prefetch and shorter waitstates are allowing to read more data and
opcodes from ROM is less time, the downside is that it increases the power
consumption.
ROM Chip
Because of how 24bit addresses are squeezed through the Gampak bus, the
cartridge must include a circuit that latches the lower 16 address bits on
non-sequential access, and that increments these bits on sequential access.
Nintendo includes this circuit directly in the ROM chip.
Also, the ROM must have 16bit data bus (or a circuit which converts two 8bit
data units into one 16bit unit - by not exceeding the waitstate timings).
Nintendo didn't include a backup-type entry in the ROM header, however, the
required type can be detected by ID strings in the ROM-image. Nintendo's tools
are automatically inserting these strings (as part of their library headers).
When using other tools, you may insert ID strings by hand.
ID Strings
The ID string must be located at a word-aligned memory location, the string
length should be a multiple of 4 bytes (padded with zero's).
EEPROM_Vnnn EEPROM 512 bytes or 8 Kbytes (4Kbit or 64Kbit)
SRAM_Vnnn SRAM 32 Kbytes (256Kbit)
FLASH_Vnnn FLASH 64 Kbytes (512Kbit) (ID used in older files)
FLASH512_Vnnn FLASH 64 Kbytes (512Kbit) (ID used in newer files)
FLASH1M_Vnnn FLASH 128 Kbytes (1Mbit)
For Nintendo's tools, "nnn" is a 3-digit library version number. When using
other tools, best keep it set to "nnn" rather than inserting numeric digits.
Notes
No$gba does auto-detect most backup types, even without ID strings, except for
128K FLASH (without ID "FLASH1M_Vnnn", the FLASH size defaults to 64K).
Ideally, for faster detection, the ID should be put into the first some bytes
of the ROM-image (ie. somewhere right after the ROM header).
Databus Width
The SRAM/FRAM databus is restricted to 8 bits, it should be accessed by LDRB,
LDRSB, and STRB opcodes only.
Recommended Workaround
Enable the Gamepak Interrupt (it'll most likely get triggered when removing the
cartridge), and hang-up the GBA in an endless loop when your interrupt handler
senses a Gamepak IRQ. For obvious reason, your interrupt handler should be
located in WRAM, ie. not in the (removed) ROM cartridge. The handler should
process Gamepak IRQs at highest priority. Periods during which interrupts are
disabled should be kept as short as possible, if necessary allow nested
interrupts.
SRAM vs FRAM
FRAM (Ferroelectric RAM) is a newer technology, used in newer GBA carts, unlike
SRAM (Static RAM), it doesn't require a battery to hold the data. At software
side, it is accessed exactly like SRAM, ie. unlike EEPROM/FLASH, it doesn't
require any Write/Erase commands/delays.
Note
In SRAM/FRAM cartridges, the /REQ pin (Pin 31 of Gamepak bus) should be a
little bit shorter as than the other pins; when removing the cartridge, this
causes the gamepak IRQ signal to get triggered before the other pins are
disconnected.
9853 - EEPROM 512 Bytes (0200h) (4Kbit) (eg. used by Super Mario Advance)
9854 - EEPROM 8 KBytes (2000h) (64Kbit) (eg. used by Boktai)
Lifetime: 100,000 writes per address
Read Data
Read a stream of 68 bits from EEPROM by using DMA,
then decipher the received data as follows:
4 bits - ignore these
64 bits - data (conventionally MSB first)
Using DMA
Transferring a bitstreams to/from the EEPROM must be done via DMA3 (manual
transfers via LDRH/STRH won't work; probably because they don't keep /CS=LOW
and A23=HIGH throughout the transfer).
For using DMA, a buffer in memory must be used (that buffer would be typically
allocated temporarily on stack, one halfword for each bit, bit1-15 of the
halfwords are don't care, only bit0 is used).
The buffer must be transfered as a whole to/from EEPROM by using DMA3 (DMA0-2
can't access external memory), use 16bit transfer mode, both source and
destination address incrementing (ie. DMA3CNT=80000000h+length).
DMA channels of higher priority should be disabled during the transfer (ie.
H/V-Blank or Sound FIFO DMAs). And, of course any interrupts that might mess
with DMA registers should be disabled.
Pin-Outs
The EEPROM chips are having only 8 pins, these are connected, Pin 1..8, to
ROMCS, RD, WR, AD0, GND, GND, A23, VDD of the GamePak bus. Carts with 32MB ROM
must have A7..A22 logically ANDed with A23.
Notes
There seems to be no autodection mechanism, so that a hardcoded bus width must
be used.
Device Types
Nintendo puts different FLASH chips in commercial game cartridges. Developers
should thus detect & support all chip types. For Atmel chips it'd be
recommended to simulate 4K sectors by software, though reportedly Nintendo
doesn't use Atmel chips in newer games anymore. Also mind that different
timings should not disturb compatibility and performance.
ID Name Size Sectors AverageTimings Timeouts/ms Waits
D4BFh SST 64K 16x4K 20us?,?,? 10, 40, 200 3,2
1CC2h Macronix 64K 16x4K ?,?,? 10,2000,2000 8,3
1B32h Panasonic 64K 16x4K ?,?,? 10, 500, 500 4,2
3D1Fh Atmel 64K 512x128 ?,?,? ...40.., 40 8,8
1362h Sanyo 128K ? ?,?,? ? ? ? ?
09C2h Macronix 128K ? ?,?,? ? ? ? ?
Identification Codes MSB=Device Type, LSB=Manufacturer.
Size in bytes, and numbers of sectors * sector size in bytes.
Average medium Write, Erase Sector, Erase Chips timings are unknown?
Timeouts in milliseconds for Write, Erase Sector, Erase Chips.
Waitstates for Writes, and Reads in clock cycles.
FLASH Waitstates
Use 8 clk waitstates for initial detection (WAITCNT Bits 0,1 both set). After
detection of certain device types smaller wait values may be used for
write/erase, and even smaller wait values for raw reading, see Device Types
table.
In practice, games seem to use smaller values only for write/erase (even though
those operations are slow anyways), whilst raw reads are always done at 8 clk
waits (even though reads could actually benefit slightly from smaller wait
values).
Note
FLASH (64Kbytes) is used by the game Sonic Advance, and possibly others.
Parts of DACS memory is used to store the debugging exception handlers (entry
point/size defined in cartridge header), the remaining memory could be used to
store game positions or other data. The address space is the upper end of the
32MB ROM area, the memory can be read directly by the CPU, including for
ability to execute program code in this area.
The I/O registers are mapped to a 6-byte region in the ROM-area at 80000C4h,
the 6-byte region should be zero-filled in the ROM-image. In Boktai, the size
of the zero-filled region is 0E0h bytes - that probably due to an incorrect
definition (the additional bytes do not contain any extra ports, nor mirrors of
the ports in the 6-byte region). Observe that ROM-bus writes are limited to
16bit/32bit access (STRB opcodes are ignored; that, only in DS mode?).
80000C6h - I/O Port Direction (for above Data Port) (selectable W or R/W)
bit0-3 Direction for Data Port Bits 0..3 (0=In, 1=Out)
bit4-15 not used (0)
80000C8h - I/O Port Control (selectable W or R/W)
bit0 Register 80000C4h..80000C8h Control (0=Write-Only, 1=Read/Write)
bit1-15 not used (0)
In write-only mode, reads return 00h (or possible other data, if the rom
contains non-zero data at that location).
Connection Examples
GPIO | Boktai | Wario
Bit Pin | RTC SOL | GYR RBL
-----------+---------+---------
0 ROM.1 | SCK CLK | RES -
1 ROM.2 | SIO RST | CLK -
2 ROM.21 | CS - | DTA -
3 ROM.22 | - FLG | - MOT
-----------+---------+---------
IRQ ROM.43 | IRQ - | - -
Aside from the I/O Port, the ROM-chip also includes an inverter (used for
inverting the RTC /IRQ signal), and some sort of an (unused) address decoder
output (which appears to be equal or related to A23 signal) (ie. reacting on
ROM A23, or SRAM D7, which share the same pin on GBA slot).
Control Register
Bit Dir Expl.
0 - Not used
1 R/W IRQ duty/hold related?
2 - Not used
3 R/W Per Minute IRQ (30s duty) (0=Disable, 1=Enable)
4 - Not used
5 R/W Unknown?
6 R/W 12/24-hour Mode (0=12h, 1=24h) (usually 1)
7 R Power-Off (auto cleared on read) (0=Normal, 1=Failure, time lost)
Setting after Battery-Shortcut is 82h. Setting after Force-Reset is 00h.
Unused bits seem to be always zero, but might be read-only or write-only?
RTC Games
Boktai series ;which/how many titles?
P-Letter series ;which/how many titles?
Rockman EXE 4.5 Real Operation
Uses a Photo Diode as Solar Sensor (used in Boktai, allowing to defeat vampires
when the cartridge is exposed to sunlight). The cartridge comes in transparent
case, and it's slightly longer than normal carts, so the sensor reaches out of
the cartridge slot. According to the manual, the sensor works only with
sunlight, but actually it works with any strong light source (eg. a 100 Watt
bulb at 1-2 centimeters distance). The sensor is accessed via 4bit I/O port
(only 3bits used), which is contained in the ROM-chip.
--> GBA Cart I/O Port (GPIO)
A/D Conversion
The cartridge uses a self-made digital-ramp converter A/D converter, which is
(maybe) better than measuring a capacitor charge-up time, and/or less expensive
than a real ADC-chip:
It contains a 74LV4040 12bit binary counter (clocked by CPU via the I/O port),
of which only the lower 8bit are used, which are passed to a resistor
ladder-type D/A converter, which is generating a linear increasing voltage,
which is passed to a TLV272 voltage comparator, which is passing a signal to
the I/O port when the counter voltage becomes greater than the sensor voltage.
Example Code
strh 0001h,[80000c8h] ;-enable R/W mode
strh 0007h,[80000c6h] ;-init I/O direction
strh 0002h,[80000c4h] ;-reset counter to zero (high=reset) (I/O bit0)
strh 0000h,[80000c4h] ;-clear reset (low=normal)
mov r0,0 ;-initial level
@@lop:
strh 0001h,[80000c4h] ;-clock high ;\increase counter (I/O bit1)
strh 0000h,[80000c4h] ;-clock low ;/
ldrh r1,[80000c4h] ;-read port (I/O bit3)
tst r1,08h ;\
addeq r0,1 ; loop until voltage match (exit with r0=00h..FFh),
tsteq r0,100h ; or until failure/timeout (exit with r0=100h)
beq @@lop ;/
The results vary depending on the clock rate used. In above example, ensure
that IRQs or DMAs do not interrupt the function. Alternately, use a super-slow
clock rate (eg. like 666Hz used in Boktai) so that additional small IRQ/DMA
delays have little effect on the overall timing. Results should be somewhat:
E8h total darkness (including LED light, or daylight on rainy days)
Dxh close to a 100 Watt Bulb
5xh reaches max level in boktai's solar gauge
00h close to a tactical nuclear bomb dropped on your city
The exact values may change from cartridge to cartridge, so it'd be recommened
to include a darkness calibration function, prompting the user to cover the
sensor for a moment (in Boktai, access Options by pressing left/right in title
screen) (alternately, auto-calibration could theoretically memorize the darkest
in-game level ever seen).
Yoshi-Type (X/Y-Axis)
All of the registers are one byte wide, mapped into the top "half" of the SRAM
memory range.
E008000h (W) Write 55h to start sampling
E008100h (W) Write AAh to start sampling
E008200h (R) Lower 8 bits of X axis
E008300h (R) Upper 4 bits of X axis, and Bit7: ADC Status (0=Busy, 1=Ready)
E008400h (R) Lower 8 bits of Y axis
E008500h (R) Upper 4 bits of Y axis
You must set SRAM wait control to 8 clocks to access it correctly.
You must also set the cartridge PHI terminal to 4 MHz to make it work.
Sampling routine (typically executed once a frame during VBlank):
wait until [E008300h].Bit7=1 or until timeout ;wait ready
x = ([E008300h] AND 0Fh)*100h + [E008200h] ;get x
y = ([E008500h] AND 0Fh)*100h + [E008400h] ;get y
[E008000h]=55h, [E008100h]=AAh ;start next conversion
Example values (may vary on different carts and on temperature, etc):
X ranged between 0x2AF to 0x477, center at 0x392. Huh?
Y ranged between 0x2C3 to 0x480, center at 0x3A0. Huh?
Thanks to Flubba for Yoshi-Type information.
Unknown if the Yoshi-Type sensors are sensing rotation, or orientation, or
motion, or something else? In case of rotation, rotation around X-axis would
result in motion in Y-direction, so not too sure whether X and Y have which
meaning?
Most probably, the sensors are measuring (both) static acceleration (gravity),
and dynamic acceleration (eg. shaking the device left/right).
The X/Y values are likely to be mirrored depending on using a back-loading
cartridge slot (original GBA), or front-loading cartridge slot (newer GBA SP,
and NDS, and NDS-Lite).
Wario-Type (Z-Axis)
Uses a single-axis sensor, which senses rotation around the Z-axis. The sensor
is connected to an analogue-in, serial-out ADC chip, which is accessed via
lower 3 bits of the GPIO,
--> GBA Cart I/O Port (GPIO)
The four I/O Lines are connected like so,
GPIO.Bit0 (W) Start Conversion
GPIO.Bit1 (W) Serial Clock
GPIO.Bit2 (R) Serial Data
GPIO.Bit3 (W) Used for Rumble (not gyro related)
There should be at least <three sequential 32bit ARM opcodes executed in WS0
region> between the STRH opcodes which toggle the CLK signal. Wario uses
WAITCNT=45B7h (SRAM=8clks, WS0/WS1/WS2=3,1clks, Prefetch=On, PHI=Off).
The data stream consists of: 4 dummy bits (usually zero), followed by 12 data
bits, followed by endless unused bits (usually zero).
read_gyro:
mov r1,8000000h ;-cartridge base address
mov r0,01h ;\enable R/W access
strh r0,[r1,0c8h] ;/
mov r0,0bh ;\init direction (gpio2=input, others=output)
strh r0,[r1,0c6h] ;/
ldrh r2,[r1,0c4h] ;-get current state (for keeping gpio3=rumble)
orr r2,3 ;\
strh r2,[r1,0c4h] ;gpio0=1 ; start ADC conversion
bic r2,1 ;
strh r2,[r1,0c4h] ;gpio0=0 ;/
mov r0,00010000h ;stop-bit ;\
bic r2,2 ;
@@lop: ;
ldrh r3,[r1,0c4h] ;get gpio2=data ; read 16 bits
strh r2,[r1,0c4h] ;gpio1=0=clk=low ; (4 dummy bits, plus 12 data bits)
movs r3,r3,lsr 3 ;gpio2 to cy=data ;
adcs r0,r0,r0 ;merge data, cy=done;
orr r3,r2,2 ;set bit1 and delay ;
strh r3,[r1,0c4h] ;gpio1=1=clk=high ;
bcc @@lop ;/
bic r0,0f000h ;-strip upper 4 dummy bits (isolate 12bit adc)
bx lr
Example values (may vary on different carts, battery charge, temperature, etc):
354h rotated in anti-clockwise direction (shock-speed)
64Dh rotated in anti-clockwise direction (normal fast)
6A3h rotated in anti-clockwise direction (slow)
6C0h no rotation (stopped)
6DAh rotation in clockwise direction (slow)
73Ah rotation in clockwise direction (normal fast)
9E3h rotation in clockwise direction (shock-speed)
For detection, values 000h and FFFh would indicate that there's no sensor.
The Z-axis always points into same direction; no matter of frontloading or
backloading cartridge slots.
Thanks to Momo Vampire for contributing a Wario cartridge.
X/Y/Z-Axes
X-Axis and Y-Axis are meant to be following the screens X and Y coordinates, so
the Z-Axis would point into the screens depth direction.
DSi Cameras
DSi consoles can mis-use the built-in cameras as Gyro sensor (as done by the
System Flaw DSi game).
GBA Rumble Carts are containing a small motor, which is causing some vibration
when/while it is switched on (that, unlike DS Rumble, which must be repeatedly
toggled on/off).
DS Rumble Pak
Additionally, there's a Rumble Pak for the NDS, which connects to the GBA slot,
so it can be used also for GBA games (provided that the game doesn't require
the GBA slot, eg. GBA multiboot games).
--> DS Cart Rumble Pak
Gamecube Rumble
Moreover, GBA games that are running on a Gameboy Player are having access to
the Rumble function of Gamecube joypads.
--> GBA Gameboy Player
________________
| ShortStrip |
|L L|
|o Center o|
|n Region n|
|g g|
| may contain |
|S pictures, S|
|t instructions t|
|r etc. r|
|i i|
|p p|
|___ShortStrip___|
The e-Reader is a large GBA cartridge (about as big as the GBA console), with
built-in dotcode scanning hardware. Dotcodes are tiny strips of black and white
pixels printed on the edges of cardboard cards. The cards have to be pulled
through a slot on the e-Reader, which is giving it a feeling like using a
magnet card reader. The binary data on the dotcodes contains small games,
either in native GBA code (ARM/THUMB), or in software emulated 8bit Z80 or
NES/Famicom (6502) code.
Region/Version
There are 3 different e-Reader's: Japanese/Original, Japanese/Plus, and
Non-Japanese. The Original version has only 64K FLASH, no Link Port, and
reportedly supports only Z80 code, but no NES/GBA code. The Plus and
Non-Japanese versions should be almost identical, except that they reject cards
from the wrong region, and that the title strings aren't ASCII in Japan, the
Plus version should be backwards compatible to the Original one.
The Problem
Nintendo's current programmers are definetly unable to squeeze a Pac-Man style
game into less than 4MBytes. Their solution has been: MORE memory. That is,
they've put a whopping 8MByte BIOS ROM into the e-Reader, which contains the
User Interface, and software emulation for running some of their 20 years old
8bit NES and Game&Watch titles, which do fit on a few dotcode strips.
Flowchart for accessing Serial Registers via E00FFB0h (looks like I2C bus)
Delay:
Wait circa 2.5us, Ret
SioBegin:
SioDta=1, SioDir=Out, SioClk=1, Delay, SioDta=0, Delay, SioClk=0, Ret
SioEnd:
SioDta=0, SioDir=Out, Delay, SioClk=1, Delay, SioDta=1, Ret
SioRead1bit: ;out: databit
SioDir=In, Delay, SioClk=1, Delay, databit=SioDta, SioClk=0, Ret
SioWrite1bit: ;in: databit
SioDta=databit, SioDir=Out, Delay, SioClk=1, Delay, SioClk=0, Ret
SioReadByte: ;in: endflag - out: data
for i=7 to 0, data.bit<i>=SioRead1bit, next i, SioWrite1bit(endflag), Ret
SioWriteByte: ;in: data - out: errorflag
for i=7 to 0, Delay(huh/why?), SioWrite1bit(data.bit<i>), next i
errorflag=SioRead1bit, SioDir=Out(huh/why?), Ret
SioWriteRegisters: ;in: index, len, buffer
SioBegin
SioWriteByte(22h) ;command (set_index) (and write_data)
SioWriteByte(index) ;index
for i=0 to len-1
SioWriteByte(buffer[i]) ;write data (and auto-increment index)
next
SioEnd
ret
SioReadRegisters: ;in: index, len - out: buffer
SioBegin
SioWriteByte(22h) ;command (set_index) (without any write_data here)
SioWriteByte(index) ;index
SioBegin
SioWriteByte(23h) ;command (read_data) (using above index)
for i=0 to len-1
if i=len-1 then endflag=1 else endflag=0
buffer[i]=SioReadByte(endflag) ;read data (and auto-increment index)
next
SioEnd
Ret
Caution: Accessing the SIO registers appears highly unstable, and seems to
require error handling with retries. Not sure what is causing that problem,
possibly the registers cannot be accessed during camera-data-scans...?
WAITCNT
The e-Reader BIOS uses WAITCNT [4000204h]=5803h when accessing the PGA, that
is, gamepak 16.78MHz phi output (bit11-12=3), 8 waits for SRAM region
(bit0-1=3), gamepak prefetch enabled (bit14=1), also sets WS0 to 4,2 waits
(bit2-4=0), and sets WS2 to odd 4,8 waits (bit8-10=0). The WS2 (probably WS0
too) settings are nonsense, and should work with faster timings (the e-Reader
can be accessed in NDS mode, which doesn't support that slow timings).
Address Columns
Each Column consists of 26 dots. From top to bottom: 1 black dot, 8 blank dots,
16 address dots (MSB topmost), and 1 blank dot. The 16bit address values can be
calculated as:
addr[0] = 03FFh
for i = 1 to 53
addr[i] = addr[i-1] xor ((i and (-i)) * 769h)
if (i and 07h)=0 then addr[i] = addr[i] xor (769h)
if (i and 0Fh)=0 then addr[i] = addr[i] xor (769h*2)
if (i and 1Fh)=0 then addr[i] = addr[i] xor (769h*4) xor (769h)
next i
Short strips use addr[1..19], long strips use addr[25..53], left to right.
Block Header
The 18h-byte Block Header is taken from the 1st two bytes (20 dots) of the 1st
0Ch blocks (and is then repeated in the 1st two bytes of further blocks).
00h Unknown (00h)
01h Dotcode type (02h=Short, 03h=Long)
02h Unknown (00h)
03h Address of 1st Block (01h=Short, 19h=Long)
04h Total Fragment Size (40h) ;64 bytes per fragment, of which,
;48 bytes are actual data, the remaining
05h Error-Info Size (10h) ;16 bytes are error-info
06h Unknown (00h)
07h Interleave Value (1Ch=Short, 2Ch=Long)
08h..17h 16 bytes Reed-solomon error correction info for Block Header
Data Order
Data starts with the upper bit of the 5bit value for the upper 4bit of the
first byte, which is located at the leftmost dot of the upper line of the
leftmost block, it does then extend towards rightmost dot of that block, and
does then continue in the next line, until reaching the bottom of the block,
and does then continue in the next block. The 1st two bytes of each block
contain a portion of the Block Header, the remaining 102 bytes in each block
contain data.
Data Size
A long strip consists of 28 blocks (28*104 = 2912 bytes), a short strip of 18
blocks (18*104 = 1872 bytes). Of which, less than 75% can be actually used for
program code, the remaining data contains error correction info, and various
headers. See Data Format for more info.
Interleaved Fragments
The Interleave Value (I) specifies the number of fragments, and does also
specify the step to the next byte inside of a fragment; except that, at the
block boundaries (every 104 bytes), the step is 2 bigger (for skipping the next
two Block Header bytes).
RAW Offset Content
000h..001h 1st 2 bytes of RAW Header
002h 1st byte of 1st fragment
003h 1st byte of 2nd fragment
... ...
002h+I-1 1st byte of last fragment
002h+I 2nd byte of 1st fragment
003h+I 2nd byte of 2nd fragment
... ...
002h+I*2-1 2nd byte of last fragment
... ...
Each fragment consists of 48 actual data bytes, followed by 16 error correction
bytes, followed by 0..2 unused bytes (since I*40h doesn't exactly match
num_blocks*102).
First Strip
Data Header (48 bytes)
Main-Title (17 bytes, or 33 bytes)
Sub-Title(s) (3+18 bytes, or 33 bytes) (for each strip) (optional)
VPK Size (2 byte value, total length of VPK Data in ALL strips)
NULL Value (4 bytes, contained ONLY in 1st strip of GBA strips)
VPK Data (length as defined in VPK Size entry, see above)
Further Strip(s)
Data Header (48 bytes)
Main-Title (17 bytes, or 33 bytes)
Sub-Title(s) (3+18 bytes, or 33 bytes) (for each strip) (optional)
VPK Data (continued from previous strip)
GBA Format
Load Address and Entrypoint are at 2000000h (in ARM state). The 32bit word at
2000008h is eventually destroyed by the e-Reader. Namely,
IF e-Reader is Non-Japanese,
AND [2000008h] is outside of range of 2000000h..20000E3h,
AND only if booted from camera (not when booted from FLASH?),
THEN [2000008h]=[2000008h]-0001610Ch ELSE [2000008h] kept intact
Existing multiboot-able GBA binaries can be converted to e-Reader format by,
Store "B 20000C0h" at 2000000h ;redirect to RAM-entrypoint
Zerofill 2000004h..20000BFh ;erase header (for better compression rate)
Store 01h,01h at 20000C4h ;indicate RAM boot
The GBA code has full access to the GBA hardware, and may additionally use
whatever API functions contained in the e-Reader BIOS. With the incoming LR
register value, "mov r0,N, bx lr" returns to the e-Reader BIOS (with N being
0=Restart, or 2=To_Menu). No idea if it's necessary to preserve portions of RAM
when returning to the e-Reader BIOS?
Caution: Unlike for normal GBA cartridges/multiboot files, the hardware is left
uninitialized when booting dotcodes (among others: sound DMA is active, and
brightness is set to zero), use "mov r0,0feh, swi 010000h" to get the normal
settings.
NES Format
Emulates a NES (Nintendo Entertainment System) console (aka Family Computer).
The visible 240x224 pixel NES/NTSC screen resolution is resampled to 240x160 to
match the smaller vertical resolution of the GBA hardware. So, writing e-Reader
games in NES format will result in blurred screen output. The
screen/sound/joypad is accessed via emulated NES I/O ports, program code is
running on an emulated 6502 8bit CPU, for more info on the NES hardware, see
no$nes debugger specifications, or
http://problemkaputt.de/everynes.htm
The e-Reader's NES emulator supports only 16K PRG ROM, followed by 8K VROM. The
emulation accuracy is very low, barely working with some of Nintendo's own NES
titles; running the no$nes diagnostics program on it has successfully failed on
ALL hardware tests ;-)
The load address for the 16K PRG-ROM is C000h, the 16bit NMI vector at [FFFAh]
is encrypted like so:
for i=17h to 0
for j=07h to 0, nmi = nmi shr 1, if carry then nmi = nmi xor 8646h, next j
nmi = nmi xor (byte[dmca_data+i] shl 8)
next i
dmca_data: db 0,0,'DMCA NINTENDO E-READER'
The 16bit reset vector at [FFFCh] contains:
Bit0-14 Lower bits of Entrypoint (0..7FFFh = Address 8000h..FFFFh)
Bit15 Nametable Mode (0=Vertical Mirroring, 1=Horizontal Mirroring)
reportedly,
(NES limitations, 1 16K program rom + 1-2 8K CHR rom, mapper 0 and 1)
ines mapper 1 would be MMC1, rather than CNROM (ines mapper 3)?
but, there are more or less NONE games that have 16K PRG ROM + 16K VROM?
The L+R Button key-combination allows to reset the NES, however, there seems to
be no way to return to the e-Reader BIOS.
Z80/8080 Format
The e-Reader doesn't support the following Z80 opcodes:
CB [Prefix] E0 RET PO E2 JP PO,nn E4 CALL PO,nn 27 DAA 76 HALT
ED [Prefix] E8 RET PE EA JP PE,nn EC CALL PE,nn D3 OUT (n),A
DD [IX Prefix] F3 DI 08 EX AF,AF' F4 CALL P,nn DB IN A,(n)
FD [IY Prefix] FB EI D9 EXX FC CALL M,nn xx RST 00h..38h
That is leaving not more than six supported Z80 opcodes (DJNZ, JR, JR
c/nc/z/nz), everything else are 8080 opcodes. Custom opcodes are:
76 WAIT A frames, D3 WAIT n frames, and C7/CF RST 0/8 used for API calls.
The load address and entrypoint are at 0100h in the emulated Z80 address space.
The Z80 doesn't have direct access to the GBA hardware, instead
video/sound/joypad are accessed via API functions, invoked via RST 0 and RST 8
opcodes, followed by an 8bit data byte, and with parameters in the Z80 CPU
registers. For example, "ld a,02h, rst 8, db 00h" does return to the e-Reader
BIOS.
The Z80/8080 emulation is incredibly inefficient, written in HLL code,
developed by somebody whom knew nothing about emulation nor about ARM nor about
Z80/8080 processors.
GBA Interface
bx [30075FCh] ;ApiVector ;in: r0=func_no,r1,r2,r3,[sp+0],[sp+4],[sp+8]=params
bx lr ;Exit ;in: r0 (0=Restart, 2=To_Menu)
Wait8bit/Wait16bit
The various Wait opcodes and functions are waiting as many frames as specified.
Many API functions have no effect until the next Wait occurs.
vpk_decompress(src,dest)
collected32bit=80000000h ;initially empty (endflag in bit31)
for i=0 to 3, id[i]=read_bits(8), next i, if id[0..3]<>'vpk0' then error
dest_end=dest+read_bits(32) ;size of decompressed data (of all strips)
method=read_bits(8), if method>1 then error
tree_index=0, load_huffman_tree, disproot=tree_index
tree_index=tree_index+1, load_huffman_tree, lenroot=tree_index
;above stuff is contained only in the first strip. below loop starts at
;current location in first strip, and does then continue in further strips.
decompress_loop:
if read_bits(1)=0 then ;copy one uncompressed data byte,
[dest]=read_bits(8), dest=dest+1 ;does work without huffman trees
else
if disproot=-1 or lenroot=-1 then error ;compression does require trees
disp=read_tree(disproot)
if method=1 ;disp*4 is good for 32bit ARM opcodes
if disp>2 then disp=disp*4-8 else disp=disp+4*read_tree(disproot)-7
len=read_tree(lenroot)
if len=0 or disp<=0 or dest+len-1>dest_end then error ;whoops
for j=1 to len, [dest]=[dest-disp], dest=dest+1, next j
if dest<dest_end then decompress_loop
ret
read_bits(num)
mov data=0
for i=1 to num
shl collected32bit,1 ;move next bit to carry, or set zeroflag if empty
if zeroflag
collected32bit=[src+0]*1000000h+[src+1]*10000h+[src+2]*100h+[src+3]
src=src+4 ;read data in 32bit units, in reversed byte-order
carryflag=1 ;endbit
rcl collected32bit,1 ;move bit31 to carry (and endbit to bit0)
rcl data,1 ;move carry to data
next i
ret(data)
read_tree(root_index)
i=root_index
while node[i].right<>-1 ;loop until reaching data node
if read_bits(1)=1 then i=node[i].right else i=node[i].left
i=node[i].left ;get number of bits
i=read_bits(i) ;read that number of bits
ret(i) ;return that value
load_huffman_tree
stacktop=sp
if read_bits(1)=1 then tree_index=-1, ret ;exit (empty)
node[tree_index].right=-1 ;indicate data node
node[tree_index].left=read_bits(8) ;store data value
if read_bits(1)=1 then ret ;exit (only 1 data node at root)
push tree_index ;save previous (child) node
tree_index=tree_index+1
jmp data_injump
load_loop:
push tree_index ;save previous (child) node
tree_index=tree_index+1
if read_bits(1)=1 then parent_node
data_injump:
node[tree_index].right=-1 ;indicate data node
node[tree_index].left=read_bits(8) ;store data value
jmp load_loop
parent_node:
pop node[tree_index].right ;store 1st child
pop node[tree_index].left ;store 2nd child
if sp<>stacktop then jmp load_loop
if read_bits(1)=0 then error ;end bit (must be 1)
ret
The best values for the huffman trees that I've found are 6,9,12-bit
displacements for method 0 (best for NES/Z80 code), and two less for method 1,
ie. 4,7,10-bit (best for GBA code). And 2,4,10-bit for the length values. The
smallest value in node 0, and the other values in node 10 and 11.
Notes
The decompression works similar to the GBA BIOS'es LZ77 decompression function,
but without using fixed bit-widths of length=4bit and displacement=12bit,
instead, the bit-widths are read from huffman trees (which can also define
fixed bit-widths; if data is located directly in the root node).
Unlike the GBA BIOS'es Huffman decompression function, the trees are starting
with data entries, end are ending with the root entry. The above load function
deciphers the data, and returns the root index.
With the variable bit-widths, the VPK compression rate is quite good, only,
it's a pity that the length/disp values are zero-based, eg. for 2bit and 4bit
lengths, it'd be much better to assign 2bit as 2..5, and 4bit as 6..21.
Non-VPK
The e-Reader additionally supports an alternate decompression function,
indicated by the absence of the "vpk0" ID, which supports compression of
increasing byte-values, which isn't useful for program code.
Bit15 of the VPK Size value seems to disable (de-)compression, the VPK Data
field is then containing plain uncompressed data.
The Error Correction Information that is appended at the end of the Block
Header & Data Fragments consists of standard Reed-Solomon codes, which are also
used for CD/DVD disks, DSL modems, and digital DVB television signals. That
info allows to locate and repair a number of invalid data bytes.
Below code shows how to create and verify error-info (but not how to do the
actual error correction). The dtalen,errlen values should be 18h,10h for the
Block Header, and 40h,10h for Data Fragments; the latter settings might be
possible to get changed to other values though?
append_error_info(data,dtalen,errlen)
reverse_byte_order(data,dtalen)
zerofill_error_bytes(data,errlen)
for i=dtalen-1 to errlen ;loop across data portion
z = rev[ data[i] xor data[errlen-1] ] ;
for j=errlen-1 to 0 ;loop across error-info portion
if j=0 then x=00h else x=data[j-1]
if z<>FFh then
y=gg[j], if y<>FFh then
y=y+z, if y>=FFh then y=y-FFh
x=x xor pow[y]
data[j]=x
next j
next i
invert_error_bytes(data,errlen)
reverse_byte_order(data,dtalen)
verify_error_info(data,dtalen,errlen)
reverse_byte_order(data,dtalen)
invert_error_bytes(data,errlen)
make_rev(data,dtalen)
for i=78h to 78h+errlen-1
x=0, z=0
for j=0 to dtalen-1
y=data[j]
if y<>FFh then
y=y+z, if y>=FFh then y=y-FFh
x=x xor pow[y]
z=z+i, if z>=FFh then z=z-FFh
next j
if x<>0 then error
next i
;(if errors occured, could correct them now)
make_pow(data,dtalen)
invert_error_bytes(data,errlen)
reverse_byte_order(data,dtalen)
make_rev(data,len)
for i=0 to len-1, data[i]=rev[data[i]], next i
make_pow(data,len)
for i=0 to len-1, data[i]=pow[data[i]], next i
invert_error_bytes(data,len)
for i=0 to len-1, data[i]=data[i] xor FFh, next i
zerofill_error_bytes(data,len)
for i=0 to len-1, data[i]=00h, next i
reverse_byte_order(data,len)
for i=0 to (len-1)/2, x=data[i], data[i]=data[len-i], data[len-i]=x, next i
create_pow_and_rev_tables
x=01h, pow[FFh]=00h, rev[00h]=FFh
for i=00h to FEh
pow[i]=x, rev[x]=i, x=x*2, if x>=100h then x=x xor 187h
next i
create_gg_table
gg[0]=pow[78h]
for i=1 to errlen-1
gg[i]=01h
for j=i downto 0
if j=0 then y=00h else y=gg[j-1]
x=gg[j], if x<>00h then
x=rev[x]+78h+i, if x>=FFh then x=x-FFh
y=y xor pow[x]
gg[j]=y
next j
next i
make_rev(gg,errlen)
With above value of 78h, and errlen=10h, gg[00h..0Fh] will be always:
00h,4Bh,EBh,D5h,EFh,4Ch,71h,00h,F4h,00h,71h,4Ch,EFh,D5h,EBh,4Bh
So using a hardcoded table should take up less memory than calculating it.
Notes
The actual error correction should be able to fix up to "errlen" errors at
known locations (eg. data from blocks that haven't been scanned, or whose
5bit-to-4bit conversion had failed due to an invalid 5bit value), or up to
"errlen/2" errors at unknown locations. The corrected data isn't guaranteed to
be correct (even if it looks okay to the "verify" function), so the Data Header
checksums should be checked, too.
More Info
For more info, I've found Reed-Solomon source code from Simon Rockliff, and an
updated version from Robert Morelos-Zaragoza and Hari Thirumoorthy to be
useful. For getting started with that source, some important relationships &
differences are:
pow = alpha_to, but generated as shown above
rev = index_of, dito
b0 = 78h
nn = dtalen
kk = dtalen-errlen
%nn = MOD FFh (for the ereader that isn't MOD dtalen)
-1 = FFh
And, the ereader processes data/errinfo backwards, starting at the last byte.
.RAW Files
Contains the "raw" information from the BMP format, that is, 2-byte block
header, 102-byte data, 2-byte block header, 102-byte data, etc. The data
portion is interleaved, and includes the full 48-byte data header, titles, vpk
compressed data, error-info, and unused bytes. RAW files are excluding Address
Bars, Sync Marks, and 4bit-to-5bit encoding.
Each RAW file contains one or more strip(s), so the RAW filesize is either
18*104 bytes (short strip), or 28*104 bytes (long strip), or a multiple thereof
(if it contains more than one strip) (although multi-strip games are often
stored in separate files for each strip; named file1.raw, file2.raw, etc).
.BIN Files
Filesize should be I*30h, with I=1Ch for short strips, and I=2Ch for long
strips, or a multiple thereof (if it contains more than one strip). Each strip
consists of the 48-byte Data Header, followed by title(s), and vpk compressed
data. Unlike .RAW files, .BIN files aren't interleaved, and do not contain
Block Headers, nor error-info, nor unused bytes (in last block). The files do
contain padding bytes to match a full strip-size of I*30h.
Caution: Older .BIN files have been using a size-reduced 12-byte header (taken
from entries 0Dh, 0Ch, 10h-11h, 26h-2Dh of the 48-byte Data Header; in that
order), that files have never contained more than one strip per file, so the
filesize should be exactly I*30h-36, the size-reduced header doesn't contain a
Primary Type entry, so it's everyone's bet which Card Type is to be used (hint:
the 12-byte headers were based on the assumption that Primary Type would be
always 01h on Short Strips, and 02h on Long Strips).
.SAV Files
Contains a copy of the e-Reader's 128Kbyte FLASH memory. With the saved
e-Reader application being located in the 2nd 64K-bank, the data consists of a
header with title and gba/nes/z80 format info, followed by the vpk compressed
data. The FLASH memory does also contain e-Reader calibration settings, the
remaining 100Kbytes are typically FFh-filled.
GBA Flashcards
--------------
Flashcards are re-writable cartridges using FLASH memory, allowing to test even
multiboot-incompatible GBA software on real hardware, providing a good
development environment when used in combination with a reasonable software
debugger.
The carts can be written to from external tools, or directly from GBA programs.
Below are pseudo code flowcharts for detect, erase, and write operations.
All flash reads/writes are meant to be 16bit (ldrh/strh) memory accesses.
detect_flashcard:
configure_flashcard(9E2468Ah,9413h) ;unlock flash advance cards
turbo=1, send_command(8000000h,90h) ;enter ID mode (both chips, if any)
maker=[8000000h], device=[8000000h+2]
IF maker=device THEN device=[8000000h+4] ELSE turbo=0
flashcard_read_mode ;exit ID mode
search (maker+device*10000h) in device_list
total/erase/write_block_size = list_entry SHL turbo
flashcard_erase(dest,len):
FOR x=1 to len/erase_block_size
send_command(dest,20h) ;erase sector command
send_command(dest,D0h) ;confirm erase sector
dest=dest+erase_block_size
IF wait_busy=okay THEN NEXT x
enter_read_mode ;exit erase/status mode
flashcard_write(src,dest,len):
siz=write_block_size
FOR x=1 to len/siz
IF siz=2 THEN send_command(dest,10h) ;write halfword command
IF siz>2 THEN send_command(dest,E8h) ;write to buffer command
IF siz>2 THEN send_command(dest,16-1) ;buffer size 16 halfwords (per chip)
FOR y=1 TO siz/2
[dest]=[src], dest=dest+2, src=src+2 ;write data to buffer
NEXT y
IF siz>2 THEN send_command(dest,D0h) ;confirm write to buffer
IF wait_busy=okay THEN NEXT x
enter_read_mode ;exit write/status mode
send_command(adr,val):
[adr]=val
IF turbo THEN [adr+2]=val
enter_read_mode:
send_command(8000000h,FFh) ;exit status mode
send_command(8000000h,FFh) ;again maybe more stable (as in jeff's source)
flashcard_wait_busy:
start=time
REPEAT
stat=[8000000h] XOR 80h
IF turbo THEN stat=stat OR ([8000000h+2] XOR 80h)
IF (stat AND 7Fh)>0 THEN error
IF (stat AND 80h)=0 THEN ready
IF time-start>5secs THEN timeout
UNTIL ready OR error OR timeout
IF error OR timeout THEN send_command(8000000h,50h) ;clear status
configure_flashcard(adr,val): ;required for Flash Advance cards only
[930ECA8h]=5354h
[802468Ah]=1234h, repeated 500 times
[800ECA8h]=5354h
[802468Ah]=5354h
[802468Ah]=5678h, repeated 500 times
[930ECA8h]=5354h
[802468Ah]=5354h
[8ECA800h]=5678h
[80268A0h]=1234h
[802468Ah]=ABCDh, repeated 500 times
[930ECA8h]=5354h
[adr]=val
Notes
All flashcards should work at 4,2 waitstates (power on default), most
commercial games change waits to 3,1 which may work unstable with some/older FA
flashcards. Intel FLASH specified to have a lifetime of 100,000 erases, and
average block erase time 1 second (up to 5 second in worst cases).
Aside from the main FLASH memory, Flash Advance (FA) (aka Visoly) cards
additionally contain battery buffered SRAM backup, and FLASH backup, and in
some cases also EEPROM backup.
Turbo FA cards are containing two chips interlaced (at odd/even halfword
addresses), allowing to write/erase both chips simultaneously, resulting in
twice as fast programming time.
Standard Nintendo flash carts have to be modified before you can actually write
to them. This is done by removing resistor R7 and putting it at empty location
R8.
Mind that write/erase/detect modes output status information in ROM area, so
that in that modes all GBA program code (and any interrupt handlers) must be
executed in WRAM, not in ROM.
Thanks to Jeff Frohwein for his FAQ and CARTLIB sample in FLGBA at devrs.com
Alignment
Addresses for 16bit or 32bit values should be properly aligned.
Codebreaker Codes
0000xxxx 000y Enable Code 1 - Game ID
1aaaaaaa 000z Enable Code 2 - Hook Address
2aaaaaaa yyyy [aaaaaaa]=[aaaaaaa] OR yyyy
3aaaaaaa 00yy [aaaaaaa]=yy
4aaaaaaa yyyy [aaaaaaa+0..(cccc-1)*ssss]=yyyy+0..(cccc-1)*ssss
iiiicccc ssss parameters for above code
5aaaaaaa cccc [aaaaaaa+0..(cccc-1)]=11,22,33,44,etc.
11223344 5566 parameter bytes 1..6 for above code (example)
77880000 0000 parameter bytes 7..8 for above code (padded with zero)
6aaaaaaa yyyy [aaaaaaa]=[aaaaaaa] AND yyyy
7aaaaaaa yyyy IF [aaaaaaa]=yyyy THEN (next code)
8aaaaaaa yyyy [aaaaaaa]=yyyy
9xyyxxxx xxxx Enable Code 0 - Encrypt all following codes (optional)
Aaaaaaaa yyyy IF [aaaaaaa]<>yyyy THEN (next code)
Baaaaaaa yyyy IF [aaaaaaa]>yyyy THEN (next code) (signed comparison)
Caaaaaaa yyyy IF [aaaaaaa]<yyyy THEN (next code) (signed comparison)
D0000020 yyyy IF [joypad] AND yyyy = 0 THEN (next code)
Eaaaaaaa yyyy [aaaaaaa]=[aaaaaaa]+yyyy
Faaaaaaa yyyy IF [aaaaaaa] AND yyyy THEN (next code)
Codebreaker Encryption
codebreaker_change_encryption:
Encryption can be (optionally) activated by code "9xyyxxxx xxxx",
for i=0 to 2Fh, swaplist[i]=i, next i
randomizer = 1111h xor byte[code+4] ;LSB value
for i=0 to 4Fh
exchange swaplist[random MOD 30h] with swaplist[random MOD 30h]
next i
halfword[seedlist+0] = halfword[code+0] ;LSW address
randomizer = 4EFAD1C3h
for i=0 to byte[code+3]-91h, randomizer=random, next i ;MSB address
word[seedlist+2]=random, halfword[seedlist+6]=random
randomizer = F254h xor byte[code+5] ;MSB value
for i=0 to byte[code+5]-01h, randomizer=random, next i ;MSB value
word[seedlist+8]=random, halfword[seedlist+12]=random
;note: byte[code+2] = don't care
ret
The above random function works like so:
randomizer=randomizer*41C64E6Dh+3039h, x=(randomizer SHL 14 AND C0000000h)
randomizer=randomizer*41C64E6Dh+3039h, x=(randomizer SHR 1 AND 3FFF8000h)+x
randomizer=randomizer*41C64E6Dh+3039h, x=(randomizer SHR 16 AND 00007FFFh)+x
return(x)
Once when encryption is activated, all following codes are decrypted like so:
for i=2Fh to 0
j=swaplist[i]
bitno1=(i AND 7), index1=xlatlist[i/8]
bitno2=(j AND 7), index2=xlatlist[j/8]
exchange [code+index1].bitno1 with [code+index2].bitno2
next i
word[code+0] = word[code+0] xor word[seedlist+8]
i = (byte[code+3]*1010000h + byte[code+0]*100h + byte[code+5])
i = (halfword[code+1]*10001h) xor (word[seedlist+2]) xor i
i = (byte[seedlist+0]*1010101h) xor (byte[seedlist+1]*1000000h) xor i
j = (byte[code+5] + (byte[code+0] xor byte[code+4])*100h)
j = (byte[seedlist+0]*101h) xor halfword[seedlist+6] xor j
word[code+0] = i, halfword[code+4] = j
The above xlatlist is fixed: xlatlist[0..5] = 3,2,1,0,5,4
Gameshark RAW Codes (These codes must be encrypted before using them)
0aaaaaaa 000000xx [aaaaaaa]=xx
1aaaaaaa 0000xxxx [aaaaaaa]=xxxx
2aaaaaaa xxxxxxxx [aaaaaaa]=xxxxxxxx
3000cccc xxxxxxxx write xxxxxxxx to (cccc-1) addresses (list in next codes)
aaaaaaaa aaaaaaaa parameter for above code, containing two addresses each
aaaaaaaa 00000000 last parameter for above, zero-padded if only one address
60aaaaaa y000xxxx [8000000h+aaaaaa*2]=xxxx (ROM Patch)
8a1aaaaa 000000xx IF GS_Button_Down THEN [a0aaaaa]=xx
8a2aaaaa 0000xxxx IF GS_Button_Down THEN [a0aaaaa]=xxxx
80F00000 0000xxxx IF GS_Button_Down THEN slowdown xxxx * ? cycles per hook
Daaaaaaa 0000xxxx IF [aaaaaaa]=xxxx THEN (next code)
E0zzxxxx 0aaaaaaa IF [aaaaaaa]=xxxx THEN (next 'zz' codes)
Faaaaaaa 00000x0y Enable Code - Hook Routine
xxxxxxxx 001DC0DE Enable Code - Game Code ID (value at [0ACh] in cartridge)
DEADFACE 0000xxyy Change Encryption Seeds
ROM Patch
This type allows GSA to intercept ROM reads and returns the value xxxx.
y=0 wait for the code handler to enable the patch
y=1 patch is enabled before the game starts
y=2 unknown ?
Note: V1/V2 hardware can only have up to 1 user-defined rom patch max. V3 can
have up to 4. Some enable code types can shorten the amount of user-defined rom
patches available.
Gameshark Encryption
A=Left half, and V=Right half of code.
FOR I=1 TO 32
A=A + (V*16+S0) XOR (V+I*9E3779B9h) XOR (V/32+S1)
V=V + (A*16+S2) XOR (A+I*9E3779B9h) XOR (A/32+S3)
NEXT I
Upon startup, the initial encryption seeds are:
S0=09F4FBBDh S1=9681884Ah S2=352027E9h S3=F3DEE5A7h
Upon DEADFACE 0000xxyy, the S0..S3 seeds are changed like so:
FOR y=0 TO 3
FOR x=0 TO 3
z = T1[(xx+x) AND FFh] + T2[(yy+y) AND FFh]
Sy = Sy*100h + (z AND FFh)
NEXT x
NEXT y
All calculations truncated to unsigned 32bit integer values.
T1 and T2 are translation tables contained in the gameshark cartridge.
Warning: There is a bug on the real AR (v2 upgraded to v3, and maybe on real
v3) with the 32bit Increment Slide code. You HAVE to add a code (best choice is
80000000 00000000 : add 0 to value at address 0) right after it, else the AR
will erase the 2 last 8 digits lines of the 32 Bits Inc. Slide code when you
enter it !!!
Final Notes
The 'turn off all codes' makes an infinite loop (that can't be broken, unless
the condition becomes True). - How? By Interrupt? Huh?
ROM Patch1 works on real V3 and, on V1/V2 upgraded to V3.
ROM Patch2,3,4 work on real V3 hardware only.
Always... Codes
For the "Always..." codes:
- XXXXXXXX can be any authorised address except 00000000 (eg. use 02000000).
- ZZZZZZZZ can be anything.
- The "y" in the code data must be in the [1-7] range (which means not 0).
typ=y,sub=0,siz=3 Always skip next line.
typ=y,sub=1,siz=3 Always skip next 2 lines.
typ=y,sub=2,siz=3 Always Stops executing all the codes below.
typ=y,sub=3,siz=3 Always turn off all codes.
The Gameboy Player is an "adapter" for the Gamecube console. It's basicly is a
GBA in a black box without LCD screen and without buttons, connected to an
expansion port at the bottom of the Gamecube. The Gamecube is then capturing
the GBA video output (and passing it to the television set), and in the other
direction, passing the Gamecube joypad input to the GBA inputs.
Palette
Knowing Nintendo, they've probably not reproduced the blurred GBA colors (?),
so the games won't look as desired on the TV screen. Unless the game does
detect the Gameboy Player, and adjust the colors accordingly by software.
Rumble
The only known existing special function is the joypad rumble function,
controlled by sending data through the serial port (the normal GBA port, even
though it also has the connectors).
The Game Boy Player added a rumble feature to certain Game Boy Advance games
when played with a GameCube controller. Those games included:
Drill Dozer (supports BOTH handheld-rumble and GBP-rumble?)
Mario & Luigi: Superstar Saga
Pokemon Pinball: Ruby & Sapphire
Shikakui Atama wo Marukusuru Advance: Kokugo Sansu Rika Shakai
Shikakui Atama wo Marukusuru Advance: Kanji Keisan
Summon Night Craft Sword Monogatari: Hajimari no Ishi
Super Mario Advance 4: Super Mario Bros. 3
The GBP can also use some of the extra controllers for the GC like the Bongas
from Donkey Konga.
The logo requires at least 256 colors, it doesn't matter if you use a tiled
screen mode or a bitmapped one, the logo can be ripped from either
"Pokemon Pinball" or "Super Mario Advance 4".
Rumble
After detecting/unlocking the Gameboy Player, init RCNT and SIOCNT to 32bit
normal mode, external clock, SO=high, with IRQ enabled, and set the transfer
start bit. You should then receive the following sequence (about once per
frame), and your serial IRQ handler should send responses accordingly:
Receive Response
0000494E 494EB6B1
xxxx494E 494EB6B1
B6B1494E 544EB6B1
B6B1544E 544EABB1
ABB1544E 4E45ABB1
ABB14E45 4E45B1BA
B1BA4E45 4F44B1BA
B1BA4F44 4F44B0BB
B0BB4F44 8000B0BB
B0BB8002 10000010
10000010 20000013
20000013 40000004
30000003 40000004
30000003 40000004
30000003 40000004
30000003 400000yy
30000003 40000004
The first part of the transfer just contains the string "NINTENDO" split into
16bit fragments, and bitwise inversions thereof (eg. 494Eh="NI", and B6B1h=NOT
494Eh). In the second part, <yy> should be 04h=RumbleOff, or 26h=RumbleOn.
Note
If it's having a similar range of functions as the 8bit Super Gameboy, then the
Gameboy Player might be also able to access analogue joypad input, and to
access other features of the Gamecube hardware, up to possibly executing code
on the Gamecube CPU...?
Forward
Most of the below is caused by 'traces' from previous operations which have
used the databus. No promises that the results are stable on all current or
future GBA models, and/or under all temperature and interference circumstances.
Also, below specifies 32bit data accesses only. When reading units less than
32bit, data is rotated depending on the alignment of the originally specified
address, and 8bit or 16bit are then isolated from the 32bit value as usually.
Memory Mirrors
Most internal memory is mirrored across the whole 24bit/16MB address space in
which it is located: Slow On-board RAM at 2XXXXXX, Fast On-Chip RAM at
3XXXXXXh, Palette RAM at 5XXXXXXh, VRAM at 6XXXXXXh, and OAM at 7XXXXXXh. Even
though VRAM is sized 96K (64K+32K), it is repeated in steps of 128K
(64K+32K+32K, the two 32K blocks itself being mirrors of each other).
BIOS ROM, Normal ROM Cartridges, and I/O area are NOT mirrored, the only
exception is the undocumented I/O port at 4000800h (repeated each 64K).
The 64K SRAM area is mirrored across the whole 32MB area at E000000h-FFFFFFFh,
also, inside of the 64K SRAM field, 32K SRAM chips are repeated twice.
NDS Reference
-------------
Overview
--> DS Technical Data
--> DS I/O Maps
--> DS Memory Maps
Hardware Programming
--> DS Memory Control
--> DS Video
--> DS 3D Video
--> DS Sound
--> DS System and Built-in Peripherals
--> DS Cartridges, Encryption, Firmware
--> DS Xboo
--> DS Wireless Communications
Other
--> BIOS Functions
--> ARM CPU Reference
--> External Connectors
DS Technical Data
-----------------
Processors
1x ARM946E-S 32bit RISC CPU, 66MHz (NDS9 video) (not used in GBA mode)
1x ARM7TDMI 32bit RISC CPU, 33MHz (NDS7 sound) (16MHz in GBA mode)
Internal Memory
4096KB Main RAM (8192KB in debug version)
96KB WRAM (64K mapped to NDS7, plus 32K mappable to NDS7 or NDS9)
60KB TCM/Cache (TCM: 16K Data, 32K Code) (Cache: 4K Data, 8K Code)
656KB VRAM (allocateable as BG/OBJ/2D/3D/Palette/Texture/WRAM memory)
4KB OAM/PAL (2K OBJ Attribute Memory, 2K Standard Palette RAM)
248KB Internal 3D Memory (104K Polygon RAM, 144K Vertex RAM)
?KB Matrix Stack, 48 scanline cache
8KB Wifi RAM
256KB Firmware FLASH (512KB in iQue variant, with chinese charset)
36KB BIOS ROM (4K NDS9, 16K NDS7, 16K GBA)
Video
2x LCD screens (each 256x192 pixel, 3 inch, 18bit color depth, backlight)
2x 2D video engines (extended variants of the GBA's video controller)
1x 3D video engine (can be assigned to upper or lower screen)
1x video capture (for effects, or for forwarding 3D to the 2nd 2D engine)
Sound
16 sound channels (16x PCM8/PCM16/IMA-ADPCM, 6x PSG-Wave, 2x PSG-Noise)
2 sound capture units (for echo effects, etc.)
Output: Two built-in stereo speakers, and headphones socket
Input: One built-in microphone, and microphone socket
Controls
Gamepad 4 Direction Keys, 8 Buttons
Touchscreen (on lower LCD screen)
Communication Ports
Wifi IEEE802.11b
Specials
Built-in Real Time Clock
Power Managment Device
Hardware divide and square root functions
CP15 System Control Coprocessor (cache, tcm, pu, bist, etc.)
External Memory
NDS Slot (for NDS games) (encrypted 8bit data bus, and serial 1bit bus)
GBA Slot (for NDS expansions, or for GBA games) (but not for DMG/CGB games)
Manufactured Cartridges
ROM: 16MB, 32MB, or 64MB
EEPROM/FLASH/FRAM: 0.5KB, 8KB, 64KB, 256KB, or 512KB
Can be booted from
NDS Cartridge (NDS mode)
Firmware FLASH (NDS mode) (eg. by patching firmware via ds-xboo cable)
Wifi (NDS mode)
GBA Cartridge (GBA mode) (without DMG/CGB support) (without SIO support)
Power Supply
Built-in rechargeable Lithium ion battery, 3.7V 1000mAh (DS-Lite)
External Supply: 5.2V DC
NDS-Lite
Slightly smaller than the original NDS, coming in a more decently elegant case.
The LCDs are much more colorful (and thus not backwards compatible with any
older NDS or GBA games), and the LCDs support wider viewing angles. Slightly
different power managment device (with selectable backlight brightness, new
external power source flag, lost audio amplifier mute flag). Slightly different
Wifi controller (different chip ID, different dirt effects when accessing
invalid wifi ports and unused wifi memory regions, different behaviour on
GAPDISP registers, RF/BB chips replaced by a single chip). Slightly different
touch screen controller (with new unused input, and slightly different
powerdown bits).
Notice
NDS9 means the ARM9 processor and its memory and I/O ports in NDS mode
NDS7 means the ARM7 processor and its memory and I/O ports in NDS mode
GBA means the ARM7 processor and its memory and I/O ports in GBA mode
DS I/O Maps
-----------
DS Memory Maps
--------------
Shared-RAM
Even though Shared WRAM begins at 3000000h, programs are commonly using mirrors
at 37F8000h (both ARM9 and ARM7). At the ARM7-side, this allows to use 32K
Shared WRAM and 64K ARM7-WRAM as a continous 96K RAM block.
DS Memory Control
-----------------
Memory Control
--> DS Memory Control - Cache and TCM
--> DS Memory Control - Cartridges and Main RAM
--> DS Memory Control - WRAM
--> DS Memory Control - VRAM
--> DS Memory Control - BIOS
Memory Access Time
--> DS Memory Timings
Cache
Data Cache 4KB, Instruction Cache 8KB
4-way set associative method
Cache line 8 words (32 bytes)
Read-allocate method (ie. writes are not allocating cache lines)
Round-robin and Pseudo-random replacement algorithms selectable
Cache Lockdown, Instruction Prefetch, Data Preload
Data write-through and write-back modes selectable
Notes
In Plain-CPU modes, VRAM can be accessed only by the CPU (and by the Capture
Unit, and by VRAM Display mode). In "Plain <ARM7>-CPU Access" mode, the VRAM
blocks are allocated as Work RAM to the NDS7 CPU.
In BG/OBJ VRAM modes, VRAM can be accessed by the CPU at specified addresses,
and by the display controller.
In Extended Palette and Texture Image/Palette modes, VRAM is not mapped to CPU
address space, and can be accessed only by the display controller (so, to
initialize or change the memory, it should be temporarily switched to Plain-CPU
mode).
All VRAM (and Palette, and OAM) can be written to only in 16bit and 32bit units
(STRH, STR opcodes), 8bit writes are ignored (by STRB opcode). The only
exception is "Plain <ARM7>-CPU Access" mode: The ARM7 CPU can use STRB to write
to VRAM (the reason for this special feature is that, in GBA mode, two 128K
VRAM blocks are used to emulate the GBA's 256K Work RAM).
The double-protected region contains the exception vectors, some bytes of code,
and the cartridge KEY1 encryption seed (about 4KBytes). As far as I know, it is
impossible to unlock the memory once when it is locked, however, with some
trickery, it is possible execute code before it gets locked. Also, the two
THUMB opcodes at 05ECh can be used to read all memory at 0..3FFFh,
05ECh ldrb r3,[r3,12h] ;requires incoming r3=src-12h
05EEh pop r2,r4,r6,r7,r15 ;requires dummy values & THUMB retadr on stack
Additionally most BIOS functions (eg. CpuSet), include a software-based
protection which rejects source addresses in the BIOS area (the only exception
is GetCRC16, though it still cannot bypass the BIOSPROT setting).
Note
The NDS9 BIOS doesn't include any software or hardware based read protection.
DS Memory Timings
-----------------
System Clock
Bus clock = 33MHz (33.513982 MHz) (1FF61FEh Hertz)
NDS7 clock = 33MHz (same as bus clock)
NDS9 clock = 66MHz (internally twice bus clock; for cache/tcm)
Most timings in this document are specified for 33MHz clock (not for the 66MHz
clock). Respectively, NDS9 timings are counted in "half" cycles.
NDS7/DATA NDS9/DATA
N32 S32 N16 S16 Bus N32 S32 N16 S16 Bus
10 2 9 1 16 10 2 9 1 16 Main RAM (read) (cache off)
1 1 1 1 32 4 1 4 1 32 WRAM,BIOS,I/O,OAM
1? 2 1 1 16 5 2 4 1 16 VRAM,Palette RAM
15 12 9 6 16 19 12 13 6 16 GBA ROM (example 10,6 access)
9 10 9 10 8 13 10 13 10 8 GBA RAM (example 10 access)
- - - - - 0.5 0.5 0.5 - 32 TCM, Cache_Hit
- - - - - (--Load 8 words--) Cache_Miss
- - - - - 11 11 11 - 32 Cache_Miss (BIOS)
- - - - - 23 23 23 - 16 Cache_Miss (Main RAM)
All timings are counted in 33MHz units (so "half" cycles can occur on NDS9).
Note: 8bit data accesses have same timings than 16bit data.
The NDS timings are altogether pretty messed up, with different timings for
CODE and DATA fetches, and different timings for NDS7 and NDS9...
NDS7/CODE
Timings for this region can be considered as "should be" timings.
NDS7/DATA
Quite the same as NDS7/CODE. Except that, nonsequential Main RAM accesses are 1
cycle slower, and more strange, nonsequential GBA Slot accesses are 1 cycle
faster.
NDS9/CODE
This is the most messiest timing. An infamous PENALTY of 3 cycles is added to
all nonsequential accesses (except cache, tcm, and main ram). And, all opcode
fetches are forcefully made nonsequential 32bit (the NDS9 simply doesn't
support fast sequential opcode fetches). That applies also for THUMB code (two
16bit opcodes are fetched by a single nonsequential 32bit access) (so the time
per 16bit opcode is one half of the 32bit fetch) (unless a branch causes only
one of the two 16bit opcodes to be executed, then that opcode will have the
full 32bit access time).
NDS9/DATA
Allows both sequential and nonsequential access, and both 16bit and 32bit
access, so it's faster than NDS9/CODE. Nethertheless, it's still having the 3
cycle PENALTY on nonsequential accesses. And, similar as NDS7/DATA, it's also
adding 1 cycle to nonsequential Main RAM accesses.
NDS9 Busses
Unlike ARM7, the ARM9 has separate code and data busses, allowing it to perform
code and data fetches simultaneously (provided that both are in different
memory regions).
Normally, opcode execution times are calculated as "(codetime+datatime)", with
the two busses, it can (ideally) be "MAX(codetime,datatime)", so the data
access time may virtually take "NULL" clock cycles.
In practice, DTCM and Data Cache access can take NULL cycles (however, data
access to ITCM can't).
When executing code in cache/itcm, data access to non-cache/tcm won't be any
faster than with only one bus (as it's best, it could subtract 0.5 cycles from
datatime, but, the access must be "aligned" to the bus-clock, so the
"datatime-0.5" will be rounded back to the original "datatime").
When executing code in uncached main ram, and accessing data (elsewhere than in
main memory, cache/tcm), then execution time is typically
"codetime+datatime-2".
Main Memory
Reportedly, the main memory access times would be 5 cycles (nonsequential
read), 4 cycles (nonsequential write), and 1 cycle (sequential read or write).
Plus whatever termination cycles. Plus 3 cycles on nonsequential access to the
last 2-bytes of a 32-byte block.
That's of course all wrong. Reads are much slower than 5 cycles. Not yet tested
if writes are faster. And, I haven't been able to reproduce the 3 cycles on
last 2-bytes effect, actually, it looks more as if that 3 cycles are accidently
added to ALL nonsequential accesses, at ALL main memory addresses, and even to
most OTHER memory regions... which might be the source of the PENALTY which
occurs on VRAM/WRAM/OAM/Palette and I/O accesses.
DMA
In some cases DMA main memory read cycles are reportedly performed
simultaneously with DMA write cycles to other memory.
NDS9
On the NDS9, all external memory access (and I/O) is delayed to bus clock (or
actually MUCH slower due to the massive waitstates), so the full 66MHz can be
used only internally in the NDS9 CPU core, ie. with cache and TCM.
Bus Clock
The exact bus clock is specified as 33.513982 MHz (1FF61FEh Hertz). However, on
my own NDS, measured in relation to the RTC seconds IRQ, it appears more like
1FF6231h, that inaccuary of 1 cycle per 657138 cycles (about one second per
week) on either oscillator, isn't too significant though.
GBA Slot
The access time for GBA slot can be configured via EXMEMCNT register.
VRAM Waitstates
Additionally, on NDS9, a one cycle wait can be added to VRAM accesses (when the
video controller simultaneously accesses it) (that can be disabled by Forced
Blank, see DISPCNT.Bit7). Moreover, additional VRAM waitstates occur when using
the video capture function.
Note: VRAM being mapped to NDS7 is always free of additional waits.
DS Video
--------
The NDS has two 2D Video Engines, each basically the same as in GBA, see
--> GBA LCD Video Controller
For Display Power Control (and Display Swap), and VRAM Allocation, see
--> DS Power Control
--> DS Power Management Device
--> DS Memory Control - VRAM
DS Video Stuff
--------------
DISPSTAT/VCOUNT
The LY and LYC values are in range 0..262, so LY/LYC values have been expanded
to 9bit values: LY = VCOUNT Bit 0..8, and LYC=DISPSTAT Bit8..15,7.
VCOUNT register is write-able, allowing to synchronize linked DS consoles.
For proper synchronization:
write new LY values only in range of 202..212
write only while old LY values are in range of 202..212
DISPSTAT/VCOUNT supported by NDS9 (Engine A Ports, without separate Engine B
Ports), and by NDS7 (allowing to synchronize NDS7 with display timings).
Similar as on GBA, the VBlank flag isn't set in the last line (ie. only in
lines 192..261, but not in line 262).
Although the drawing time is only 1536 cycles (256*6), the NDS9 H-Blank flag is
"0" for a total of 1606 cycles (and, for whatever reason, a bit longer, 1613
cycles in total, on NDS7).
VRAM Waitstates
The display controller performs VRAM-reads once every 6 clock cycles, a 1 cycle
waitstate is generated if the CPU simultaneously accesses VRAM. With capture
enabled, additionally VRAM-writes take place once every 6 cycles, so the total
VRAM-read/write access rate is then once every 3 cycles.
DS Window Glitches
The DS counts scanlines in range 0..262 (0..106h), of which only the lower 8bit
are compared with the WIN0V/WIN1V register settings. Respectively, Y1
coordinates 00h..06h will be triggered in scanlines 100h-106h by mistake. That
means, the window gets activated within VBlank period, and will be active in
scanline 0 and up (that is no problem with Y1=0, but Y1=1..6 will appear as if
if Y1 would be 0). Workaround would be to disable the Window during VBlank, or
to change Y1 during VBlank (to a value that does not occur during VBlank
period, ie. 7..191).
Also, there's a problem to fit the 256 pixel horizontal screen resolution into
8bit values: X1=00h is treated as 0 (left-most), X2=00h is treated as 100h
(right-most). However, the window is not displayed if X1=X2=00h; the window
width can be max 255 pixels.
2D Engines
Includes two 2D Engines, called A and B. Both engines are accessed by the ARM9
processor, each using different memory and register addresses:
Region______Engine A______________Engine B___________
I/O Ports 4000000h 4001000h
Palette 5000000h (1K) 5000400h (1K)
BG VRAM 6000000h (max 512K) 6200000h (max 128K)
OBJ VRAM 6400000h (max 256K) 6600000h (max 128K)
OAM 7000000h (1K) 7000400h (1K)
Engine A additionally supports 3D and large-screen 256-color Bitmaps, plus
main-memory-display and vram-display modes, plus capture unit.
Viewing Angles
The LCD screens are best viewed at viewing angles of 90 degrees. Colors may
appear distorted, and may even become invisible at other viewing angles.
When the console is handheld, both screens can be turned into preferred
direction. When the console is settled on a table, only the upper screen can be
turned, but the lower screen is stuck into horizontal position - which results
in rather bad visibility (unless the user moves his/her head directly above of
it).
DS-Lite Screens
The screens in the DS-Lite seem to allow a wider range of vertical angles.
The bad news is that the colors of the DS-Lite are (no surprise) not backwards
compatible with older NDS and GBA displays. The good news is that Nintendo has
finally reached near-CRT-quality (without blurred colors), so one could hope
that they won't show up with more displays with other colors in future.
Don't know if there's an official/recommended way to detect DS-Lite displays
(?) possible methods would be whatever values in Firmware header, or by
functionality of Power Managment device, or (not too LCD-related) by Wifi Chip
ID.
BG Mode
Engine A BG Mode (DISPCNT LSBs) (0-6, 7=Reserved)
Mode BG0 BG1 BG2 BG3
0 Text/3D Text Text Text
1 Text/3D Text Text Affine
2 Text/3D Text Affine Affine
3 Text/3D Text Text Extended
4 Text/3D Text Affine Extended
5 Text/3D Text Extended Extended
6 3D - Large -
Of which, the "Extended" modes are sub-selected by BGxCNT bits:
BGxCNT.Bit7 BGxCNT.Bit2 Extended Affine Mode Selection
0 CharBaseLsb rot/scal with 16bit bgmap entries (Text+Affine mixup)
1 0 rot/scal 256 color bitmap
1 1 rot/scal direct color bitmap
Engine B: Same as above, except that: Mode 6 is reserved (no Large screen
bitmap), and BG0 is always Text (no 3D support).
Affine = formerly Rot/Scal mode (with 8bit BG Map entries)
Large Screen Bitmap = rot/scal 256 color bitmap (using all 512K of 2D VRAM)
BGxCNT
character base extended from bit2-3 to bit2-5 (bit4-5 formerly unused)
engine A screen base: BGxCNT.bits*2K + DISPCNT.bits*64K
engine B screen base: BGxCNT.bits*2K + 0
engine A char base: BGxCNT.bits*16K + DISPCNT.bits*64K
engine B char base: BGxCNT.bits*16K + 0
char base is used only in tile/map modes (not bitmap modes)
screen base is used in tile/map modes,
screen base used in bitmap modes as BGxCNT.bits*16K, without DISPCNT.bits*64K
screen base however NOT used at all for Large screen bitmap mode
bgcnt size text rotscal bitmap large bmp
0 256x256 128x128 128x128 512x1024
1 512x256 256x256 256x256 1024x512
2 256x512 512x512 512x256 -
3 512x512 1024x1024 512x512 -
bitmaps that require more than 128K VRAM are supported on engine A only.
For BGxCNT.Bit7 and BGxCNT.Bit2 in Extended Affine modes, see above BG Mode
description (extended affine doesn't include 16-color modes, so color depth bit
can be used for mode selection. Also, bitmap modes do not use charbase, so
charbase.0 can be used for mode selection as well).
Unlike GBA bitmap modes, NDS bitmap modes are supporting the Area Overflow bit
(BG2CNT and BG3CNT, Bit 13).
DS Video OBJs
-------------
DS OBJ Priority
The GBA has been assigning OBJ priority in respect to the 7bit OAM entry
number, regardless of the OBJs 2bit BG-priority attribute (which allowed to
specify invalid priority orders). That problem has been fixed in DS mode by
combining the above two values into a 9bit priority value.
Extended Palettes
When allocating extended palettes, the allocated memory is not mapped to the
CPU bus, so the CPU can access extended palette only when temporarily
de-allocating it.
Capture data is 15bit color depth (even when capturing 18bit 3D-images).
Capture A: Dest_Intensity = SrcA_Intensitity ; Dest_Alpha=SrcA_Alpha.
Capture B: Dest_Intensity = SrcB_Intensitity ; Dest_Alpha=SrcB_Alpha.
Capture A+B (blending):
Dest_Intensity = ( (SrcA_Intensitity * SrcA_Alpha * EVA)
+ (SrcB_Intensitity * SrcB_Alpha * EVB) ) / 16
Dest_Alpha = (SrcA_Alpha AND (EVA>0)) OR (SrcB_Alpha AND EVB>0))
DS Files - 2D Video
-------------------
Header
000h 4 Chunk ID "RLCN" (aka NCLR backwards, Nitro Color Resource)
004h 2 Byte Order (FEFFh)
006h 2 Version (0100h)
008h 4 Total Filesize
00Ch 2 Offset to "TTLP" Chunk, aka Size of "RLCN" Chunk (0010h)
00Eh 2 Total number of following Chunks (1=TTLP) (or 2=TTLP+PMCP ?)
TTLP Chunk
000h 4 Chunk ID "TTLP" (aka PLTT backwards, Palette data)
004h 4 Chunk Size (eg. 0218h)
008h 4 Reportedly Color Depth (ie. "tile usage info") (3=4bpp, 4=8bpp)
00Ch 4 Zero
010h 4 Palette Data Size in bytes (eg. 200h) (or 200h-N? no, blah!)
014h 4 Offset from TTLP+8 to Palette Data? (always 10h)
018h N*2 Palete Data (16bit colors, 0000h..7FFFh)
Most DSi titles use full 200h-byte palettes (Paper Plane has a smaller one in
Graphics.NARC\Seq\pause.zcl). There seem to be no DSi titles with PMCP chunks.
PMCP Chunk (if any) (reportedly exists, but not in DSi Launcher...?)
000h 4 Chunk ID "PMCP" (aka PCMP backwards, Palette CMP?)
004h 4 Chunk Size (reportedly always 12h ???)
008h 2 Number of palettes in file (uh?)
00Ah 2 Unused (BEEFh=Bullshit)
00Ch 4 Offset from PMCP+8 to Palette IDs? (always 08h)
DATA N*2 "Palette ID numbers for each palette (starting from 0)"
Header
000h 4 Chunk ID "RGCN" (aka NCGR backwards, Nitro Char Graphics Resource)
004h 2 Byte Order (FEFFh)
006h 2 Version (0101h) (unknown if 0100h does also exist?)
008h 4 Total Filesize
00Ch 2 Offset to "RAHC" Chunk, aka Size of "RGCN" Chunk (0010h)
00Eh 2 Total number of following Chunks (1=RAHC, or 2=RAHC+SOPC)
RAHC Chunk
000h 4 Chunk ID "RAHC" (aka CHAR backwards)
004h 4 Chunk Size (eg. 1420h)
008h 2 Tile Data Size in Kilobytes ;\or both set to FFFFh
00Ah 2 Unknown (always 20h) ;/(when size<>N*1024)
00Ch 4 Color Depth (3=4bpp, 4=8bpp)
010h 2 Zero ;or 10h (when SOPC not exists? kbyte size rounded up?)
012h 2 Zero ;or 20h (when SOPC not exists?)
014h 4 Zero
018h 4 Tile Data Size in Bytes (eg. 1400h)
01Ch 4 Offset from RAHC+8 to Tile Data? ;=always 18h
020h ... Tile Data (eg. 20h-byte zerofilled for 4bpp SPC char?)
Nonzero [10h,12h] spotted in Paper Plane "rom:\Graphics.NARC\Plane\plane.zcg".
Header
000h 4 Chunk ID "RCSN" (aka NSCR backwards, Nitro Screen Resource)
004h 2 Byte Order (FEFFh)
006h 2 Version (0100h)
008h 4 Total Filesize
00Ch 2 Offset to "NRCS" Chunk, aka Size of "RCSN" Chunk (0010h)
00Eh 2 Total number of following Chunks (1=NRCS)
NRCS Chunk
000h 4 Chunk ID "NRCS" (aka SCRN backwards, Screen)
004h 4 Chunk Size
008h 4 Screen Width in pixels
00Ah 2 Screen Height in pixels
00Ch 4 Zero
010h 4 Screen Data Size (width/8)*(height/8)*2
014h N*2 Screen Data (16bit BG Map entries, palette+xyflip+tileno)
Header
000h 4 Chunk ID "RNAN" (aka NANR backwards, Nitro Animation Resource)
004h 2 Byte Order (FEFFh)
006h 2 Version (0100h)
008h 4 Total Filesize
00Ch 2 Offset to "KNBA" Chunk, aka Size of "RNAN" Chunk (0010h)
00Eh 2 Total number of following Chunks (1=KNBA, or 3=KNBA+LBAL+TXEU)
One chunk exists in DSi Launcher
Three chunks exist in DSi Flipnote "rom:ManualData.Eu\md2res_narc.blz\data\obj
KNBA Chunk
000h 4 Chunk ID "KNBA" (aka ABNK backwards, Animation Bank)
004h 4 Chunk Size (always padded to 4-byte boundary if LABL chunk follows)
008h 2 Number of 16-byte Animation Blocks ;implies NumLabels in LABL chunk
00Ah 2 Number of 8-byte Frame Blocks
00Ch 4 Offset from KNBA+8 to Animation Blocks ;=18h
010h 4 Offset from KNBA+8 to Frame Blocks ;=[0Ch]+[08h]*10h
014h 4 Offset from KNBA+8 to Frame Data ;=[10h]+[0Ah]*8
018h 8 Zero
DATA .. Animation Blocks (16-byte entries)
00h 4 Number of Frames
04h 2 Unknown (0)
06h 2 Unknown Always (1) ;reportedly "always unknown"
08h 4 Unknown (1..2)
0Ch 4 Offset from FrameBlock+0 to First Frame
DATA .. Frame Blocks (8-byte entries)
00h 4 Offset from FrameData+0 to whatever? (always 4-byte aligned?)
04h 2 Frame Width ;3Ch or 01..06h ;Time in 60Hz units? num meta's?
06h 2 Unused (usually 0000h, or BEEFh=Bullshit)
DATA .. Frame Data (2-byte entries)
00h 2 Unknown 16bit values? (maybe CELL index or whatever??) (CCCCh=?)
LBAL Chunk
000h 4 Chunk ID "LBAL" (aka LABL backwards, Labels)
004h 4 Chunk Size (not padded to 4-byte size, following TXEU is unaligned)
008h 4*N Offsets from LabelArea+0 to Labels (for each Animation Block)
... .. Label Area (ASCII Strings, terminated by 00h)
The LabelArea starts at LBAL+8+NumLabels*4 (whereas, NumLabels is found in KNBA
chunk).
TXEU Chunk
Caution: Not 4-byte aligned (the preceeding LBAL chunk can have odd size).
000h 4 Chunk ID "TXEU" (aka UEXT backwards, Whatever Extension or so?)
004h 4 Chunk Size (0Ch)
008h 4 Unknown (usually 0) (reportedly 0 or 1)
__________________________ Nitro OBJ Metatile Cells __________________________
Header
000h 4 Chunk ID "RECN" (aka NCER backwards, Nitro Cell Resource)
004h 2 Byte Order (FEFFh)
006h 2 Version (0100h)
008h 4 Total Filesize
00Ch 2 Offset to "KBEC" Chunk, aka Size of "RECN" Chunk (0010h)
00Eh 2 Total number of following Chunks (1=KBEC, or 3=KBEC+LBAL+TXEU)
KBEC Chunk
000h 4 Chunk ID "KBEC" (aka CEBK backwards, Cell Bank)
004h 4 Chunk Size (always padded to 4-byte boundary if LABL chunk follows)
008h 2 Number of Metatiles
00Ah 2 Metatiles Entry Size (0=Normal 8 bytes, 1=Extended 16 bytes)
(DSi Launcher ..layout\cmn\launcher_u\.. uses 16-byte size)
00Ch 4 Offset from KBEC+8 to Metatile Table? (18h)
010h 4 Boundary Size (?) (but is ZERO in layout\cmn\launcher_u\)
"Specifies the area in which the image can be drawn,
multiplied by 64, ie. 2 means that the area is 128x128 pixels."
014h 0Ch Zero
020h .. Metatile Table (8 bytes each) (or 16 bytes)
... .. OBJ Attribute Table (6-bytes each)
Metatile Table entries are (8-byte or 16-byte):
000h 2 Number of OBJs
002h 2 Unknown
004h 4 OBJ Data Offset (from begin of OBJ Attr Table)
(008h 2) Unknown (can be 02h,10h,48h,74h)
(00Ah 2) Unknown (can be 08h)
(00Ch 2) Unknown (can be FFA0h..FFF0h) ;\maybe extra coordinate offsets?
(00Eh 2) Unknown (can be FFF0h..FFF9h) ;/
OBJ Attribute Table...
starts at Number of Cells * 8 | each cell is made up of 6 bytes)
The 6-byte OBJ Attributes seem to be in normal OAM format, containing the
coordinates, tile number, tile size, and other flags (however, the coordinates
contain signed values; ie. one needs to add the current OBJ position to those
values). For details on the OBJ Attributes, see:
--> LCD OBJ - OAM Attributes
Note: DSi Launcher layout\cmn\logodemo.szs has KBEC Chunk Size 2B6h (although
the filesize is padded as if it were 2B8h bytes) (the file has no LBAL chunk,
so it's unclear if/how it were aligned if present).
.ntft file
Probably texture data (maybe for use as extra 2D layer), size is usually/always
a power of 2 (ranging from 80h bytes to at least 64Kbytes (or even 512Kbytes?).
Color depth can be 16bit or 8bit (and maybe less). Files with less than 16bit
are bundled with a .ntfp palette file.
.ntfp file
Probably texture palette, with 16bit color numbers. The files can be quite
small (eg. only 6 or 8 bytes).
.wmif file
000h 1Bh ID "Wild Magic Image File 3.00",00h
01Bh 4 Palette Filename Length (eg. 0Dh)
01Fh LEN Palette Filename (eg. "BG_Board.wmpf")
... 4 Texture Format (6=4bpp, 7=8bpp)
... 4 Texture Width in pixels
... 4 Texture Height in pixels
... .. Texture data
.wmpf file
000h 1Dh ID "Wild Magic Palette File 1.00",00h
01Dh 4 Zero?
021h 4 Number of Colors
025h .. Colors, 16bit (0000h..7FFFh)
Some Nintendo DS games are use the following set of Nitro Studio files for 3D
Models:
.NSBMD (ID="BMD0") - Nitro Polygon Model
.NSBTX (ID="BTX0") - Nitro Texture and Palette
.NSBCA (ID="BCA0") - Nitro Skeletal Character Animation
.NSBTP (ID="BTP0") - Nitro Texture Pattern-swap Animation
.NSBTA (ID="BTA0") - Nitro Texture UV-change Animation (aka texcoords?)
.NSBMA (ID="BMA0") - Nitro Material-swap Animation (whut?)
.NSBVA (ID="BVA0") - Nitro Vis... Animation?
Unknown which games are actually using that format... probably some mid-NDS-era
titles from Nintendo (early NDS launch titles didn't use it, 3rd party NDS
titles tend to use custom formats, and later DSi mini-games don't support 3D
graphics at all).
Aka NSBMD
BMD0 Header
000h 4 ID "BMD0" (Basic Model Data)
004h 2 Byte Order (FEFFh)
006h 2 Version? (reportedly 1 or 2, in whatever audio/video files?)
008h 4 Total Filesize
00Ch 2 Size of this structure (always 16 ???)
00Eh 2 Number of chunks (1=MDL0 or 2=MDL0+TEX0)
010h 4 Offset to MDL0 Chunk
014h 4 Offset to TEX0 Chunk (if any?) (otherwise TEX0 is in NSBTX file)
MDL0 Chunk
000h 4 Chunk ID "MDL0" (Model Block)
004h 4 Chunk Size
008h .. Model Dict (with 32bit offsets to Models from "Block_MDL0")
... .. Models
3: | 0 A B| 4: | A 0 B| 5: | A B 0|
| 1 0 0| | 0 1 0| | 0 0 1|
| 0 B -A| | B 0 -A| | B -A 0|
6: | 0 A B| 7: | A 0 B| 8: | A B 0|
| 0 B -A| | B 0 -A| | B -A 0|
| 1 0 0| | 0 1 0| | 0 0 1|
Non-Pivot does probably also use some kind of matrix made of A,B,C,D...?
Texture & Palette Offset <-- what is that, addressed from Model [008h] ?
000h 2 Offset of Texture Section (relative to Texture & Palette Offset)
002h 2 Offset of Palette Section (relative to Texture & Palette Offset)
Texture Section
Dict struct Header;// Texture Header: one Header object for each texture
{// The u32 'Data' for this Header is like so:
000h 2 Offset of Matching Data (relative to Texture & Palette
Offset)
002h 2 Amount of associated Materials (a texture can be in more
than one material)
}
Palette Section
Dict struct Header;// Palette Header: one Header object for each palette
{// The u32 'Data' for this Header is like so:
000h 2 Offset of Matching Data (relative to Texture & Palette
Offset)
002h 2 Amount of associated Materials (a palette can be in more
than one material)
}
Polygon Section
Dict struct Header;// Polygon Header: one Header object for each material
{// The 'Data' for this Header is like so:
000h 4 Offset of Polygon Definition, relative to the start of this
Polygon Section
}
Display List
// The Display List is actually packed geometry command.
// See the DStek specification for more information:
// http://www.akkit.org/info/gbatek.htm#ds3dvideo ;uh?
TEX0 Chunk
Reportedly same as in BTX0 files, see there for details.
The NSBTX file format stores texture image and palette information.
The "TEX0" Block can be found in certain NSBMD files, not just in NSBTX files.
BTX0 Header
000h 4 ID "BTX0" (Basic Texture)
004h 2 Byte Order (FEFFh)
006h 2 Version? (reportedly 1 or 2, in whatever audio/video files?)
008h 4 Total Filesize
00Ch 2 Size of this structure (always 16 ???)
00Eh 2 Number of chunks (1=TEX0)
010h 4 Offset to TEX0 Chunk
TEX0 Chunk
000h 4 Chunk ID "TEX0" (Texture Block)
004h 4 Chunk Size
008h 4 Padding (0)
00Ch 2 Texture Data Size (bitshift << 3) ;\
00Eh 2 Texture Dict Offset (03Ch) ; Texture
010h 4 Padding (0) ;
014h 4 Texture Data Offset ;/
018h 4 Padding (0)
01Ch 2 Compressed Texture Data Size (bitshift << 3) ;\<-- Size
01Eh 2 Compressed Texture Dict? Offset (03Ch, again?); <-- Dict?
020h 4 Padding (0) ;
024h 4 Compressed Texture Data Offset ; <-- Data
028h 4 Compressed Texture Info Data Offset ;/<-- InfoData?
02Ch 4 Padding (0)
030h 4 Palette Data Size (bitshift << 3) ;\
034h 4 Palette Dict Offset ; Palette
038h 4 Palette Data Offset ;/
03Ch .. Texture Dict (with 8-byte entries, see below)
N/A? ? Compressed Texture Dict? (maybe here? with whatever entries?)
... .. Palette Dict (with 4-byte entries, see below)
... .. Texture Data Section (unknown... maybe bitmap/pixels?)
... .. Compressed Texture Data Section (unknown...)
... .. Compressed Texture Info Data Section (unknown...)
... .. Palette Data Section (unknown... maybe palette/colors?)
BCA0 Header
000h 4 ID "BCA0" (Basic Character Animation)
004h 2 Byte Order (FEFFh)
006h 2 Version? (reportedly 1 or 2, in whatever audio/video files?)
008h 4 Total Filesize
00Ch 2 Size of this structure (always 16 ???)
00Eh 2 Number of chunks (1=JNT0)
010h 4 Offset to JNT0 Chunk
JNT0 Chunk
000h 4 Chunk ID "JNT0" (Joint Block)
004h 4 Chunk Size
008h .. Joint Dict (with 32bit offsets to Joints, from "Block_JNT0")
Joints
Reportedly Joints "repeats * Amount of Objects"
Uh, with Amount of Objects stored inside of below?
Maybe rather meant to mean that Joints exist for each Model (not Object)?
000h 4 ID 'J.AC' (Joint Animation Content ?)
004h 2 Amount of Frames
006h 2 Amount of Objects (should be same as in BMD0 file)
008h 4 Unknown
00Ch 4 Offset to Unknown1 chunk. Relative to start of this block.
010h 4 Offset to Unknown2 chunk. Relative to start of this block.
014h 4 Object Info Offset (repeats * Amount of Objects), relative
to start of this Joint Section.
uh, is above meant to be Offset to first Object?
or an array with Offsets to all Objects?
... .. Object Info, for each object (supposedly here?)
... .. Unknown1
... .. Unknown2
... .. Reportedly "end of file" (is that possible with multiple joints?)
BTP0 Header
000h 4 ID "BTP0" (Texture Pattern Animation)
... .. XXX
PAT0 Chunk
000h 4 Chunk ID "PAT0" (Pattern Block)
004h 4 Chunk Size
... .. Unknown
BTA0 Header
000h 4 ID "BTA0" (Texture Animation)
... .. XXX
SRT0 Chunk
000h 4 Chunk ID "SRT0" (maybe short for Scale/Rotate/Translate?)
004h 4 Chunk Size
... .. Unknown
BMA0 Header
000h 4 ID "BMA0" (Material Animation)
... .. XXX
MAT0 Chunk
000h 4 Chunk ID "MAT0" (Material Block)
004h 4 Chunk Size
... .. Unknown
BVA0 Header
000h 4 ID "BVA0" (whatever Vis... Animation?)
... .. XXX
VIS0 Chunk
000h 4 Chunk ID "VIS0" (Visibility...?)
004h 4 Chunk Size
... .. Unknown
DS 3D Video
-----------
--> DS 3D Overview
--> DS 3D I/O Map
--> DS 3D Display Control
--> DS 3D Geometry Commands
--> DS 3D Matrix Load/Multiply
--> DS 3D Matrix Types
--> DS 3D Matrix Stack
--> DS 3D Matrix Examples (Projection)
--> DS 3D Matrix Examples (Rotate/Scale/Translate)
--> DS 3D Matrix Examples (Maths Basics)
--> DS 3D Polygon Attributes
--> DS 3D Polygon Definitions by Vertices
--> DS 3D Polygon Light Parameters
--> DS 3D Shadow Polygons
--> DS 3D Texture Attributes
--> DS 3D Texture Formats
--> DS 3D Texture Coordinates
--> DS 3D Texture Blending
--> DS 3D Toon, Edge, Fog, Alpha-Blending, Anti-Aliasing
--> DS 3D Status
--> DS 3D Tests
--> DS 3D Rear-Plane
--> DS 3D Final 2D Output
Swap Buffers (Pass data from the Geometry Engine to the Rendering Engine)
The hardware includes two sets of Vertex/Polygon RAM, one used by the Geometry
Engine, one by the Rendering Engine. The SwapBuffers command simply exchanges
these buffers (so the new Geometry Data is passed to the Rendering Engine) (and
the old buffer is emptied, so the Geometry engine can write new data to it).
Additionally, the two parameter bits from the <previous> SwapBuffers command
are copied to the Geometry Engine.
Data that is NOT swapped: SwapBuffers obviously can't swap Texture memory (so
software must take care that Texture memory is kept mapped throughout
rendering). Moreover, the rendering control registers (ports 4000060h, and
4000330h..40003BFh) are not swapped (so that values must be kept intact during
rendering, too).
DS 3D I/O Map
-------------
3D I/O Map
Address Siz Name Expl.
Rendering Engine (per Frame settings)
4000060h 2 DISP3DCNT 3D Display Control Register (R/W)
4000320h 1 RDLINES_COUNT Rendered Line Count Register (R)
4000330h 10h EDGE_COLOR Edge Colors 0..7 (W)
4000340h 1 ALPHA_TEST_REF Alpha-Test Comparision Value (W)
4000350h 4 CLEAR_COLOR Clear Color Attribute Register (W)
4000354h 2 CLEAR_DEPTH Clear Depth Register (W)
4000356h 2 CLRIMAGE_OFFSET Rear-plane Bitmap Scroll Offsets (W)
4000358h 4 FOG_COLOR Fog Color (W)
400035Ch 2 FOG_OFFSET Fog Depth Offset (W)
4000360h 20h FOG_TABLE Fog Density Table, 32 entries (W)
4000380h 40h TOON_TABLE Toon Table, 32 colors (W)
Geometry Engine (per Polygon/Vertex settings)
4000400h 40h GXFIFO Geometry Command FIFO (W)
4000440h ... ... Geometry Command Ports (see below)
4000600h 4 GXSTAT Geometry Engine Status Register (R and R/W)
4000604h 4 RAM_COUNT Polygon List & Vertex RAM Count Register (R)
4000610h 2 DISP_1DOT_DEPTH 1-Dot Polygon Display Boundary Depth (W)
4000620h 10h POS_RESULT Position Test Results (R)
4000630h 6 VEC_RESULT Vector Test Results (R)
4000640h 40h CLIPMTX_RESULT Read Current Clip Coordinates Matrix (R)
4000680h 24h VECMTX_RESULT Read Current Directional Vector Matrix (R)
DS 3D Display Control
---------------------
DS 3D Geometry Commands
-----------------------
Invalid GX commands
Invalid commands (anything else than 10h..1Ch, 20h..2Bh, 30h..33h, 40h..41h,
50h, 60h, or 70h..72h) seem to be simply ignored by the hardware (at least,
testing has confirmed that they do not fetch any parameters from the gxfifo).
DS 3D Matrix Load/Multiply
--------------------------
4000454h - Cmd 15h - MTX_IDENTITY - Load Unit Matrix to Current Matrix (W)
Sets C=I. Parameters: None
The Identity Matrix (I), aka Unit Matrix, consists of all zeroes, with a
diagonal row of ones. A matrix multiplied by the Unit Matrix is left unchanged.
4000458h - Cmd 16h - MTX_LOAD_4x4 - Load 4x4 Matrix to Current Matrix (W)
Sets C=M. Parameters: 16, m[0..15]
400045Ch - Cmd 17h - MTX_LOAD_4x3 - Load 4x3 Matrix to Current Matrix (W)
Sets C=M. Parameters: 12, m[0..11]
4000460h - Cmd 18h - MTX_MULT_4x4 - Multiply Current Matrix by 4x4 Matrix (W)
Sets C=M*C. Parameters: 16, m[0..15]
4000464h - Cmd 19h - MTX_MULT_4x3 - Multiply Current Matrix by 4x3 Matrix (W)
Sets C=M*C. Parameters: 12, m[0..11]
4000468h - Cmd 1Ah - MTX_MULT_3x3 - Multiply Current Matrix by 3x3 Matrix (W)
Sets C=M*C. Parameters: 9, m[0..8]
400046Ch - Cmd 1Bh - MTX_SCALE - Multiply Current Matrix by Scale Matrix (W)
Sets C=M*C. Parameters: 3, m[0..2]
Note: MTX_SCALE doesn't change Vector Matrix (even when in MTX_MODE=2) (that's
done so for keeping the length of the light vector's intact).
4000470h - Cmd 1Ch - MTX_TRANS - Mult. Curr. Matrix by Translation Matrix (W)
Sets C=M*C. Parameters: 3, m[0..2] (x,y,z position)
DS 3D Matrix Types
------------------
Essentially, all matrices in the NDS are 4x4 Matrices, consisting of 16 values,
m[0..15]. Each element is a signed fixed-point 32bit number, with a fractional
part in the lower 12bits.
The other Matrix Types are used to reduce the number of parameters being
transferred, for example, 3x3 Matrix requires only nine parameters, the other
seven elements are automatically set to 0 or 1.0 (whereas "1.0" means "1 SHL
12" in 12bit fixed-point notation).
DS 3D Matrix Stack
------------------
Matrix Stack
The NDS has three Matrix Stacks, and two Matrix Stack Pointers (the Coordinate
Matrix stack pointer is also shared for Directional Matrix Stack).
Matrix Stack________Valid Stack Area____Stack Pointer___________________
Projection Stack 0..0 (1 entry) 0..1 (1bit) (GXSTAT: 1bit)
Coordinate Stack 0..30 (31 entries) 0..63 (6bit) (GXSTAT: 5bit only)
Directional Stack 0..30 (31 entries) (uses Coordinate Stack Pointer)
Texture Stack One..None? 0..1 (1bit) (GXSTAT: N/A)
Which of the stacks/matrices depends on the current Matrix Mode (as usually,
but with one exception; stack operations MTX_PUSH/POP/STORE/RESTORE in Mode 1
are acting same as in Mode 2):
MTX_MODE = 0 --> Projection Stack
MTX_MODE = 1 or 2 --> BOTH Coordinate AND Directional Stack
MTX_MODE = 3 --> Texture Stack
The initial value of the Stack Pointers is zero, the current value of the
pointers can be read from GXSTAT (read-only), that register does also indicate
stack overflows (errors flag gets set on read/write to invalid entries, ie.
entries 1 or 1Fh..3Fh). For all stacks, the upper half (ie. 1 or 20h..3Fh) are
mirrors of the lower half (ie. 0 or 0..1Fh).
4000448h - Cmd 12h - MTX_POP - Pop Current Matrix from Stack (W)
Sets S=S-N, and then C=[S].
Parameter Bit0-5: Stack Offset (signed value, -30..+31) (usually +1)
Parameter Bit6-31: Not used
Offset N=(+1) pops the most recently pushed value, larger offsets of N>1 will
"deallocate" N values (and load the Nth value into C). Zero or negative values
can be used to pop previously "deallocated" values.
The stack has only one level (at address 0) in projection mode, in that mode,
the parameter value is ignored, the offset is always +1 in that mode.
4000450h - Cmd 14h - MTX_RESTORE - Restore Current Matrix from Stack (W)
Sets C=[N]. The stack pointer S is not used, and is left unchanged.
Parameter Bit0-4: Stack Address (0..30) (31 causes overflow in GXSTAT.15)
Parameter Bit5-31: Not used
The stack has only one level (at address 0) in projection mode, in that mode,
the parameter value is ignored.
In Projection mode, the parameter for POP, STORE, and RESTORE is unused - not
sure if the parameter (ie. a dummy value) is - or is not - to be written to the
command FIFO?
There appear to be actually 32 entries in Coordinate & Directional Stacks,
entry 31 appears to exist, and appears to be read/write-able (although the
stack overflow flag gets set when accessing it).
The most important matrix is the Projection Matrix (to be initialized with
MTX_MODE=0 via MTX_LOAD_4x4 command). It does specify the dimensions of the
view volume.
With Perspective Projections more distant objects will appear smaller, with
Orthogonal Projects the size of the objects is always same regardless of their
distance.
Correctly initializing the projection matrix (as shown in the examples below)
can be quite difficult (mind that fixed point multiply/divide requires to
adjust the fixed-point width before/after calculation). For beginners, it may
be recommended to start with a simple Identity Matrix (MTX_IDENTITY command)
used as Projection Matrix (ie. Ortho with t,b,l,r set to +/-1).
Identity Matrix
The MTX_IDENTITY command can be used to initialize the Position Matrix before
doing any Translation/Scaling/Rotation, for example:
Load(Identity) ;no rotation/scaling used
Load(Identity), Mul(Rotate), Mul(Scale) ;rotation/scaling (not so efficient)
Load(Rotate), Mul(Scale) ;rotation/scaling (more efficient)
Rotation Matrices
Rotation can be performed with MTX_MULT_3x3 command, simple examples are:
Around X-Axis Around Y-Axis Around Z-Axis
| 1.0 0 0 | | cos 0 sin | | cos sin 0 |
| 0 cos sin | | 0 1.0 0 | | -sin cos 0 |
| 0 -sin cos | | -sin 0 cos | | 0 0 1.0 |
Scale Matrix
The MTX_SCALE command allows to adjust the size of the polygon. The x,y,z
parameters should be normally all having the same value, x=y=z (unless if you
want to change only the height of the object, for example). Identical results
can be obtained with MTX_MULT commands, however, when using lighting
(MTX_MODE=2), then scaling should be done ONLY with MTX_SCALE (which keeps the
length of the light's directional vector intact).
Translation Matrix
The MTX_TRANS command allows to move polygons to the desired position. The
polygon VTX commands are spanning only a small range of coordinates (near
zero-coordinate), so translation is required to move the polygons to other
locations in the world coordinates. Aside from that, translation is useful for
moved objects (at variable coordinates), and for re-using an object at various
locations (eg. you can create a forest by translating a tree to different
coordinates).
Matrix-by-Matrix Multiplication
Matrix multiplication, C = A * B, is possible only if the number of columns in
A is equal to the number of rows in B, so it works fine with the 4x4 matrices
which are used in the NDS. For the multiplication, assume matrix C to consist
of elements cyx, and respecitively, matrix A and B to consist of elements ayx
and byx. So that C = A * B looks like:
| c11 c12 c13 c14 | | a11 a12 a13 a14 | | b11 b12 b13 b14 |
| c21 c22 c23 c24 | = | a21 a22 a23 a24 | * | b21 b22 b23 b24 |
| c31 c32 c33 c34 | | a31 a32 a33 a34 | | b31 b32 b33 b34 |
| c41 c42 c43 c44 | | a41 a42 a43 a44 | | b41 b42 b43 b44 |
Each element in C is calculated by multiplying the elements from one row in A
by the elements from the corresponding column in B, and then taking the sum of
the products, ie.
cyx = ay1*b1x + ay2*b2x + ay3*b3x + ay4*b4x
In total, that requires 64 multiplications (four multiplications for each of
the 16 cyx elements), and 48 additions (three per cyx element), the hardware
carries out that operation at a relative decent speed of 30..35 clock cycles,
possibly by performing several multiplications simultaneously with separate
multiply units.
Observe that for matrix multiplication, A*B is NOT the same as B*A.
Matrix-by-Number Multiplication
Simply multiply all elements of the Matrix by the number, C = A * n:
cyx = ayx*n
Of course, works also with vectors (matrices with only one row/column).
Matrix-to-Matrix Addition/Subtraction
Both matrices must have the same number of rows & columns, add/subtract all
elements with corresponding elements in other matrix, C = A +/- B:
cyx = ayx +/- byx
Of course, works also with vectors (two matrices with only one row/column).
Vectors
A vector, for example (x,y,z), consists of offsets along x-,y-, and z-axis. The
line from origin to origin-plus-offset is having two characteristics: A
direction, and a length.
The length (aka magnitude) can be calculated as L=sqrt(x^2+y^2+z^2).
Vector-by-Vector Multiplication
This can be processed as LineVector*RowVector, so the result is a number (aka
scalar) (aka a matrix with only 1x1 elements). Multiplying two (normalized)
vectors results in: "cos(angle)=vec1*vec2", ie. the cosine of the angle between
the two vectors (eg. used for light vectors). Multiplying a vector with itself,
and taking the square root of the result obtains its length, ie.
"length=sqrt(vec^2)".
That stuff should be done with 3-dimensional vectors (not 4-dimensionals).
Normalized Vectors
Normalized Vectors (aka Unit Vectors) are vectors with length=1.0. To normalize
a vector, divide its coordinates by its length, ie. x=x/L, y=y/L, z=z/L, the
direction remains the same, but the length is now 1.0.
On the NDS, normalized vectors should have a length of something less than 1.0
(eg. something like 0.99) because several NDS registers are limited to 1bit
sign, 0bit integer, Nbit fractional part (so vectors that are parallel to the
x,y,z axes, or that become parallel to them after rotation, cannot have a
length of 1.0).
Fixed-Point Numbers
The NDS uses fixed-point numbers (rather than floating point numbers). Addition
and Subtraction works as with normal integers, provided that the fractional
part is the same for both numbers. If it is not the same: Shift-left the value
with the smaller fractional part.
For multiplication, the fractional part of result is the sum of the fractional
parts (eg. 12bit fraction * 12bit fraction = 24bit fraction; shift-right the
result by 12 to convert it 12bit fraction). The NDS matrix multiply unit is
maintaining the full 24bit fraction when processing the
cyx = ay1*b1x + ay2*b2x + ay3*b3x + ay4*b4x
formula, ie. the three additions are using full 24bit fractions (with
carry-outs to upper bits), the final result of the additions is then
shifted-right by 12.
For division, it's vice versa, the fractions of the operands are substracted,
24bit fraction / 12bit fraction = 12bit fraction. When dividing two 12bit
numbers, shift-left the first number by 12 before division to get a result with
12bit fractional part.
Four-Dimensional Matrices
The NDS uses four-dimensional matrices and vectors, ie. matrices with 4x4
elements, and vectors with 4 elements. The first three elements are associated
with the X,Y,Z-axes of the three-dimensional space. The fourth element is
somewhat a "W-axis".
With 4-dimensional matrices, the Translate matrix can be used to move an object
to another position. Ie. once when you've setup a matrix (which may consists of
pre-multiplied scaling, rotation, translation matrices), then that matrix can
be used on vertices to perform the rotation, scaling, translation all-at-once;
by a single Vector*Matrix operation.
With 3-dimensional matrices, translation would require a separate addition,
additionally to the multiply operation.
DS 3D Polygon Attributes
------------------------
Depth Test
The Depth Test compares the depth of the pixels of the polygon with the depth
of previously rendered polygons (or of the rear plane if there have been none
rendered yet). The new pixels are drawn if the new depth is Less (closer to the
camera), or if it is Equal, as selected by POLYGON_ATTR.Bit14.
Normally, Depth Equal would work only exact matches (ie. if the overlapping
polygons have exactly the same coordinates; and thus have the same rounding
errors), however, the NDS hardware is allowing "Equal" to have a tolerance of
+/-200h (within the 24bit depth range of 0..FFFFFFh), that may bypass rounding
errors, but it may also cause nearby polygons to be accidently treated to have
equal depth.
For Line Segments, use Triangles with twice the same vertex, Line Segments are
rendered always because they do not have any front and back sides.
The Prohibited Quad shapes may produce unintended results, namely, that are
Quads with crossed sides, and quads with angles greater than 180 degrees.
The lighting operation is performed by executing the Normal command (which sets
the VertexColor based on the Light/Material parameters) (to the rest of the
hardware it doesn't matter if the VertexColor was set by Color command or by
Normal command). Light is calculated only for the Front side of the polygon
(assuming that the Normal is matched to that side), so the Back side will be
(incorrectly) using the same color.
40004C4h - Cmd 31h - SPE_EMI - MaterialColor1 - Specular Ref. & Emission (W)
0-4 Specular Reflection Red ;\light(s) reflected towards the camera,
5-9 Specular Reflection Green ; ie. max when NormalVector is in middle of
10-14 Specular Reflection Blue ;/LightVector and ViewDirection
15 Specular Reflection Shininess Table (0=Disable, 1=Enable)
16-20 Emission Red ;\light emitted by the polygon itself,
21-25 Emission Green ; ie. regardless of light colors/vectors,
26-30 Emission Blue ;/and no matter if any lights are enabled
31 Not used
Caution: Specular Reflection WON'T WORK when the ProjectionMatrix is rotated.
Normal Vector
The Normal vector must point "away from the polygon surface" (eg. for the
floor, the Normal should point upwards). That direction is implied by the
polygon vertices, however, the hardware cannot automatically calculate it, so
it must be set manually with the Normal command (prior to the VTX-commands).
When using lighting, the Normal command must be re-executed after switching
Lighting on/off, or after changing light/material parameters. And, of course,
also before defining polygons with different orientation. Polygons with same
orientation (eg. horizontal polygon surfaces) and same material color can use
the same Normal. Changing the Normal per polygon gives differently colored
polygons with flat surfaces, changing the Normal per vertex gives the illusion
of curved surfaces.
Light Vector
Each light consists of parallel beams; similar to sunlight, which appears to us
(due to the great distance) to consist of parallel beams, all emmitted into the
same direction; towards Earth.
In reality, light is emitted into ALL directions, originated from the light
source (eg. a candle), the hardware doesn't support that type of non-parallel
light. However, the light vectors can be changed per polygon, so a polygon that
is located north of the light source may use different light direction than a
polygon that is east of the light source.
And, of course, Light 0..3 may (and should) have different directions.
Normalized Vectors
The Normal Vector and the Light Vectors should be normalized (ie. their length
should be 1.0) (in practice: something like 0.99, since the registers have only
fractional parts) (a length of 1.0 can cause overflows).
Lighting Limitations
The functionality of the light feature is limited to reflecting light to the
camera (light is not reflected to other polygons, nor does it cast shadows on
other polygons). However, independently of the lighting feature, the DS
hardware does allow to create shadows, see:
--> DS 3D Shadow Polygons
DS 3D Shadow Polygons
---------------------
Translucent Targets
Casting shadows on Translucent Polygons. First draw the translucent target
(with update depth buffer enabled, required for the shadow z-coordinates), then
draw the Shadow Mask/Rendering volumes.
Due to the updated depth buffer the shadow will be cast only on the translucent
target (not on any other polygons underneath of the translucent polygon). If
you want the shadow to appear on both: Draw draw the Shadow Mask/Rendering
volume TWICE (once before, and once after drawing the translucent target).
DS 3D Texture Attributes
------------------------
40004ACh - Cmd 2Bh - PLTT_BASE - Set Texture Palette Base Address (W)
0-12 Palette Base Address (div8 or div10h, see below)
(Not used for Texture Format 7: Direct Color Texture)
(0..FFF8h/8 for Texture Format 2: ie. 4-color-palette Texture)
(0..17FF0h/10h for all other Texture formats)
13-31 Not used
The palette data occupies 16bit per color, Bit0-4: Red, Bit5-9: Green,
Bit10-14: Blue, Bit15: Not used.
(VRAM must be allocated as Texture Palette, there can be up to 6 Slots
allocated, ie. the addressable 18000h bytes, see Memory Control chapter)
DS 3D Texture Formats
---------------------
DS 3D Texture Coordinates
-------------------------
For textured polygons, a texture coordinate must be associated with each vertex
of the polygon. The coordinates (S,T) are defined by TEXCOORD command
(typically issued prior to each VTX command), and can be optionally
automatically transformed, by the Transformation Mode selected in
TEXIMAGE_PARAM register.
Texture Matrix
Although the texture matrix is 4x4, with values m[0..15], only the left two
columns of this matrix are actually used. In Mode 2 and 3, the bottom row of
the matrix is replaced by S and T values from most recent TEXCOORD command.
DS 3D Texture Blending
----------------------
Above formulas are for 6bit RGBA values, ie. 5bit values internally expanded to
6bit as such: IF X>0 THEN X=X*2+1.
Uni-Colored Textures
Although textures are normally containing "pictures", in some cases it makes
sense to use "blank" textures that are filled with a single color:
Wire-frame polygons are always having Av=31, however, they can be made
transparent by using Translucent Textures (ie. A5I3 or A3I5 formats) with
At<31.
In Toon/Highlight shading modes, the Vertex Color is mis-used as table index,
however, Toon/Highlight shading can be used on uni-colored textures, which is
more or less the same as using Toon/Highlight shading on uni-colored
Vertex-colors.
Anti-Aliasing
Anti-Aliasing can be enabled in DISP3DCNT, when enabled, the edges of opaque
polygons will be anti-aliased (ie. the pixels at the edges may become
translucent).
Anti-Aliasing is not applied on translucent polygons. And, Anti-Aliasing is not
applied on the interiors of the poylgons (eg. an 8x8 chessboard texture will be
anti-aliased only at the board edges, not at the edges of the 64 fields).
Anti-Aliasing is (accidently) applied to opaque 1dot polygongs, line-segments
and wire-frames (which results in dirty lines with missing pixels, 1dot polys
become totally invisible), workaround is to use translucent dots, lines and
wires (eg. with alpha=30).
Anti-Aliasing is (correctly) not applied to edges of Edge-Marked polygons, in
that special case even opaque line-segments and wire-frames are working even if
anti-aliasing is enabled (provided that they are edge-marked, ie. if their
polygon ID differs from the framebuffer's ID).
Anti-Aliasing is (accidently) making the edges of Edge-Marked polygons
translucent (with alpha=16 or so?), that reduces the contrast of the edge
colors. Moreover, if two of these translucent edges do overlap, then they are
blended twice (even if they have the same polygon_id, and even if the
depth_update bit in polygon_attr is set; both should normally prevent
double-blending), that scatters the brightness of such edges.
Polygon Size
In some cases, the NDS hardware doesn't render the lower/right edges of certain
polygons. That feature reduces rendering load, and, when rendering connected
polygons (eg. strips), then it'd be unnecessary to render that edges (since
they'd overlap with the upper/left edges of the other polygon). On the
contrary, if there's no connected polygon displayed, then the polygon may
appear smaller than expected. Small polygons with excluded edges are:
Opaque polygons (except wire-frames) without Edge-Marking and Anti-Aliasing,
and, all polygons with vertical right-edges (except line-segments).
Plus, Translucent Polys when Alpha-Blending is disabled in DISP3DCNT.Bit3.
All other polygons are rendered at full size with all edges included (except
vertical right edges). Note: To disable the small-polygon feature, you can
enable edge-marking (which does increase the polygon size, even if no edges are
drawn, ie. even if all polys do have the same ID).
DS 3D Status
------------
4000604h - RAM_COUNT - Polygon List & Vertex RAM Count Register (R)
0-11 Number of Polygons currently stored in Polygon List RAM (0..2048)
12-15 Not used
16-28 Number of Vertices currently stored in Vertex RAM (0..6144)
13-15 Not used
If a SwapBuffers command has been sent, then the counters are reset 10 cycles
(at 33.51MHz clock) after next VBlank.
DS 3D Tests
-----------
40005C0h - Cmd 70h - BOX_TEST - Test if Cuboid Sits inside View Volume (W)
The BoxTest result indicates if one or more of the 6 faces of the box are fully
or parts of inside of the view volume. Can be used to reduce unnecessary
overload, ie. if the result is false, then the program can skip drawing of
objects which are inside of the box.
BoxTest verifies only if the faces of the box are inside view volume, and so,
it will return false if the whole view volume is located inside of the box
(still objects inside of the box may be inside of view).
Parameter 1, Bit 0-15 X-Coordinate
Parameter 1, Bit 16-31 Y-Coordinate
Parameter 2, Bit 0-15 Z-Coordinate
Parameter 2, Bit 16-31 Width (presumably: X-Offset?)
Parameter 3, Bit 0-15 Height (presumably: Y-Offset?)
Parameter 3, Bit 16-31 Depth (presumably: Z-Offset?)
All values are 1bit sign, 3bit integer, 12bit fractional part
The result of the "coordinate+offset" additions should not overflow 16bit
vertex coordinate range (1bit sign, 3bit integer, 12bit fraction).
Before using BoxTest, be sure that far-plane-intersecting & 1-dot polygons are
enabled, if they aren't: Send the PolygonAttr command (with bit12,13 set to
enable them), followed by dummy Begin and End commands (required to apply the
new PolygonAttr settings). BoxTest should not be issued within Begin/End.
After sending the BoxTest command, wait until GXSTAT.Bit0 indicates Ready, then
read the result from GXSTAT.Bit1.
40005C4h - Cmd 71h - POS_TEST - Set Position Coordinates for Test (W)
Parameter 1, Bit 0-15 X-Coordinate
Parameter 1, Bit 16-31 Y-Coordinate
Parameter 2, Bit 0-15 Z-Coordinate
Parameter 2, Bit 16-31 Not used
All values are 1bit sign, 3bit integer, 12bit fractional part.
Multiplies the specified line-vector (x,y,z,1) by the clip coordinate matrix.
After sending the command, wait until GXSTAT.Bit0 indicates Ready, then read
the result from POS_RESULT registers. POS_TEST can be issued anywhere (except
within polygon strips, huh?).
Caution: POS_TEST overwrites the internal VTX registers, so the next vertex
should be <fully> defined by VTX_10 or VTX_16, otherwise, when using VTX_XY,
VTX_XZ, VTX_YZ, or VTX_DIFF, then the new vertex will be relative to the
POS_TEST coordinates (rather than to the previous vertex).
40005C8h - Cmd 72h - VEC_TEST - Set Directional Vector for Test (W)
Parameter 1, Bit 0-9 X-Component
Parameter 1, Bit 10-19 Y-Component
Parameter 1, Bit 20-29 Z-Component
Parameter 1, Bit 30-31 Not used
All values are 1bit sign, 9bit fractional part.
Multiplies the specified line-vector (x,y,z,0) by the directional vector
matrix. Similar as for the NORMAL command, it does require Matrix Mode 2 (ie.
Position & Vector Simultaneous Set mode).
After sending the command, wait until GXSTAT.Bit0 indicates Ready, then read
the result ("the directional vector in the View coordinate space") from
VEC_RESULT registers.
DS 3D Rear-Plane
----------------
The rear-plane can be initialized via below two registers (so all pixels in the
plane have the same colors and attributes), this method is used when
DISP3DCNT.14 is zero:
DS 3D Final 2D Output
---------------------
Scrolling
The BG0HOFS register (4000010h) can be used the scroll the 3D layer
horizontally, the scroll region is 512 pixels, consisting of 256 pixels for the
3D image, followed by 256 transparent pixels, and then wrapped to the 3D image
again. Vertical scrolling (and rotation/scaling) cannot be used on the 3D
layer.
BG Priority Order
The lower 2bit of the BG0CNT register (4000008h) control the priority relative
to other BGs and OBJs, so the 3D layer can be in front of or behind 2D layers.
All other bits in BG0CNT have no effect on 3D, namely, mosaic cannot be used on
the 3D layer.
Special Effects
Special Effects Registers (4000050h..54h) can be used as such:
Brightness up/down with BG0 as 1st Target via EVY (as for 2D)
Blending with BG0 as 2nd Target via EVA/EVB (as for 2D)
Blending with BG0 as 1st Target via 3D Alpha-values (unlike as for 2D)
The latter method probably (?) uses per-pixel 3D alpha values as such: EVA=A/2,
and EVB=16-A/2, without using the EVA/EVB settings in 4000052h.
Window Feature
Window Feature (4000040h..4Bh) can be used as for 2D.
"If the 3D screen has highest priority, then alpha-blending is always enabled,
regardless of the Window Control register's color effect enable flag [ie.
regardless of Bit5 of WIN0IN, WIN1IN, WINOBJ, WINOUT registers]"... not sure if
that is true, and if it superseedes the effect selection in Port 4000050h...?
DS Sound
--------
DS Sound Hardware
The DS contains 16 hardware sound channels.
The console contains two speakers, arranged left and right of the upper screen,
and so, provides stereo sound even without using the headphone socket.
--> DS Sound Channels 0..15
--> DS Sound Control Registers
--> DS Sound Capture
--> DS Sound Block Diagrams
--> DS Sound Notes
DS Sound Files
--> DS Files - Sound (SDAT etc.)
Power control
When restoring power supply to the sound circuit, do not output any sound
during the first 15 milliseconds.
Each of the 16 sound channels occopies 16 bytes in the I/O region, starting
with channel 0 at 4000400h..400040Fh, up to channel 15 at 40004F0h..40004FFh.
The sampling frequency of the mixer is 1.04876 MHz with an amplitude resolution
of 24 bits, but the sampling frequency after mixing with PWM modulation is
32.768 kHz with an amplitude resolution of 10 bits.
DS Sound Capture
----------------
The DS contains 2 built-in sound capture devices that can capture output
waveform data to memory.
Sound capture 0 can capture output from left-mixer or output from channel 0.
Sound capture 1 can capture output from right-mixer or output from channel 2.
4000508h - NDS7 - SNDCAP0CNT - Sound Capture 0 Control Register (R/W)
4000509h - NDS7 - SNDCAP1CNT - Sound Capture 1 Control Register (R/W)
Bit0 Control of Associated Sound Channels (ANDed with Bit7)
SNDCAP0CNT: Output Sound Channel 1 (0=As such, 1=Add to Channel 0)
SNDCAP1CNT: Output Sound Channel 3 (0=As such, 1=Add to Channel 2)
Caution: Addition mode works only if BOTH Bit0 and Bit7 are set.
Bit1 Capture Source Selection
SNDCAP0CNT: Capture 0 Source (0=Left Mixer, 1=Channel 0/Bugged)
SNDCAP1CNT: Capture 1 Source (0=Right Mixer, 1=Channel 2/Bugged)
Bit2 Capture Repeat (0=Loop, 1=One-shot)
Bit3 Capture Format (0=PCM16, 1=PCM8)
Bit4-6 Not used (always zero)
Bit7 Capture Start/Status (0=Stop, 1=Start/Busy)
Capture Bugs
The NDS contains two hardware bugs which do occur when capturing data from
ch(a) (SNDCAPxCNT.Bit1=1), if so, either bug occurs depending on whether
ch(a)+ch(b) addition is enabled or disabled (SNDCAPxCNT.Bit0).
1) Both Negative Bug - SNDCAPxCNT Bit1=1, Bit0=0 (addition disabled)
Capture data is accidently set to -8000h if ch(a) and ch(b) are both <0.
Otherwise the correct capture result is returned, ie. plain ch(a) data,
not being affected by ch(b) (since addition is disabled).
Workaround: Ensure that ch(a) and/or ch(b) are >=0 (or disabled).
2) Overflow Bug - SNDCAPxCNT Bit1=1, Bit0=1 (addition enabled)
In this mode, Capture data isn't clipped to MinMax(-8000h,+7FFFh),
instead, it is ANDed with FFFFh, so the sign bit is lost if the
addition result ch(a)+ch(b) is less/greater than -8000h/+7FFFh.
Workaround: Reduce ch(a)/ch(b) volume or data to avoid overflows.
These bugs occur only for capture (speaker output remains intact), and they
occur only when capturing ch(a) (capturing mixer-output works flawless).
DS Sound Notes
--------------
Channel/Mixer Bit-Widths
Step Bits Min Max
0 Incoming PCM16 Data 16.0 -8000h +7FFFh
1 Volume Divider (div 1..16) 16.4 -8000h +7FFFh
2 Volume Factor (mul N/128) 16.11 -8000h +7FFFh
3 Panning (mul N/128) 16.18 -8000h +7FFFh
4 Rounding Down (strip 10bit) 16.8 -8000h +7FFFh
5 Mixer (add channel 0..15) 20.8 -80000h +7FFF0h
6 Master Volume (mul N/128/64) 14.21 -2000h +1FF0h
7 Strip fraction 14.0 -2000h +1FF0h
8 Add Bias (0..3FFh, def=200h) 15.0 -2000h+0 +1FF0h+3FFh
9 Clip (min/max 0h..3FFh) 10.0 0 +3FFh
Table shows integer.fractional bits, and min/max values (without fraction).
Capture Clipping/Rounding
Incoming ch(a) is NOT clipped, ch(a)+ch(b) may overflow (see Capture Bugs).
Incoming mixer data (20.8bits) is clipped to 16.8bits (MinMax -8000h..7FFFh).
For PCM8 capture format, the 16.8 bits are divided by 100h (=8.16 bits).
If the MSB of the fractional part is set, then data is rounded towards zero.
(Positive values are rounded down, negative values are rounded up.)
The fractional part is then discarded, and plain integer data is captured.
PSG Sound
The output volume equals to PCM16 values +7FFFh (HIGH) and -7FFFh (LOW).
PSG sound is always Infinite (the SOUNDxLEN Register, and the SOUNDxCNT Repeat
Mode bits have no effect). The PSG hardware doesn't support sound length,
sweep, or volume envelopes, however, these effects can be produced by software
with little overload (or, more typically, with enormous overload, depending on
the programming language used).
IMA-ADPCM Format
IMA-ADPCM is a Adaptive Differential Pulse Code Modulation (ADPCM) variant,
designed by International Multimedia Association (IMA), the format is used,
among others, in IMA-ADPCM compressed Windows .WAV files.
The NDS data consist of a 32bit header, followed by 4bit values (so each byte
contains two values, the first value in the lower 4bits, the second in upper 4
bits). The 32bit header contains initial values:
Bit0-15 Initial PCM16 Value (Pcm16bit = -7FFFh..+7FFF) (not -8000h)
Bit16-22 Initial Table Index Value (Index = 0..88)
Bit23-31 Not used (zero)
In theory, the 4bit values are decoded into PCM16 values, as such:
Diff = ((Data4bit AND 7)*2+1)*AdpcmTable[Index]/8 ;see rounding-error
IF (Data4bit AND 8)=0 THEN Pcm16bit = Max(Pcm16bit+Diff,+7FFFh)
IF (Data4bit AND 8)=8 THEN Pcm16bit = Min(Pcm16bit-Diff,-7FFFh)
Index = MinMax (Index+IndexTable[Data4bit AND 7],0,88)
In practice, the first line works like so (with rounding-error):
Diff = AdpcmTable[Index]/8
IF (data4bit AND 1) THEN Diff = Diff + AdpcmTable[Index]/4
IF (data4bit AND 2) THEN Diff = Diff + AdpcmTable[Index]/2
IF (data4bit AND 4) THEN Diff = Diff + AdpcmTable[Index]/1
And, a note on the second/third lines (with clipping-error):
Max(+7FFFh) leaves -8000h unclipped (can happen if initial PCM16 was -8000h)
Min(-7FFFh) clips -8000h to -7FFFh (possibly unlike windows .WAV files?)
Whereas, IndexTable[0..7] = -1,-1,-1,-1,2,4,6,8. And AdpcmTable [0..88] =
0007h,0008h,0009h,000Ah,000Bh,000Ch,000Dh,000Eh,0010h,0011h,0013h,0015h
0017h,0019h,001Ch,001Fh,0022h,0025h,0029h,002Dh,0032h,0037h,003Ch,0042h
0049h,0050h,0058h,0061h,006Bh,0076h,0082h,008Fh,009Dh,00ADh,00BEh,00D1h
00E6h,00FDh,0117h,0133h,0151h,0173h,0198h,01C1h,01EEh,0220h,0256h,0292h
02D4h,031Ch,036Ch,03C3h,0424h,048Eh,0502h,0583h,0610h,06ABh,0756h,0812h
08E0h,09C3h,0ABDh,0BD0h,0CFFh,0E4Ch,0FBAh,114Ch,1307h,14EEh,1706h,1954h
1BDCh,1EA5h,21B6h,2515h,28CAh,2CDFh,315Bh,364Bh,3BB9h,41B2h,4844h,4F7Eh
5771h,602Fh,69CEh,7462h,7FFFh
The closest way to reproduce the AdpcmTable with 32bit integer maths appears:
X=000776d2h, FOR I=0 TO 88, Table[I]=X SHR 16, X=X+(X/10), NEXT I
Table[3]=000Ah, Table[4]=000Bh, Table[88]=7FFFh, Table[89..127]=0000h
When using ADPCM and loops, set the loopstart position to the data part, rather
than the header. At the loop end, the SAD value is reloaded to the loop start
location, additionally index and pcm16 values are reloaded to the values that
have originally appeared at that location. Do not change the ADPCM loop start
position during playback.
Microphone Input
For Microphone (and Touchscreen) inputs, see
--> DS Touch Screen Controller (TSC)
Sound data is often stored in a SDAT file (with SSEQ, SSAR, SBNK, SWAR, STRM
blocks inside of the SDAT files). Samples can be stored in SWAV files (or be
contained in SWAR's inside of SDAT files).
--> DS Sound Files - SDAT (Sound Data Archive)
--> DS Sound Files - SSEQ (Sound Sequence)
--> DS Sound Files - SSAR (Sound Sequence Archive)
--> DS Sound Files - SBNK (Sound Bank)
--> DS Sound Files - SWAR (Sound Wave Archive)
--> DS Sound Files - SWAV (Sound Wave Data)
--> DS Sound Files - STRM (Sound Wave Stream)
Thanks: http://www.feshrine.net/hacking/doc/nds-sdat.php - 2007 by kiwi.ds
SDAT Header
000h 4 ID "SDAT" ;alike "CSAR" on 3DS
004h 2 Byte Order (FEFFh)
006h 2 Version (0100h)
008h 4 Total Filesize
00Ch 2 Header Size (usually 40h)
00Eh 2 Number of Blocks (usually 4 = SYMB+INFO+FAT+FILE) (or 3=no SYMB)
010h 4+4 SYMB Block (Offset from SDAT+0, Size) ;=0,0 if above is 3=no SYMB
018h 4+4 INFO Block (Offset from SDAT+0, Size) ;\
020h 4+4 FAT Block (Offset from SDAT+0, Size) ; always present
028h 4+4 FILE Block (Offset from SDAT+0, Size) ;/
030h 10h Padding to 20h-byte boundary (0)
The SYMB block exists in most SDAT files (except in some titles like Downhill
Jam and Over the Hedge).
Symbol Block (if present) (names for the corresponding items in INFO block)
000h 4 ID "SYMB"
004h 4 SYMB Block Size (rounded up to 4-byte boundary, unlike as in SDAT)
008h 4 File List SSEQ (Offset from SYMB+0) Sequences (songs)
00Ch 4 Folder List SSAR (Offset from SYMB+0) Sequence Archives (fx)
010h 4 File List BANK (Offset from SYMB+0) Banks
014h 4 File List SWAR (Offset from SYMB+0) Wave Archives (samples)
018h 4 File List Player (Offset from SYMB+0) Player (Group-related)
01Ch 4 File List Group (Offset from SYMB+0) Group (SSEQ+SSAR+BANK+SWAR)
020h 4 File List Player2 (Offset from SYMB+0) Player2 (Stream-related)
024h 4 File List STRM (Offset from SYMB+0) Wave Stream
028h 18h Reserved (0)
040h .. File/Folder Lists (see below)
.. .. File/Folder Name Strings (ASCII, terminated by 0)
.. .. Padding to 4-byte boundary (0)
File List's are having following format:
000h 4 Number of entries in this list (can be 0=None)
004h N*4 File Name (Offset from SYMB+0)
Folder List (for SSAR):
000h 4 Number of entries in this list (can be 0=None)
004h N*(4+4) SSAR "Folder Name" and SSEQ "File List" (Offset's from SYMB+0)
Info Block
000h 4 ID "INFO"
004h 4 INFO Block Size (same as in SDAT header)
008h 4 Info List SSEQ (Offset from INFO+0) Sequences (songs)
00Ch 4 Info List SSAR (Offset from INFO+0) Sequence Archives (fx)
010h 4 Info List BANK (Offset from INFO+0) Banks
014h 4 Info List SWAR (Offset from INFO+0) Wave Archives (samples)
018h 4 Info List Player (Offset from INFO+0) Player (Group-related)
01Ch 4 Info List Group (Offset from INFO+0) Group (SSEQ+SSAR+BANK+SWAR)
020h 4 Info List Player2 (Offset from INFO+0) Player2 (Stream-related)
024h 4 Info List STRM (Offset from INFO+0) Wave Stream
028h 18h Reserved (0)
.. .. Info Lists (see below)
.. .. Info Entries (see below)
.. .. Padding to 4-byte boundary (0)
Info List's are having following format:
000h 4 Number of entries in this list (can be 0=None)
004h N*4 Info Entries (Offset from INFO+0)
Group Info Entry (whatever, list of files that must be loaded to memory?)
000h 4 Number of items in this group
004h N*(4+4) Array (with ID+Index pairs)
ID values: 700h=SSEQ, 803h=SSAR, 601h=BANK, 402h=SWAR.
Index: Entry number in the corresponding SSEQ/SSAR/BANK/SWAR list.
FAT Block
000h 4 ID "FAT "
004h 4 FAT Block Size (same as in SDAT header) (0Ch+N*10h)
008h 4 Number of files
00Ch N*(4+4+8) File Entries (Offset from SDAT+0, Size, Zero)
The 8-byte Zero entries can be used for storing data at runtime.
File Block
000h 4 ID "FILE"
004h 4 FILE Block Size (same as in SDAT header)
008h 4 Number of files (same as in FAT block)
00Ch 4 Reserved (0)
010h .. Files (SSEQ,SSAR,SBNK,SWAR,STRM) (at offsets specified in FAT)
SSEQ Header
000h 4 ID "SSEQ" ;\
004h 2 Byte Order (FEFFh) ;
006h 2 Version (0100h) ; Main header
008h 4 Total Filesize ;
00Ch 2 Header Size (usually 10h) ;
00Eh 2 Number of Blocks (usually 1 = DATA) ;/
010h 4 ID "DATA" ;\
014h 4 Total Filesize, minus 10h ; Sub header
018h 4 Offset to data (from SSEQ+0) (1Ch) ;/
01Ch .. Arrays of sequence data.. ;-
NB. For the details of the SSEQ file, please refer to loveemu's sseq2mid
Description
A SSEQ can have at maximum 16 tracks, notes in the range of 0..127 (middle C is
60). Each quartet note has a fixed tick length of 48. Tempo in the range of
1..240 BPM (default is 120). The SSEQ will not be played correctly if tempo
higher than 240.
The SEQ player uses ARM7's Timer1 for timing. The ARM7's 4 Timers runs at 33MHz
(approximately 2^25). The SEQ player sets Timer1 reload value to 2728,
prescaler to F/64. So on about every 0.0052 sec (64*2728/33MHz) the SEQ Player
will be notified (1 cycle). As a quartet note has fixed tick value of 48, the
highest tempo that SEQ Player can handle is 240 BPM (60/(0.0052*48)).
During each cycle, the SEQ player adds the tempo value to a variable. Then it
checks if the value exceeds 240. If it does, the SEQ player subtracts 240 from
the variable, and process the SSEQ file. Using this method, the playback is not
very precise but the difference is too small to be noticed.
Take an example with tempo = 160 BPM, the SSEQ file is processed twice in 3
notifications.
cycle variable action
1 0 Add 160
2 160 Add 160
3 320 Subtract 240, process once, add 160
4 240 Subtract 240, process once, add 160
5 160 Add 160
6 320 Subtract 240, process once, add 160
7 240 Subtract 240, process once, add 160
8 160 Add 160
Events
ID Parameter Description
00h-7Fh Velocity: 1 byte [0..127]
Duration: Variable Length
NOTE-ON. Duration is expressed in tick.
48 for quartet note.
Usually it is NOT a multiple of 3.
80h Duration: Variable Length
REST. It tells the SSEQ-sequencer to wait for
a certain tick. Usually it is a multiple of 3.
81h Bank & Program Number:
Variable Length
bits[0..7] is the program number,
bits[8..14] is the bank number.
Bank change is seldomly found,
so usually bank 0 is used.
FEh 2 bytes Indicates which tracks are used.
Bit0 for track 0, ... Bit15 for track 15.
If the bit is set, the corresponding track is used.
Indication begin of multitrack. Must be in the
beginning of the first track to work. A series
of event 0x93 follows.
93h 4 bytes 1st byte is track number [0..15]
The other 3 bytes are the relative adress of track data.
Add nDataOffset (usually 0x1C) to find out the absolute address.
SSEQ is similar to MIDI in that track data are
stored one after one track. Unlike mod music.
94h JUMP Address: 3 bytes
(Add nDataOffset (usually 0x1C) to find out the absolute address.)
JUMP. A jump must be backward. So that the
song will loop forever.
95h CALL Address: 3 bytes
(Add nDataOffset (usually 0x1C) to find out the absolute address.)
A0h-BFh See loveemu's sseq2mid for more details.
Some arithmetic operations / comparions.
Affect how SSEQ is to be played.
C0h 1 byte PAN (0..127, middle is 64, uh?)
C1h 1 byte VOLUME (0..127)
C2h 1 byte MASTER VOLUME (0..127)
C3h 1 byte TRANSPOSE (Channel Coarse Tuning) (0..64 = 64..128 in MIDI)
C4h 1 byte PITCH BEND
C5h 1 byte PITCH BEND RANGE
C6h 1 byte TRACK PRIORITY
C7h 1 byte MONO/POLY (0=Poly, 1=Mono)
C8h 1 byte TIE (unknown) (0=Off, 1=On)
C9h 1 byte PORTAMENTO CONTROL
CAh 1 byte MODULATION DEPTH (0=Off, 1=On)
CBh 1 byte MODULATION SPEED
CCh 1 byte MODULATION TYPE (0=Pitch, 1=Volume, 2=Pan)
CDh 1 byte MODULATION RANGE
CEh 1 byte PORTAMENTO ON/OFF
CFh 1 byte PORTAMENTO TIME
D0h 1 byte ATTACK RATE
D1h 1 byte DECAY RATE
D2h 1 byte SUSTAIN RATE
D3h 1 byte RELEASE RATE
D4h 1 byte LOOP START (how many times to be looped)
D5h 1 byte EXPRESSION
D6h 1 byte PRINT VARIABLE (unknown)
E0h 2 byte MODULATION DELAY
E1h 2 byte TEMPO
E3h 2 byte SWEEP PITCH
FCh - LOOP END (for LOOP START)
FDh - RETURN from CALL command
FFh - EOT: End Of Track
SSAR Header
000h 4 ID "SSAR" ;\
004h 2 Byte Order (FEFFh) ;
006h 2 Version (0100h) ; Main header
008h 4 Total Filesize ;
00Ch 2 Header Size (usually 10h) ;
00Eh 2 Number of Blocks (usually 1 = DATA) ;/
010h 4 ID "DATA" ;\
014h 4 Total Filesize, minus 10h ;
018h 4 Offset to data (from SSAR+0) (20h+N*0Ch) ; Sub header
01Ch 4 Number of records ;
020h N*0Ch Records (12 bytes each) ;/
.. .. data... unknown content? alike SSEQ? ;-
SSAR Records
000h 4 nOffset ;relative offset of the archived SEQ file,
absolute offset = nOffset + SSAR::nDataOffset
004h 2 bnk ;bank
006h 1 vol ;volume
007h 1 cpr ;channel pressure
008h 1 ppr ;polyphonic pressure
009h 1 ply ;play
00Ah 2 reserved (0)
NB. Archived SSEQ files are not stored in sequence (order). So Rec[0].nOffset
may point to 0x100 but Rec[1].nOffset points to 0x40.
NB. Archived SSEQ files cannot be readily extracted from SSAR file because data
in one SSEQ may 'call' data in other SSEQ.
This seems to assign ADSR patterns to each note of each SWAV instrument...?
"A bank is linked to up to 4 SWAR files which contain the samples. It defines
the instruments which a SSEQ sequence can use. You may imagine SSEQ + SBNK +
SWAR are similar to module music created by trackers." uh?
SBNK Header
000h 4 ID "SBNK" ;\
004h 2 Byte Order (FEFFh) ;
006h 2 Version (0100h) ; Main header
008h 4 Total Filesize ;
00Ch 2 Header Size (usually 10h) ;
00Eh 2 Number of Blocks (usually 1 = DATA) ;/
010h 4 ID "DATA" ;\
014h 4 Total Filesize, minus 10h ;
018h 20h Reserved (0) (for use at runtime) ; Sub header
038h 4 Number of Instruments (SWAV's) ;
03Ch N*4 Instrument Records (1+2+1 bytes per instr.) ;/
... .. Instrument Data (depending of above records) ;-
Instrument Record
000h 1 fRecord ;can be either 0, 1..4, 16 or 17
001h 2 nOffset ;absolute offset of the data in file ;uh, misaligned?
003h 1 Reserved (0)
Articulation Data
. <-- max level (127)
/ \
/ \
/ '---------. <-- sustain level (0..127)
/ \
/ \
-----'---------------------'-- <-- min level (0)
Attack Decay Sustain Release
"The SEQ Player treats 0 as the 100% amplitude value and -92544 (723*128)
as the 0% amplitude value. The starting ampltitude is 0% (-92544)." uh?
"During the attack phase, in each cycle, the SSEQ Player calculates the new
amplitude value: amplitude value = attack rate * amplitude value / 255. The
attack phase stops when amplitude reaches 0." THAT IS... NON-LINEAR attack?
"During the decay phase, in each cycle, the SSEQ Player calculates the new
amplitude value: amplitude value = amplitude value - decay rate.
Note the starting amplitude value is 0. The decay phase stops when
amplitude reaches sustain level." THAT IS... LINEAR decay/release?
SWAV Header (present only in standalone SWAV files) (not in SWAR archives)
000h 4 ID "SWAV" ;\
004h 2 Byte Order (FEFFh) ;
006h 2 Version (0100h) ; Main header
008h 4 Total Filesize ;
00Ch 2 Header Size (usually 10h) ;
00Eh 2 Number of Blocks (usually 1 = DATA) ;/
010h 4 ID "DATA" ;\Sub header
014h 4 Total Filesize, minus 10h ;/
018h .. Sample block (see below)
Note: System Flaw has a lot of SWAV files (instead of using SWAR archives).
STRM Header
000h 4 ID "STRM" ;\
004h 2 Byte Order (FEFFh) ;
006h 2 Version (0100h) ; Main header
008h 4 Total Filesize ;
00Ch 2 Header Size (usually 10h) ;
00Eh 2 Number of Blocks (usually 2 = HEAD+DATA) ;/
010h 4 ID "HEAD" ;\
014h 4 Size of HEAD structure (uh, this is... 50h?) ;
018h 1 Type (0=PCM8, 1=PCM16, 2=IMA-ADPCM) ; Sub header
019h 1 Loop flag (?=TRUE|FALSE) ;uh? ;
01Ah 1 Channels (?=What) ;mono/stereo? ;
01Bh 1 Unknown (always 0) ;
01Ch 2 Sampling Rate (perhaps resampled from original) ;
01Eh 2 Time (1.0 / rate * ARM7_CLOCK / 32) ;
[ARM7_CLOCK: 33.513982MHz/2 = 1.6756991e7] ;
020h 4 Loop Offset (samples) ;
024h 4 Number of Samples ;
028h 4 Wave Data Offset (always 68h) ;
02Ch 4 Number of Blocks (per what?) ;
030h 4 Block Length (per Channel) ;
034h 4 Samples Per Block (per Channel) ;
038h 4 Last Block Length (per Channel) ;
03Ch 4 Samples Per Last Block (per Channel) ;
040h 20h Reserved (always 0) ;/
060h 4 ID "DATA" ;\Data header
064h 4 Data Size (8+N ?) ;/
068h N Wave Data blocks... ;-Sample data
Mono blocks are ordered: Block1, Block2, Block3, etc.
Stereo blocks are ordered: LeftBlock1, RightBlock1, LeftBlock2, etc.
DS DMA Transfers
----------------
The DS includes four DMA channels for each CPU (ie. eight channels in total),
which are working more or less the same as on GBA:
--> GBA DMA Transfers
All NDS9 and NDS7 DMA Registers are R/W. The gamepak bit (Bit 27) has been
removed (on the NDS9 the bit is used to expand the mode setting to 3bits).
NDS9 DMA
Word count of all channels is expanded to 21bits (max 1..1FFFFFh units, or
0=200000h units), and SAD/DAD registers for all channels support ranges of
0..0FFFFFFEh. The transfer modes (DMACNT Bit27-29) are:
0 Start Immediately
1 Start at V-Blank
2 Start at H-Blank (paused during V-Blank)
3 Synchronize to start of display
4 Main memory display
5 DS Cartridge Slot
6 GBA Cartridge Slot
7 Geometry Command FIFO
NDS7 DMA
Word Count, SAD, and DAD are R/W, aside from that they do have the same
restrictions as on GBA (max 4000h or 10000h units, some addresses limited to
0..07FFFFFEh). DMACNT Bit27 is unused on NDS7. The transfer modes (DMACNT
Bit28-29) are:
0 Start Immediately
1 Start at V-Blank
2 DS Cartridge Slot
3 DMA0/DMA2: Wireless interrupt, DMA1/DMA3: GBA Cartridge Slot
DS Timers
---------
Same as GBA, except F = 33.513982 MHz (for both NDS9 and NDS7).
--> GBA Timers
Both NDS9 and NDS7 have four Timers each, eight Timers in total.
The NDS sound controller is having its own frequency generators (unlike GBA,
which needed to use Timers to drive channel A/B sounds).
DS Interrupts
-------------
380FFC0h - DSi7 only - Extra IRQ Check Bits for IE2/IF2 (hardcoded RAM addr)
Same as the above 380FFF8h value, but for new IE2/IF2 registers, intended for
use with IntrWait and VBlankIntrWait functions. However, that functions are
BUGGED on DSi and won't actually work in practice (they do support only the new
380FFC0h bits, but do accidently ignore the old 380FFF8h bits).
DS Maths
--------
Division Overflows
Overflows occur on "DIV0" and "-MAX/-1" (eg. -80000000h/-1 in 32bit mode):
DIV0 --> REMAIN=NUMER, RESULT=+/-1 (with sign opposite of NUMER)
-MAX/-1 --> RESULT=-MAX (instead +MAX)
On overflows in 32bit/32bit=32bit mode: the upper 32bit of the sign-expanded
32bit result are inverted. This feature produces a correct 64bit (+MAX) result
in case of the incorrect 32bit (-MAX) result. The feature also applies on DIV0
errors (which makes the sign-expanded 64bit result even more messed-up than the
normal 32bit result).
The DIV0 flag in DIVCNT.14 indicates DENOM=0 errors (it does not indicate
"-MAX/-1" errors). The DENOM=0 check relies on the full 64bit value (so, in
32bit mode, the flag works only if the unused upper 32bit of DENOM are zero).
IRQ Notes
Push all DIV/SQRT values (parameters and control registers) when using DIV/SQRT
registers on interrupt level, and, after restoring them, be sure to wait until
the busy flag goes off, before leaving the IRQ handler.
BIOS Notes
The NDS9 and NDS7 BIOSes additionally contain software based division and
square root functions, which are NOT using above hardware registers (even the
NDS9 functions are raw software).
Timing Notes
The Div/Sqrt timings are counted in 33.51MHz units. Although the calculations
are quite fast, mind that reading/writing the result/parameter registers takes
up additional clock cycles (especially due to the PENALTY cycle glitch for
non-sequential accesses; parts of that problem can be eventually bypassed by
using sequential STMIA/LDMIA opcodes) (nethertheless, in some cases, software
may be actually faster than the hardware registers; eg. for small 8bit numbers;
that of course NOT by using the BIOS software functions which are endless
inefficient).
IPCFIFO Notes
When IPCFIFOCNT.15 is disabled: Writes to IPCFIFOSEND are ignored (no data is
stored in the FIFO, the error bit doesn't get set though), and reads from
IPCFIFORECV return the oldest FIFO word (as usually) (but without removing the
word from the FIFO).
When the Receive FIFO is empty: Reading from IPCFIFORECV returns the most
recently received word (if any), or ZERO (if there was no data, or if the FIFO
was cleared via IPCFIFOCNT.3), and, in either case the error bit gets set.
The Fifo-IRQs are edge triggered, IF.17 gets set when the condition
"(IPCFIFOCNT.2 AND IPCFIFOCNT.0)" changes from 0-to-1, and IF.18 gets set when
"(IPCFIFOCNT.10 AND NOT IPCFIFOCNT.8)" changes from 0-to-1. The IRQ flags can
be acknowledged even while that conditions are true.
DS Keypad
---------
For the GBA-buttons: Same as GBA, both ARM7 and ARM9 have keyboard input
registers, and each its own keypad IRQ control register.
--> GBA Keypad Input
The DS doesn't have a Serial Link Port Socket, however, internally, the NDS7
contains the complete set of Serial I/O Ports, as contained in the GBA:
--> GBA Communication Ports
In GBA mode, the ports are working as on real GBA (as when no cable is
connected). In NDS mode, the ports are even containing some additional bits:
RCNT
RCNT (4000134h) should be set to 80xxh (general purpose mode) before accessing
EXTKEYIN (4000136h) or RTC (4000138h). No idea why (except when using
RTC/SI-interrupt).
DS Serial Port
The SI line is labeled "INT" on the NDS mainboard, it is connected to Pin 1 of
the RTC chip (ie. the /INT interrupt pin).
I have no idea where to find SO, SC, and SD. I've written a test proggy that
pulsed all four RCNT bits - but all I could find was the SI signal. However,
the BIOS contains some code that uses SIO normal mode transfers (for the debug
version), so at least SI, SO, SC should exist...?
MAYBE that three signals are somehow replaced by EXTKEYIN bit0,1,3?
NDS
Seiko Instruments Inc. S-35180 (compatible with S-35190A)
Miniature 8pin RTC with 3-wire serial bus
DSi
Seiko S-35199A01 (12pin BGA, with some extra functions like FOUT and Alarm
Date)
Command Register
Command Register
Fwd Rev
0 7 Fixed Code (must be 0)
1 6 Fixed Code (must be 1)
2 5 Fixed Code (must be 1)
3 4 Fixed Code (must be 0, or, DSi only: 1=Extended Command)
4-6 3-1 Command
Fwd Rev Parameter bytes (read/write access)
0 0 1 byte, status register 1
4 1 1 byte, status register 2
2 2 7 bytes, date & time (year,month,day,day_of_week,hh,mm,ss)
6 3 3 bytes, time (hh,mm,ss)
1* 4* 1 byte, int1, frequency duty setting
1* 4* 3 bytes, int1, alarm time 1 (day_of_week, hour, minute)
5 5 3 bytes, int2, alarm time 2 (day_of_week, hour, minute)
3 6 1 byte, clock adjustment register
7 7 1 byte, free register
Extended command (when above "fourth bit" was set, DSi only)
Fwd Rev Parameter bytes (read/write access)
0 0 3 byte, up counter (msw,mid,lsw) (read only)
4 1 1 byte, FOUT register setting 1
2 2 1 byte, FOUT register setting 2
6 3 reserved
1 4 3 bytes, alarm date 1 (year,month,day)
5 5 3 bytes, alarm date 2 (year,month,day)
3 6 reserved
7 7 reserved
7 0 Parameter Read/Write Access (0=Write, 1=Read)
* INT1: Type and number of parameters depend on INT1 setting in stat reg2.
The "Fwd" bit numbers and command values for LSB-first command transfers (ie.
both commands and parameters use the same bit-order).
The "Rev" numbers/values are for MSB-first command transfers (ie. commands
using opposite bit-order than parameters, as being suggested by Seiko).
Date Registers
Year Register
0-7 R/W Year (BCD 00h..99h = 2000..2099)
Month Register
0-4 R/W Month (BCD 01h..12h = January..December)
5-7 - Not used (always zero)
Day Register
0-5 R/W Day (BCD 01h..28h,29h,30h,31h, range depending on month/year)
6-7 - Not used (always zero)
Day of Week Register (septenary counter)
0-2 R/W Day of Week (00h..06h, custom assignment, usually 0=Monday?)
3-7 - Not used (always zero)
Time Registers
Hour Register
0-5 R/W Hour (BCD 00h..23h in 24h mode, or 00h..11h in 12h mode)
6 * AM/PM (0=AM before noon, 1=PM after noon)
* 24h mode: AM/PM flag is read only (PM=1 if hour = 12h..23h)
* 12h mode: AM/PM flag is read/write-able
* 12h mode: Observe that 12 o'clock is defined as 00h (not 12h)
7 - Not used (always zero)
Minute Register
0-6 R/W Minute (BCD 00h..59h)
7 - Not used (always zero)
Second Register
0-6 R/W Minute (BCD 00h..59h)
7 - Not used (always zero)
Interrupt
There's only one /INT signal, shared for both INT1 and INT2.
In the NDS, it is connected to the SI-input of the SIO unit (and so, also
shared with SIO interrupts). To enable the interrupt, RCNT should be set to
8144h (Bit14-15=General Purpose mode, Bit8=SI Interrupt Enable, Bit6,2=SI
Output/High).
The Output/High settings seems to be used as pullup (giving faster reactions on
low-to-high transitions) (nethertheless, in most cases it seems to be also
working okay as Input, ie. with RCNT=8100h).
The RCNT interrupt is generated on high-to-low transitions on the SI line (but
only if the IRQ is enabled in RCNT.8, and only if RCNT is set to general
purpose mode) (note: changing RCNT.8 from off-to-on does NOT generate IRQs,
even when SI is LOW).
Pin-Outs
1 /INT 8 VDD
2 XOUT 7 SIO
3 XIN 6 /SCK
4 GND 5 CS
Notes/Glitches
SPICNT Bits 12,13 appear to be unused (always zero), although the BIOS
(attempts to) set Bit13=1, and Bit12=Bit11 when accessing the firmware.
The SPIDATA register is restricted to 8bit, so that only each 2nd byte will
appear in SPIDATA when attempting to use the bugged-16bit mode.
Channel
0 Temperature 0 (requires calibration, step 2.1mV per 1'C accuracy)
1 Touchscreen Y-Position (somewhat 0B0h..F20h, or FFFh=released)
2 Battery Voltage (not used, connected to GND in NDS, always 000h)
3 Touchscreen Z1-Position (diagonal position for pressure measurement)
4 Touchscreen Z2-Position (diagonal position for pressure measurement)
5 Touchscreen X-Position (somewhat 100h..ED0h, or 000h=released)
6 AUX Input (connected to Microphone in the NDS)
7 Temperature 1 (difference to Temp 0, without calibration, 2'C accuracy)
All channels can be accessed in Single-Ended mode.
In differential mode, only channel 1,3,4,5 (X,Z1,Z2,Y) can be accessed.
On AK4148AVT, channel 6 (AUX) is split into two separate channels, IN1 and IN2,
separated by Bit2 (Reference Select). IN1 is selected when Bit2=1, IN2 is
selected when Bit2=0 (despite of the Bit2 settings, both IN1 and IN2 are using
single ended more). On the NDS-Lite, IN1 connects to the mircrophone (as on
original NDS), and the new IN2 input is simply wired to VDD3.3 (which is equal
to the external VREF voltage, so IN2 is always FFFh).
Reply Data
The following reply data is received (via Input line) after the Command byte
has been transferred: One dummy bit (zero), followed by the 8bit or 12bit
conversion result (MSB first), followed by endless padding (zero).
Note: The returned ADC value may become unreliable if there are longer delays
between sending the command, and receiving the reply byte(s).
Touchscreen Position
Read the X and Y positions in 12bit differential mode, then convert the
touchscreen values (adc) to screen/pixel positions (scr), as such:
scr.x = (adc.x-adc.x1) * (scr.x2-scr.x1) / (adc.x2-adc.x1) + (scr.x1-1)
scr.y = (adc.y-adc.y1) * (scr.y2-scr.y1) / (adc.y2-adc.y1) + (scr.y1-1)
The X1,Y1 and X2,Y2 calibration points are found in Firmware User Settings,
--> DS Firmware User Settings
scr.x1,y1,x2,y2 are originated at 1,1 (converted to 0,0 by above formula).
Touchscreen Notes
It may be impossible to press locations close to the screen borders.
When pressing two or more locations the TSC values will be somewhere in the
middle of these locations.
The TSC values may be garbage if the screen becomes newly pressed or released,
to avoid invalid inputs: read TSC values at least two times, and ignore BOTH
positions if ONE position was invalid.
Pin-Outs
________
VCC 1|o |16 DCLK
X+ 2| |15 /CS
Y+ 3| TSC |14 DIN
X- 4| 2046 |13 BUSY
Y- 5| |12 DOUT
GND 6| |11 /PENIRQ
VBAT 7| |10 IOVDD
AUX 8|________|9 VREF
For AK4181AVT, same pins as above, except that IOVDD replaced by the new IN2
input, the pin is wired to VDD3.3 (so IN2 is always equal to VREF, which is
wired to VDD3.3, too) (and AUX is renamed to IN1, and is kept used for MIC
input).
DS Power Control
----------------
The DS contains several Power Managment functions, some accessed via I/O ports
(described below), and some accessed via SPI bus:
--> DS Power Management Device
Main Memory
The DS Main Memory is 2Mx16bit (4MByte), 1.8V Pseudo SRAM (PSRAM); all Dynamic
RAM refresh is handled internally, the chip doesn't require any external
refresh signals, and alltogether behaves like Static RAM. Non-sequential access
time is 70ns, sequential (burst) access time is 12ns.
Fujitsu 82DBS02163C-70L
The Configuration Register (CR) can be written to by the following sequence:
LDRH R0,[27FFFFEh] ;read one value
STRH R0,[27FFFFEh] ;write should be same value as above
STRH R0,[27FFFFEh] ;write should be same value as above
STRH R0,[27FFFFEh] ;write any value
STRH R0,[27FFFFEh] ;write any value
LDRH R0,[2400000h+CR*2] ;read, address-bits are defining new CR value
Do not access any other Main Memory addresses during above sequence (ie.
disable interrupts, and do not execute the sequence by code located in Main
Memory). The CR value is write-only. The CR bits are:
Bit Expl.
0-6 Reserved (Must be 7Fh)
7 Write Control
0=WE Single Clock Pulse Control without Write Suspend Function
1=WE Level Control with Write Suspend Function)
Burst Read/Single Write is not supported at WE Single Clock Mode.
8 Reserved (Must be 1)
9 Valid Clock Edge (0=Falling Edge, 1=Rising Edge)
10 Single Write (0=Burst Read/Burst Write, 1=Burst Read/Single Write)
11 Burst Sequence (0=Reserved, 1=Sequential)
12-14 Read Latency (1=3 clocks, 2=4 clocks, 3=5 clocks, other=Reserved)
15 Mode
0=Synchronous: Burst Read, Burst Write
1=Asynchronous: Page Read, Normal Write
In Mode 1 (Async), only the Partial Size bits are used,
all other bits, CR bits 0..18, must be "1".
16-18 Burst Length (2=8 Words, 3=16Words, 7=Continous, other=Reserved)
19-20 Partial Size (0=1MB, 1=512KB, 2=Reserved, 3=Deep/0 bytes)
The Power Down mode is entered by setting CE2=LOW, this can be probably done by
setting EXMEMCNT Bit14 to zero.
ST Microelectronics M69AB048BL70ZA8
The chip name decodes as PSRAM (M96), Asynchronous (A), 1.8V Burst (B), 2Mx16
(048), Two Chip Enables (B), Low Leakage (L), 70ns (70), Package (ZA),
-30..+85'C (8).
There are three data sheets for different PSRAM chips available at www.st.com
(unfortunately none for M69AB048BL70ZA8), each using different memory control
mechanisms.
NDS9 BIOS
The NDS9 BIOS contains the following Main Memory initialization code, that
method doesn't match up with any ST (nor Fujitsu) data sheets that I've seen.
At its best, it looks like a strange (and presumably non-functional) mix-up of
different ST control methods.
STRH 2000h,[4000204h] ;EXMEMCNT, enable RAM, async mode
LDRH R0,[27FFFFEh]
STRH R0,[27FFFFEh]
STRH R0,[27FFFFEh]
STRH FFDFh,[27FFFFEh]
STRH E732h,[27FFFFEh]
LDRH R0,[27E57FEh]
STRH 6000h,[4000204h] ;EXMEMCNT, enable RAM, normal mode
DS Backwards-compatible GBA-Mode
--------------------------------
When booting a 32pin GBA cartridge, the NDS is automatically switched into GBA
mode, in that mode all NDS related features are disabled, and the console
behaves (almost) like a GBA.
NDS Devkit
In Nintendo's devkit, debug messages are handled in file "os_printf.c", this
file detects the available hardware/software based debug I/O ports, and
redirects the [OS_PutString] vector to the corresponding string_out function
(eg. to OS_PutStringAris for writing a 00h-terminated string to port 4FFF000h).
With some minimal efforts, this could be redirected to the corresponding no$gba
debug I/O ports.
Cartridges
--> DS Cartridge Header
--> DS Cartridge Secure Area
--> DS Cartridge Icon/Title
--> DS Cartridge Protocol
--> DS Cartridge Backup
--> DS Cartridge NAND
--> DS Cartridge I/O Ports
--> DS Cartridge NitroROM and NitroARC File Systems
--> DS Cartridge Unknown Commands
--> DS Cartridge PassMe/PassThrough
--> DS Cartridge GBA Slot
Add-Ons
--> DS Cart Rumble Pak
--> DS Cart Slider with Rumble
--> DS Cart Expansion RAM
--> DS Cart Infrared/Pedometers
--> DS Cart Unknown Extras
Special Cartridges
--> DS Cart Cheat Action Replay DS
--> DS Cart Cheat Codebreaker DS
--> DS Cart DLDI Driver
Encryption
--> DS Encryption by Gamecode/Idcode (KEY1)
--> DS Encryption by Random Seed (KEY2)
DS Cartridge Header
-------------------
Header Overview (loaded from ROM Addr 0 to Main RAM 27FFE00h on Power-up)
Address Bytes Expl.
000h 12 Game Title (Uppercase ASCII, padded with 00h)
00Ch 4 Gamecode (Uppercase ASCII, NTR-<code>) (0=homebrew)
010h 2 Makercode (Uppercase ASCII, eg. "01"=Nintendo) (0=homebrew)
012h 1 Unitcode (00h=NDS, 02h=NDS+DSi, 03h=DSi) (bit1=DSi)
013h 1 Encryption Seed Select (00..07h, usually 00h)
014h 1 Devicecapacity (Chipsize = 128KB SHL nn) (eg. 7 = 16MB)
015h 7 Reserved (zero filled)
01Ch 1 Reserved (zero) (except, used on DSi)
01Dh 1 NDS Region (00h=Normal, 80h=China, 40h=Korea) (other on DSi)
01Eh 1 ROM Version (usually 00h)
01Fh 1 Autostart (Bit2: Skip "Press Button" after Health and Safety)
(Also skips bootmenu, even in Manual mode & even Start pressed)
020h 4 ARM9 rom_offset (4000h and up, align 1000h)
024h 4 ARM9 entry_address (2000000h..23BFE00h)
028h 4 ARM9 ram_address (2000000h..23BFE00h)
02Ch 4 ARM9 size (max 3BFE00h) (3839.5KB)
030h 4 ARM7 rom_offset (8000h and up)
034h 4 ARM7 entry_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
038h 4 ARM7 ram_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
03Ch 4 ARM7 size (max 3BFE00h, or FE00h) (3839.5KB, 63.5KB)
040h 4 File Name Table (FNT) offset
044h 4 File Name Table (FNT) size
048h 4 File Allocation Table (FAT) offset
04Ch 4 File Allocation Table (FAT) size
050h 4 File ARM9 overlay_offset
054h 4 File ARM9 overlay_size
058h 4 File ARM7 overlay_offset
05Ch 4 File ARM7 overlay_size
060h 4 Port 40001A4h setting for normal commands (usually 00586000h)
064h 4 Port 40001A4h setting for KEY1 commands (usually 001808F8h)
068h 4 Icon/Title offset (0=None) (8000h and up)
06Ch 2 Secure Area Checksum, CRC-16 of [[020h]..00007FFFh]
06Eh 2 Secure Area Delay (in 131kHz units) (051Eh=10ms or 0D7Eh=26ms)
070h 4 ARM9 Auto Load List Hook RAM Address (?) ;\endaddr of auto-load
074h 4 ARM7 Auto Load List Hook RAM Address (?) ;/functions
078h 8 Secure Area Disable (by encrypted "NmMdOnly") (usually zero)
080h 4 Total Used ROM size (remaining/unused bytes usually FFh-padded)
084h 4 ROM Header Size (4000h)
088h 4 Unknown, some rom_offset, or zero? (DSi: slightly different)
08Ch 8 Reserved (zero filled; except, [88h..93h] used on DSi)
094h 2 NAND end of ROM area ;\in 20000h-byte units (DSi: 80000h-byte)
096h 2 NAND start of RW area ;/usually both same address (0=None)
098h 18h Reserved (zero filled)
0B0h 10h Reserved (zero filled; or "DoNotZeroFillMem"=unlaunch fastboot)
0C0h 9Ch Nintendo Logo (compressed bitmap, same as in GBA Headers)
15Ch 2 Nintendo Logo Checksum, CRC-16 of [0C0h-15Bh], fixed CF56h
15Eh 2 Header Checksum, CRC-16 of [000h-15Dh]
160h 4 Debug rom_offset (0=none) (8000h and up) ;only if debug
164h 4 Debug size (0=none) (max 3BFE00h) ;version with
168h 4 Debug ram_address (0=none) (2400000h..27BFE00h) ;SIO and 8MB
16Ch 4 Reserved (zero filled) (transferred, and stored, but not used)
170h 90h Reserved (zero filled) (transferred, but not stored in RAM)
200h E00h Reserved (zero filled) (usually not transferred)
DSi Cartridges are using an extended cartridge header,
--> DSi Cartridge Header
Some of that new/changed DSi header entries are important even in NDS mode:
- On DSi, ARM9/ARM7 areas are restricted to 2.75MB (instead 3.8MB on real NDS)
- New NDS titles must have RSA signatures (and old titles must be in whitelist)
For more info about CRC-16, see description of GetCRC16 BIOS function,
--> BIOS Misc Functions
For the Logo checksum, the BIOS verifies only [15Ch]=CF56h, it does NOT verify
the actual data at [0C0h-15Bh] (nor it's checksum), however, the data is
verified by the firmware.
NDS Gamecodes
This is the same code as the NTR-UTTD (NDS) or TWL-UTTD (DSi) code which is
printed on the package and sticker on (commercial) cartridges (excluding the
leading "NTR-" or "TWL-" part).
U Unique Code (usually "A", "B", "C", or special meaning)
TT Short Title (eg. "PM" for Pac Man)
D Destination/Language (usually "J" or "E" or "P" or specific language)
The first character (U) is usually "A" or "B", in detail:
A NDS common games
B NDS common games
C NDS common games
D DSi-exclusive games
H DSiWare (system utilities and browser) (eg. HNGP=browser)
I NDS and DSi-enhanced games with built-in Infrared port
K DSiWare (dsiware games and flipnote) (eg. KGUV=flipnote)
N NDS nintendo channel demo's japan (NTR-NTRJ-JPN)
T NDS many games
U NDS and DSi uncommon extra hardware (eg. NAND, ram, microSD, TV, azimuth)
V DSi-enhanced games
Y NDS many games
The second/third characters (TT) are:
Usually an abbreviation of the game title (eg. "PM" for "Pac Man") (unless
that gamecode was already used for another game, then TT is just random)
The fourth character (D) indicates Destination/Language:
A Asian E English/USA I Italian M Swedish Q Danish U Australian
B N/A F French J Japanese N Nor R Russian V EUR+AUS
C Chinese G N/A K Korean O Int S Spanish W..Z Europe #3..5
D German H Dutch L USA #2 P Europe T USA+AUS
Secure Area ID
The first 8 bytes of the secure area are containing the Secure Area ID, the ID
is required (verified by BIOS boot code), the ID value changes during boot
process:
Value Expl.
"encryObj" raw ID before encryption (raw ROM-image)
(encrypted) encrypted ID after encryption (encrypted ROM-image)
"encryObj" raw ID after decryption (verified by BIOS boot code)
E7FFDEFFh,E7FFDEFFh destroyed ID (overwritten by BIOS after verify)
If the decrypted ID does match, then the BIOS overwrites the first 8 bytes by
E7FFDEFFh-values (ie. only the ID is destroyed). If the ID doesn't match, then
the first 800h bytes (2K) are overwritten by E7FFDEFFh-values.
DS Cartridge Icon/Title
-----------------------
The ROM offset of the Icon/Title is defined in CartHdr[68h]. The size was
originally implied by the size of the original Icon/Title structure rounded to
200h-byte sector boundary (ie. A00h bytes for Version 1 or 2), however, later
DSi carts are having a size entry at CartHdr[208h] (usually 23C0h).
If it is present (ie. if CartHdr[68h]=nonzero), then Icon/Title are displayed
in the bootmenu.
0000h 2 Version (0001h, 0002h, 0003h, or 0103h)
0002h 2 CRC16 across entries 0020h..083Fh (all versions)
0004h 2 CRC16 across entries 0020h..093Fh (Version 0002h and up)
0006h 2 CRC16 across entries 0020h..0A3Fh (Version 0003h and up)
0008h 2 CRC16 across entries 1240h..23BFh (Version 0103h and up)
000Ah 16h Reserved (zero-filled)
0020h 200h Icon Bitmap (32x32 pix) (4x4 tiles, 4bit depth) (4x8 bytes/tile)
0220h 20h Icon Palette (16 colors, 16bit, range 0000h-7FFFh)
(Color 0 is transparent, so the 1st palette entry is ignored)
0240h 100h Title 0 Japanese (128 characters, 16bit Unicode)
0340h 100h Title 1 English ("")
0440h 100h Title 2 French ("")
0540h 100h Title 3 German ("")
0640h 100h Title 4 Italian ("")
0740h 100h Title 5 Spanish ("")
0840h 100h Title 6 Chinese ("") (Version 0002h and up)
0940h 100h Title 7 Korean ("") (Version 0003h and up)
0A40h 800h Zerofilled (probably reserved for Title 8..15)
Below for animated DSi icons only (Version 0103h and up):
1240h 1000h Icon Animation Bitmap 0..7 (200h bytes each, format as above)
2240h 100h Icon Animation Palette 0..7 (20h bytes each, format as above)
2340h 80h Icon Animation Sequence (16bit tokens)
Unused/padding bytes:
0840h 1C0h Unused/padding (FFh-filled) in Version 0001h
0940h C0h Unused/padding (FFh-filled) in Version 0002h
23C0h 40h Unused/padding (FFh-filled) in Version 0103h
Versions
0001h = Original
0002h = With Chinese Title
0003h = With Chinese+Korean Titles
0103h = With Chinese+Korean Titles and animated DSi icon
Title Strings
Usually, for non-multilanguage games, the same (english) title is stored in all
title entries. The title may consist of ASCII characters 0020h-007Fh, character
000Ah (linefeed), and should be terminated/padded by 0000h.
The whole text should not exceed the dimensions of the DS cart field in the
bootmenu (the maximum number of characters differs due to proportional font).
The title is usually split into a primary title, optional sub-title, and
manufacturer, each separated by 000Ah character(s). For example: "America",
000Ah, "The Axis of War", 000Ah, "Cynicware", 0000h.
DS Cartridge Protocol
---------------------
Cartridge Reset
The /RES Pin switches the cartridge into unencrypted mode. After reset, the
first two commands (9Fh and 00h) are transferred at 4MB/s CLK rate.
3Diiijjjxkkkkkxxh (0) - Activate KEY1 Encryption Mode and Unlock DSi Mode
Same as command 3Ch (but with different initial 1048h-byte encryption values),
and works only on DSi carts. Command 3Dh is unlocking two features on DSi
carts:
1) Command 2bbbbiiijjjkkkkkh loads ARM9i secure area (instead of ARM9 area)
2) Command B7aaaaaaaa000000h allows to read the 'whole' cartridge space
Without command 3Dh, DSi carts will allow to read only the first some megabytes
(for example, the first 11 Mbyte of the System Flaw cartridge), and the
remaining memory returns mirrors of "addr=8000h+(addr AND 1FFh)").
Note: After reset, the cartridge protocol allows to send only either one of the
3Ch/3Dh commands (DSi consoles can control the cartridge reset pin, so they can
first send 3Ch and read the normal secure area, then issue a reset and 3Dh and
read the DSi secure area) (on a NDS one could do the same by ejecting/inserting
the cartridge instead of toggling the reset pin).
DS Cartridge Backup
-------------------
SPI Bus Backup Memory is accessed via Ports 40001A0h and 40001A2h, see
--> DS Cartridge I/O Ports
Commands
For all EEPROM and FRAM types:
06h WREN Write Enable Cmd, no parameters
04h WRDI Write Disable Cmd, no parameters
05h RDSR Read Status Register Cmd, read repeated status value(s)
01h WRSR Write Status Register Cmd, write one-byte value
9Fh RDID Read JEDEC ID (not supported on EEPROM/FLASH, returns FFh-bytes)
For 0.5K EEPROM (8+1bit Address):
03h RDLO Read from Memory 000h-0FFh Cmd, addr lsb, read byte(s)
0Bh RDHI Read from Memory 100h-1FFh Cmd, addr lsb, read byte(s)
02h WRLO Write to Memory 000h-0FFh Cmd, addr lsb, write 1..MAX byte(s)
0Ah WRHI Write to Memory 100h-1FFh Cmd, addr lsb, write 1..MAX byte(s)
For 8K..64K EEPROM and for FRAM (16bit Address):
03h RD Read from Memory Cmd, addr msb,lsb, read byte(s)
02h WR Write to Memory Cmd, addr msb,lsb, write 1..MAX byte(s)
For 128K EEPROM (24bit Address):
As above, but with 24bit addr msb,mid,lsb ?
Note: MAX = Page Size (see above chip list) (no limit for FRAM).
For FLASH backup, commands should be same as for Firmware FLASH memory:
--> DS Firmware Serial Flash Memory
A few NDS/DSi carts are sharing the SPI bus for FLASH and Infrared, this
requires a 00h-prefix byte for FLASH access, with slower 1MHz SPI clock and
delays, see:
--> DS Cart Infrared/Pedometers
Status Register
0 WIP Write in Progress (1=Busy) (Read only) (always 0 for FRAM chips)
1 WEL Write Enable Latch (1=Enable) (Read only, except by WREN,WRDI)
2-3 WP Write Protect (0=None, 1=Upper quarter, 2=Upper Half, 3=All memory)
For 0.5K EEPROM:
4-7 ONEs Not used (all four bits are always set to "1" each)
For 8K..64K EEPROM and for FRAM:
4-6 ZERO Not used (all three bits are always set to "0" each)
7 SRWD Status Register Write Disable (0=Normal, 1=Lock) (Only if /W=LOW)
WEL gets reset on Power-up, WRDI, WRSR, WRITE/LO/HI, and on /W=LOW.
The WRSR command allows to change ONLY the two WP bits, and the SRWD bit (if
any), these bits are non-volatile (remain intact during power-down),
respectively, the WIP bit must be checked to sense WRSR completion.
DS Cartridge NAND
-----------------
SLC-NAND is used in at least three NDS/DSi games. The ROM Chip ID has bit3 in
4th byte set.
ECh,7Fh,00h,88h NDS Samsung 128MB NAND (eg. Warioware D.I.Y., NTR-UORE)
ECh,7Fh,01h,88h NDS Samsung 128MB NAND (eg. Jam with the Band, NTR-UXBP)
ECh,7Fh,00h,E8h DSi Samsung 128MB NAND (eg. Face Training, TWL-USKV)
In the cart header, the 1st byte of the Gamecode is "U" (that "U" is also used
for a few other carts with "uncommon" hardware), and header entries [094h,096h]
indicate the end of the ROM region and start of RW region (in 128Kbyte units
for NDS, or 512Kbyte units for DSi; exception: the oldest NAND title (japanese
version of Jam with the Band) did have [094h,096h] set to all zeroes). The
chips are all 128MByte (122MByte usable), with memory map as so:
00000000h ROM region (one large region) (R)
0xxx0000h RW region (split into several 128KByte blocks) (R/W)
07A00000h Reserved region (R)
The RW space is 8MB for Jam with the Band, 16MB for WarioWare DIY, and 82MB in
Face Training. Unknown if some of the cart memory is reserved for broken sector
handling.
Command Summary
For whatever reason, random access is slightly restricted: One must use command
8Bh/B2h to select ROM region or a 128KByte RW window before reading/writing the
selected area. Writing is done in 2Kbyte units (4x200h bytes).
In ROM access mode:
9400000000000000h Len=200h NAND Read ID
B2aaaaaaaa000000h Len=0 NAND Select 128Kbyte RW access mode
B300000000000000h Len=04h Unknown (returns 00000000h)
BB00000000000000h Len=200h Unknown (returns 1X 04 09 20 04, plus zeroes)
In RW access mode (on DSi carts, this works ONLY in DSi mode):
81aaaaaaaa000000h Len=200h NAND Write to Write Buffer (must be issued 4x)
8200000000000000h Len=0 NAND Forward Write Buffer to NAND
8400000000000000h Len=0 NAND Discard Write Buffer
8500000000000000h Len=0 NAND Write Enable
8600000000000000h Len=0 Unknown
8700000000000000h Len=0 NAND Write Disable
8B00000000000000h Len=0 NAND Select ROM access mode
In either mode:
0B00000000000000h Len=200h Returns cart header[000h..1FFh]
0C00000000000000h Len=200h Returns corrupted cart header[1F8h..3F7h] ??
58h..5Fh Len=0 Unknown (looks same/similar as in 1T-ROM carts)
60h..68h Len=800h Unknown (looks same/similar as in 1T-ROM carts)
B000000000000000h Len=04h Unknown (returns 01010101h)
B500000000000000h Len=0 Unknown (looks same/similar as in SanDisk carts)
B7aaaaaaaa000000h Len=200h NAND Read from ROM or RW area
B800000000000000h Len=04h Read Chip ID
D600000000000000h Len=04h NAND Read Status
Further command(s) spotted in Face Training disassembly:
8800000000000000h Len=0 Unknown (is in disassembly, but fails on HW?)
Reserved Area (at 07A00000h and up) (including 08000000h and up)
This memory isn't intended to be used, in Jam with the Band it just returns
FFh's. However, in Face Training it does return some interesting internal data
(in RW mode):
The DSi Blowfish key (with the gamecode pre-applied), some NDS ARM code (for
the secure area or so), and most interestingly some more ARM+THUMB code
(apparently containing the firmware running on an ARM CPU inside of the game
cartridge itself).
Unfortunately, that internal memory is returned as "raw" data with faulty bits,
and it seems to be required to apply error correction to convert it to actual
intact data (the "raw" stuff consists of 1E8h-byte data snippets, usually
followed by 8-byte ECC info, or sometimes 16-byte or 20-byte ECC, or no ECC at
all). There are several "backup" copies of the blowfish/firmware blocks.
Write Example
B2aaaaaaaa000000h - Select 128Kbyte RW access mode (unlesss already)
8500000000000000h - NAND Write Enable
81aaaaaaaa000000h - NAND Write to Write Buffer + Data[200h]
81aaaaaaaa000000h - NAND Write to Write Buffer + Data[200h]
81aaaaaaaa000000h - NAND Write to Write Buffer + Data[200h]
81aaaaaaaa000000h - NAND Write to Write Buffer + Data[200h]
8200000000000000h - NAND Forward Write Buffer to NAND
D600000000000000h - NAND Read Status + Data[4]
(...repeat reading status until bit5=1=ready...)
8400000000000000h - NAND Discard SRAM write
8B00000000000000h - NAND Select ROM access mode (if desired)
Chipsets
Warioware D.I.Y., NTR-UORE:
PCB "DI X-7 C17-01"
Chip "SAMSUNG 004, KLC2811ANB-P204, NTR-UORE-0"
Jam with the Band, NTR-UXBP:
PCB (Unknown)
Chip "SAMSUNG 013, KLC2811UOC-P30A, NTR-UXBP-0, WKA069J2"
Face Training, TWL-USKV:
PCB "DI X-8 C17-01"
U1 "SAMSUNG 031, KLC2811UOC-P309, TWL-USKV-0, WKE114(80?)"
(this chip must be slightly different, for DSi mode support)
There are also a bunch of 3DS games with similar chips (with the RW area being
called "CARD2" area on 3DS, and, the 3DS is using 16-byte commands, so the
protocol is different).
Notes
Unlike ROM carts, the NAND cart does crash upon invalid commands (and stops to
respond to further commands). That is, upon invalid command numbers, upon ROM
mode commands in RW mode (or vice-versa), upon any data lengths other listed
above.
The Gamecard bus registers can be mapped to NDS7 or NDS9 via EXMEMCNT, see
--> DS Memory Control
The DS hardware, BIOS, and Firmware do NOT contain any built-in filesystem
functions. The ARM9/ARM7 boot code (together max 3903KB), and Icon/Title
information are automatically loaded on power-up.
Programs that require to load additional data from cartridge ROM may do that
either by implementing whatever functions to translate filenames to ROM
addresses, or by reading from ROM directly.
NitroROM
The NitroROM Filesystem is used by many NDS games (at least those that have
been developed with Nintendo's tools). It's used for ROM Cartridges, and, on
the DSi, it's also used for DSiWare games (in the latter case, NitroROM acts as
a 2nd virtual filesystem inside of the DSi's FAT16 filesystem).
FNT = cart_hdr[040h] ;\origin as defined in ROM cartridge header
FAT = cart_hdr[048h] ;/
IMG = 00000000h ;-origin at begin of ROM
Aside from using filenames, NitroROM files can be alternately accessed via
Overlay IDs (see later on below).
NARCless variant
There are a few NARC archives with crippled header, without "NARC" string (eg.
rom:\dwc\utility.bin in Over the Hedge, Downhill Jam, and Tony Hawk's
Skateland).
000h 4 FNT Filename Table Offset (always at 10h)
004h 4 FNT Filename Table Size
008h 4 FAT Allocaton Table Offset (at above Offset+Size+Padding)
00Ch 4 FAT Allocaton Table Size
010h .. FNT Filename Table Data
... .. FAT Allocaton Table Data
... .. IMG File Data
The offsets in FAT are relative to IMG=0 (as if IMG would start at begin of
file).
ARM9 and ARM7 Overlay Tables (OVT) (base/size defined in cart header)
Somehow related to Nintendo's compiler, allows to assign compiler Overlay IDs
to filesystem File IDs, and to define additional information such like load
addresses.
Addr Size Expl.
00h 4 Overlay ID
04h 4 RAM Address ;Point at which to load
08h 4 RAM Size ;Amount to load
0Ch 4 BSS Size ;Size of BSS data region
10h 4 Static initialiser start address
14h 4 Static initialiser end address
18h 4 File ID (0000h..EFFFh)
1Ch 4 Reserved (zero)
Cartridge Header
The base/size of FAT, FNT, OVT areas is defined in cartridge header,
--> DS Cartridge Header
The Main Data transfer mode is normally using only two commands (B7h/B8h),
however most cartridges do support one or more undocumented commands (as
opposed to invalid commands, which will cause the cart to stop responding).
Title Chip ID Commands...
Metroid First Hunt 00000FC2 B7 B8 D8
Meine Tierarztpraxis 00000FAE B7 B8 D8
Meine Tierpension 00000FC2 B7 B8 D8
Nanostray 00000FC2 B7 B8 D8
Over the Hedge 00001FC2 B7 B8 D8
Tony Hawk's Skateland 00003FC2 B7 B8
Tony Hawk's Downhill Jam 00003FC2 B7 B8
Ultimate Spiderman 00003FC2 B7 B8
System Flaw (DSi) 40001FC2 B7 B8 F1
Biggest Loser (DSi) 40001FC2 B7 B8 F1
Cooking Coach (DSi) C0007FC2 58..5F 60..68 B7 B8
Walk with Me E0013F80 69..6C B5 B7 B8 D6
Face Training (DSI NAND) E8007FEC 0x 5x 6x 8x 94 Bx D6 (see NAND chapter)
The presence of those commands was tested on DSi (where one can reset the cart
by software to recover from invalid commands), with all parameter bits set to
zero.
That testing is more difficult on NAND carts because the commands do only work
when transferring the correct number of data bytes (0, 4, 200h, or 800h bytes),
and only when being in the correct mode (ROM or RW mode; whereof, on DSi carts,
the RW mode works ONLY in DSi mode).
Command B5h/D6h are supported in carts that have bit5 set in 4th byte of Chip
ID (eg. in Walk with Me). Command D6h (and maybe also B5h) works both on power
up (before secure area), and in main data phase (after secure area). The DSi
Launcher contains following code to deal with such carts:
if chip_id AND 20000000h
get_nand_status(cmd_D6h)
if (nand_status AND 0Ch)<>0 ;whatever bits
whatever(cmd_B5h) ;whatever command
loop:
get_nand_status(cmd_D6h)
if (nand_status AND 20h)=0 then goto loop ;wait for ready flag
DS Cartridge PassMe/PassThrough
-------------------------------
ARM9 Entrypoint
The GBA-slot access rights in the EXMEMCNT register are initially assigned to
the ARM7 CPU, so the ARM9 cannot boot from the flashcard, instead it is
switched into an endless loop in Main RAM (which contains a copy of the
cartridge header at 27FFE00h and up). The ARM7 must thus copy ARM9 code to Main
RAM, and then set the ARM9 entry address by writing to [027FFE24h].
Aside from the 17-pin NDS slot, the DS also includes a 32-pin GBA slot. This
slot is used for GBA backwards compatibility mode. Additionally, in DS mode, it
can be as expansion port, or for importing data from GBA games.
NDS: Normal 32pin slot
DS Lite: Short 32pin slot (GBA cards stick out)
DSi: N/A (dropped support for GBA carts, and for DS-expansions)
In DS mode, ROM, SRAM, FLASH backup, and whatever peripherals contained in
older GBA cartridges can be accessed (almost) identically as in GBA mode,
--> GBA Cartridges
Addressing
In DS mode, only one ROM-region is present at 8000000h-9FFFFFFh (ie. without
the GBA's mirrored WS1 and WS2 regions at A000000h-DFFFFFFh). The expansion
region (for SRAM/FLASH/etc) has been moved from E000000h-E00FFFFh (GBA-mode) to
A000000h-A00FFFFh (DS-mode).
Timings
GBA timings are specified as "waitstates" (excluding 1 access cycle), NDS
timings are specified as (total) "access time". And, the NDS bus-clock is twice
as fast as for GBA. So, for "N" GBA waitstates, the NDS access time should be
"(N+1)*2". Timings are controlled via NDS EXMEMCNT instead GBA WAITCNT,
--> DS Memory Control - Cartridges and Main RAM
GBA EEPROM
EEPROMs in GBA carts cannot be accessed in DS mode. The EEPROMs should be
accessed with 8 waits on GBA, ie. 18 cycles on NDS on both 1st/2nd access. But,
2nd access is restricted to max 6 cycles in NDS mode, which is ways too fast.
DS Memory Expansions
There are several RAM expansions for the NDS. The RAM cartridge connects to the
GBA slot; can can be then accessed from cartridges in the DS slot.
Opera (8MB RAM) (official RAM expansion for Opera browser)
EZ3/4/3-in-1 (8-16MB RAM, plus FLASH, plus rumble)
Supercard (32MB)
M3 (32MB)
G6 (32MB)
The recommended access time (waitstates) for all memory types is unknown.
Unknown which programs do use these expansions for which purposes (aside from
the Opera browser).
Thanks to Rick "Lick" Wong for info on detection and unlocking.
EZ
base=8400000h, size=VAR (8MB..16MB)
locking/unlocking/detection see below
Supercard
base=8000000h, size=1FFFFFEh (32MB minus last two bytes?)
unlock=5 (RAM_RW), lock=3 (MEDIA)
STRH [9FFFFFEh],A55Ah
STRH [9FFFFFEh],A55Ah
STRH [9FFFFFEh],lock/unlock
STRH [9FFFFFEh],lock/unlock
M3
base=8000000h, size=2000000h (32MB)
unlock=00400006h, lock=00400003h
LDRH Rd,[8E00002h]
LDRH Rd,[800000Eh]
LDRH Rd,[8801FFCh]
LDRH Rd,[800104Ah]
LDRH Rd,[8800612h]
LDRH Rd,[8000000h]
LDRH Rd,[8801B66h]
LDRH Rd,[8000000h+(lock/unlock)*2]
LDRH Rd,[800080Eh]
LDRH Rd,[8000000h]
LDRH Rd,[80001E4h]
LDRH Rd,[80001E4h]
LDRH Rd,[8000188h]
LDRH Rd,[8000188h]
G6
base=8000000h, size=2000000h (32MB)
unlock=6, lock=3
LDRH Rd,[9000000h]
LDRH Rd,[9FFFFE0h]
LDRH Rd,[9FFFFECh]
LDRH Rd,[9FFFFECh]
LDRH Rd,[9FFFFECh]
LDRH Rd,[9FFFFFCh]
LDRH Rd,[9FFFFFCh]
LDRH Rd,[9FFFFFCh]
LDRH Rd,[9FFFF4Ah]
LDRH Rd,[9FFFF4Ah]
LDRH Rd,[9FFFF4Ah]
LDRH Rd,[9200000h+(lock/unlock)*2]
LDRH Rd,[9FFFFF0h]
LDRH Rd,[9FFFFE8h]
Detection
For EZ, detection works as so:
ez_ram_test: ;Based on DSLinux Amadeus' detection
ez_subfunc(9880000h,8000h) ;-SetRompage (OS mode)
ez_subfunc(9C40000h,1500h) ;-OpenNorWrite
[08400000h]=1234h ;\
if [08400000h]=1234h ; test writability at 8400000h
[8000000h]=4321h ; and non-writability at 8000000h
if [8000000h]<>4321h ;
return true ;/
ez_subfunc(9C40000h,D200h) ;CloseNorWrite
ez_subfunc(9880000h,0160h) ;SetRompage (0160h)
ez_subfunc(9C40000h,1500h) ;OpenNorWrite
[8400000h]=1234h ;\
if [8400000h]=1234h ; test writability at 8400000h
return true ;/
return false ;-failed
ez_subfunc(addr,data):
STRH [9FE0000h],D200h
STRH [8000000h],1500h
STRH [8020000h],D200h
STRH [8040000h],1500h
STRH [addr],data
STRH [9FC0000h],1500h
For all other types (everything except EZ), simply verify that you can write
(when unlocked), and that you can't (when locked).
DS Cart Infrared/Pedometers
---------------------------
Activity Meter
Pedometer with two-color LED and button. The step counter results can be
transferred to NDS via IrDA.
--> DS Cart Infrared Activity Meter IR Commands
--> DS Cart Infrared Activity Meter Memory Map
P-Walker
Pedometer with LCD, speaker, and three buttons. There is no intended way to run
custom program code (though it can be tweaked to do so via CPU Memory Write
command).
--> DS Cart Infrared P-Walker IR Commands
--> DS Cart Infrared P-Walker Memory Map
--> DS Cart Infrared P-Walker Ports LCD Controller
--> DS Cart Infrared P-Walker Ports Accelerometer BMA150
The purpose is more or less unknown: Apart from communicating with the NDS, the
IrDA can be also used communicate with other P-Walkers (maybe for
trading/fighting?). The GUI supports Teams, Routes, Events, Items (maybe for
some built-in interactice game engine?).
Component Lists
--> DS Cart Infrared Component Lists
References
H8/300H Series Programming Manual (Hitachi, 257 pages) ;-Opcodes
H8/38602R Group Hardware Manual (Renesas, 554 pages) ;-SFR's
The addition of H8/38606 Group (Renesas, 6 pages) ;-FLASH/ROM/RAM
For P-Walker:
BMA150 Triaxial digital acceleration sensor Data sheet (Bosch, 56 pages)
SSD1850 Advance Information (Solomon System, 56 pages) ;-LCD driver
http://dmitry.gr/?r=05.Projects&proj=28.%20pokewalker ;-Disassembly/Story
http://forums.nesdev.com/viewtopic.php?f=23&t=21140#p265388 ;-Forum
There are two NDS cart firmware versions with minor differences:
OLD was used in Walk with Me (maybe also Active Health?)
NEW was used in the P-Letter game series
The IR-port is accessed via SPI bus commands; that bus is also shared for
accessing FLASH/EEPROM memory (via 00h-prefix).
SPI Transfers
The SPI transfers are working at max 1MHz transfer clock, and they do require a
delay after each byte:
Waiting 800h clks at 33MHz seems to work okay (eg. MOV r0,200h // SWI 03h on
ARM7). The NEW ROM version disables IR polling when doing the SPI transfers for
RX/TX data blocks (so it may work with shorter delays between the data[...]
bytes).
The savedata access is directly passed to the FLASH/EEPROM chip and does work
at 4MHz without delays (except, the leading 00h prefix must be transferred at
1MHz plus delay, and another delay is needed when releasing chipselect after
last byte).
Note: The NDS cart slot IRQ pin is GNDed in Walk with Me (ie. there is no IRQ
for SPI/IR status).
SPI access does require cart power on and reset (via DSi SCFG registers), but
doesn't require any ROM commands like secure area loading. Confusingly, the ROM
Chip ID seems to have an IR flag in bit0 of 3rd byte (although the ROM chip
isn't wired to IR hardware at all).
IR Transfers
The IR transfers are using a fixed baudrate: 115200 baud, 8n1, one-directional
(RX gets disabled during TX). The RX/TX commands are transferring "packets"
(with each "packet" being terminated by a "pause" in the IR transmission; that
"packet+pause" mechanism is making it impossible to use streaming for
transferring larger blocks that exceed the buffer size of max 84h or B8h
bytes).
The RX command will return empty data with len=00h until a WHOLE packet has
been received via IR.
The TX command won't start the IR transfer until the WHOLE packet has been
written via SPI, with packet end indicated by releasing chip select.
There is no way to detect TX transfer end (other than computing the expected
tranfer time and using an ARM timer).
However, Nintendo is sending a Reply for most TX commands, so one can simply
wait for RX packets to determine TX completion (if neither Reply nor Checksum
Error are received then one will still need timeout handling).
Memory Read/Write
These commands are normally not used. The memory commands do forcefully abort
IR transfers, so they can't be used for polling IR transfer status.
However, they can be used for dumping the firmware ROM, and they could be used
to upload/execute custom code in RAM, which may allow to overcome some of the
above IR transfer restrictions (other baudrates, fewer delays, better
streaming, not ignoring byte F2h, etc).
IR Cart Detection
NDS/DSi Carts with IR support are having special game code with "I" in first
letter (NTR-Ixxx or TWL-Ixxx). There are reportedly pirate/bootleg versions of
the P-Letter games without IR hardware, unknown if they do nethertheless have
the "I" in the gamecode.
Emulators can detect the leading 00h prefix for Savedata access, although that
detection may go wrong if preceeded by IR access. Emulators can additionally
detect the slow 1MHz SPI clock used for IR access (and for 00h prefix).
Packet Encryption/Checksumming
Nintendo wants all IR packet bytes to be "encrypted" (XORed by AAh), that
encryption/decryption must be done on ARM side. The checksums are calculated as
so (on decrypted packets):
sum=0, packet[2,3]=00h,00h ;-initial chksum
for i=0 to size-1
if (i and 1)=0 then sum=sum+packet[i]*100h ;\add in big-endian fashion
if (i and 1)=1 then sum=sum+packet[i] ;/
sum=(sum/10000h)+(sum AND FFFFh) ;\final adjust
sum=(sum/10000h)+(sum) ;/
packet[2,3]=sum,sum/100h ;-store in little-endian
The packets are transferred at 115200 baud, 8n1. End of Packet is indicated by
a pause in the IR transmission (that does also indicate the packet size).
Before sending a command packet, one should always wait for incoming data from
the Activity Meter (ie. for the FCh byte, or for Reply/ChecksumError responses
for previous command).
Notes
cc,cc Checksum (LITTLE-ENDIAN)
msb,lsb Memory Address (big-endian)
ss,ss,ss,ss Seconds since 2001 (big-endian)
ss,mm,hh RTC time HH:MM:SS (BCD) (caution: smashes seconds since 2001)
sq Increasing sequence number in Memory Access replies
cs LED color/state (c=color red/green, s=state on/off)
xx Whatever (don't care?)
There aren't any specific commands for reading things like step counters, one
must instead use the Memory Read/Write commands with hardcoded RAM or EEPROM
address, see:
--> DS Cart Infrared Activity Meter Memory Map
The command/reply are intended to be transferred from/to NDS accordingly, but
things could go wrong if there are multiple consoles or activity meters (all
trying to process the same message, or even mistreating replies as commands).
The infrared range (distance/angle) is unknown. Dumping the whole 64K CPU
memory space worked without checksum errors at about 5-10cm distance (and that
worked without even using the Connect command).
The most important RAM locations are FCE8h=Total steps, and FB9Ch=Unique ID
(when using multiple Activity Meters), FCF0h=Daily Goal (to change LED color
after N steps). Nintendo is reading/writing a few more RAM locations. And,
there are ring buffers with steps per minute/hour/day in EEPROM.
Commands are usually send from NDS (or from other Walkers)
EEPROM Commands (Cmd 02,04,0C,0E,82) ;\From NDS or Walker
Connect Commands (Cmd F8,FA,FC) ;/
Peer Commands (Cmd 10...1C) ;-From Walker
Unused Commands (Cmd's with * marking) ;-From Prototype tests?
Other Commands (Cmd's other than above) ;-From NDS
Incoming Commands from NDS (or incoming commands/replies from another Walker)
00,hi,..,lzss(..) EEPROM Write [hi00h..hi7Fh] Compressed ;Reply=04
80,hi,..,lzss(..) EEPROM Write [hi80h..hiFFh] Compressed ;Reply=04
02,hi,..,data(..) EEPROM Write [hi00h..hi7Fh] Raw ;Reply=04
82,hi,..,data(..) EEPROM Write [hi80h..hiFFh] Raw ;Reply=04
04,xx,.. EEPROM Write Reply ;SendMoreCmd(s)
06,hi,..,lo,data(nn)* CPU Memory Write [hilo+(0..nn-1)] ;Reply=06
0A,hi,..,lo,data(nn)* EEPROM Write Random Len [hilo+(0..nn-1)] ;Reply=04
0C,xx,..,hi,lo,nn EEPROM Read Request [hilo+(0..nn-1)] ;Reply=0E
0E,xx,..,data(nn) EEPROM Read Reply ;SendMoreCmd(s)
10,xx,..,data(68h) Peer Step 1 Request ;Reply=12
12,xx,..,data(68h) Peer Step 1 Reply ;SendMoreCmd(s)
14,xx,..,data(38h) Peer Step 2 Request ;Reply=16
16,xx,.. Peer Step 2 Reply ;Reply=16 or None
1C,xx,.. Peer Refuse ;Reply=None+Disconnect
20,xx,.. Identity Read Request ;Reply=22
24,xx,.. * Ping Request ;Reply=26
2A,xx,..,none? Unique ID Read Request ;Reply=2A
2C,xx,..,none? * Unique ID Read Request slightly other ;Reply=2A
32,xx,..,data(28h?) * Identity Write Request 1 ;Reply=34
36,xx,.. * Connection Error 1 ;Reply=None
38,xx,.. * Walk Start Silent ;Reply=38
40,xx,..,data(28h?) * Identity Write Request 2 ;Reply=42
44,xx,.. * Connection Error 2 ;Reply=None
4E,xx,.. Walk End Request ;Reply=50
52,xx,..,data(28h?)?? Identity Write Request 3 ;Reply=54
56,xx,.. * Connection Error 3 ;Reply=None
5A,xx,.. Walk Start Nonsilent ;Reply=5A
60,xx,..,data(28h?) * Identity Write Request 4 ;Reply=62
64,xx,.. * Connection Error 4 ;Reply=None
66,xx,.. * Walk End Request OTHER ;Reply=68
9C,xx,.. * Error Whatever ;Reply=9C+Disconnect
9E,xx,.. * Error Weird Participate ;Reply=9E+Disconnect
A0,xx,.. * Weird Participate 1 ;Reply=A0 or 9E
A2,xx,.. * Weird Participate 2 ;Reply=A2 or 9E
A4,xx,.. * Weird Participate 3 ;Reply=A4 or 9E
A6,xx,.. * Weird Participate 4 ;Reply=A6 or 9E
A8,xx,.. * Weird Participate 5 ;Reply=A8 or 9E
AA,xx,.. * Weird Participate 6 ;Reply=AA or 9E
AC,xx,.. * Weird Participate 7 ;Reply=AC or 9E
AE,xx,.. * Weird Participate 8 ;Reply=AE or 9E
B8,xx,.. * Award Stamp Heart ;Reply=D8
BA,xx,.. * Award Stamp Spade ;Reply=DA
BC,xx,.. * Award Stamp Diamond ;Reply=DC
BE,xx,.. * Award Stamp Club ;Reply=DE
C0,xx,.. * Award Special Map ;Reply=C0
C2,xx,.. * Award Event P-Letter ;Reply=C2
C4,xx,.. * Award Event Item ;Reply=C4
C6,xx,.. * Award Event Route ;Reply=C6
D0,xx,.. * Award All Stamps and Special Map ;Reply=C0
D2,xx,.. * Award All Stamps and Event P-Letter ;Reply=C2
D4,xx,.. * Award All Stamps and Event Item ;Reply=C4
D6,xx,.. * Award All Stamps and Event Route ;Reply=C6
D8,xx,.. * Connection Error 5 ;Reply=None
F0,xx,..,data(71h) ?? Enroll Data (28h+40h+8+1 bytes) ;Reply=F0
F4,xx,.. * Disconnect ;Reply=None+Disconnect
F8,02,.. Connection Reply from Walker ;SendCmd=1002
FA,01,.. Connection Request from NDS ;Reply=F802
FA,02,.. Connection Request from Walker ;Reply=F802
FA,xx,.. Connection Request invalid ;Reply=None+Disconnect
FC Connection Beacon from Walker ;SendCmd=FA
FE,01,..,data(8) * EEPROM Write [0008h..000Fh] ;Reply=FE
xx * Ignored (single byte other than FC) ;Reply=None
xx,xx,.. * Invalid Cmd ;Reply=None
xx,xx,xxxx * Ignored (wrong 4-byte ID for Cmd 00-F7) ;Reply=None
xx,xx,xxxx * Bad Checksum (disconnect if too often) ;Reply=None
Outgoing Replies to NDS (or outgoing commands/replies to another Walker)
02,hi,..,data(nn) EEPROM Write ... ;Cmd=Peer
82,hi,..,data(nn) EEPROM Write ... ;Cmd=Peer
04,hi,.. EEPROM Write Reply ;Cmd=00/02/0A/80/82
06,hi,.. * CPU Memory Write Reply ;Cmd=06h
0C,02,..,hi,lo,nn EEPROM Read Request ;Peer, EEPROM Read ;Cmd=0Eh
0E,02,..,data(nn) EEPROM Read Reply ;Cmd=0Ch
10,02,..,data(68h) Peer Step 1 Request (after Connect Reply);Cmd=F8h
12,02,..,data(68h) Peer Step 1 Reply ;Cmd=10h
14,02,..,data(38h) Peer Step 2 Request ;Cmd=0Eh
16,02,.. Peer Step 2 Reply ;Cmd=14h/16h
1C,02,.. Peer Refuse ;Cmd=10h/12h
22,02,..,data(68h) Identitiy Read Reply ;Cmd=20h
26,02,.. * Ping Reply ;Cmd=24h
2A,02,..,data(28h) Unique ID Reply ;Cmd=2Ah/2Ch
34,02,.. * Identitiy Write 1 Reply ;Cmd=32h
38,02,.. * Walk Start silent Reply ;Cmd=38h
42,02,.. * Identitiy Write 2 Reply ;Cmd=40h
50,02,.. Walk End Reply ;Cmd=4Eh
54,02,.. ?? Identitiy Write 3 Reply ;Cmd=52h
5A,02,.. Walk Start nonsilent Reply ;Cmd=5Ah
62,02,.. * Identitiy Write 4 Reply ;Cmd=60h
68,02,.. * Walk End OTHER Reply ;Cmd=66h
9C,02,.. * Weird Whatever Reply-to-Reply? ;Cmd=9Ch
9E,02,..,data(11h) * Weird Participated Reply ;Cmd=A0h..AEh
9E,02,.. * Weird Participated Reply-to-Reply? ;Cmd=9Eh
A0,02,..,data(11h) * Weird Participated Reply 1 ;Cmd=A0h
A2,02,..,data(11h) * Weird Participated Reply 2 ;Cmd=A2h
A4,02,..,data(11h) * Weird Participated Reply 3 ;Cmd=A4h
A6,02,..,data(11h) * Weird Participated Reply 4 ;Cmd=A6h
A8,02,..,data(11h) * Weird Participated Reply 5 ;Cmd=A8h
AA,02,..,data(11h) * Weird Participated Reply 6 ;Cmd=AAh
AC,02,..,data(11h) * Weird Participated Reply 7 ;Cmd=ACh
AE,02,..,data(11h) * Weird Participated Reply 8 ;Cmd=AEh
C0,02,.. * Award Special Map Reply ;Cmd=C0h/D0h
C2,02,.. * Award Event P-Letter Reply ;Cmd=C2h/D2h
C4,02,.. * Award Event Item Reply ;Cmd=C4h/D4h
C6,02,.. * Award Event Route Reply ;Cmd=C6h/D6h
C8,02,.. * Award Stamp Heart Reply ;Cmd=B8h
CA,02,.. * Award Stamp Spade Reply ;Cmd=BAh
CC,02,.. * Award Stamp Diamond Reply ;Cmd=BCh
CE,02,.. * Award Stamp Club Reply ;Cmd=BEh
F0,02,..,data(28h) ?? Enroll Reply ;Cmd=F0h
F8,02,.. Connect Reply ;Cmd=FAh
FA,02,.. Connect Request from walker ;Cmd=FCh
FC Connection Beacon ;Button?
FE,02,.. * EEPROM Write [0008h..000Fh] Reply ;Cmd=FEh
-?- Checksum Error... has no reply? or maybe sends Beacons?
Notes
.. short for 16bit Checksum at hdr[2..3] and 32bit Session ID at hdr[4..7]
xx somewhat don't care (usually 01h=From NDS, or 02h=From Walker)
All 16bit checksum and the IR "encryption" (XOR by AAh), seem to be same as for
Activity Meter (see there, except use initial sum=2, not sum=0).
The Connect Request & Reply commands are sending a "random" SessionID each, all
following commands/replies (except F8h and up) must use
SessionID = ConnectRequestRandomID XOR ConnectReplyRandomID.
The Compressed EEPROM commands are writing decompressed 80h-bytes of data to
EEPROM (ie. the compression is only used to speedup the IR transfer, not to
save memory). The compression format is Nintendo's standard LZSS (including the
header value 10h, and little-endian 24bit length; which should be always 80h).
Special case: Compressed writes with exactly 80h bytes of incoming data are
treated as uncompressed writes (to be used when compression ratio is worse than
no compression).
ROM Map
For some quick hacks, Dmitry recommends these ROM addresses (which won't work
when reflashing the firmware).
0772h Send IR packet (F8D6h=src, r0l=len, r0h=hdr[0], r1l=hdr[1])
08D6h Default callback (when in IR transfer mode)
259Eh Watchdog refresh
EEPROM Map
The EEPROM contains some important basic data, plus GUI related bitmaps (mostly
text strings pre-rendered as bitmaps for the local user name & game language)
(and maybe(?) also game specific customizations).
0000h 8 ID "nintendo" (set after initial power-up eeprom init)
0008h 8 ID whatever (set via Cmd F0h and FEh) (never read)
0010h 62h ???
0072h 1 Number of watchdog resets
0073h 0Dh ???
0080h 02h+1 ADC calibration (factory-provided) ;\
0083h 28h+1 Unique ID (set via Cmd F0h) ; with 1-byte
00ACh 40h+1 LCD ConfigCmds (set via Cmd F0h) ; checksums
00EDh 68h+1 Identity Data ("provisioned" at walk start time) ; and backup
0156h 18h+1 Health Data ("provisioned" at walk start time) ; copies at
016Fh 01h+1 Copy Flag (00h=Normal, A5h=copy was interrupted) ; 0180h-027Fh
0171h 0Fh Unused ;/
0180h 100h Backup copies of entries at 0080h-0017Fh
0280h ... Various Bitmaps
8C70h ... Various Garbage, Bitmaps, Items, Team, Route
CE8Ah 2 current watts written to eeprom by cmd 20h before replying
(likely so remote can read them directly). u16 BE
CE8Ch ... Various stuff
CEF0h 1Ch Historic step count per day. u32 each, BE,
[0] is yesterday, [1] is day before, etc...
CF0Ch ... Various stuff
See Dmitry's webpage for more "game-specifc" data structures and memory
addresses.
VRAM Reading and Status Byte (both supported in parallel Non-SPI mode only)
The controller supports four modes (Nintendo uses the 4-wire SPI mode):
3-wire SPI Serial write-only (/CS, CLK, MOSI, with cmd E8h instead D/C pin)
4-wire SPI Serial write-only (/CS, CLK, MOSI, D/C=Data/Cmd)
12-wire 8080 Parallel read/write (/CS, D0-D7, D/C, /RD, /WR)
12-wire 6800 Parallel read/write (/CS, D0-D7, D/C, E, R/W)
VRAM can be read setting the VRAM address as usually, and then reading with
D/C=High. And, an 8bit status byte can be read with D/C=Low:
7 BUSY Chip is executing instruction (0=Ready, 1=Busy)
6 ON Display is On/Off (0=Off, 1=On)
5 RES Chip is executing reset (0=Ready, 1=Busy)
4-0 - Fixed Chip ID (08h=SSD1850)
Note
Nintendo uses a 96x64 pixel grayscale LCD screen with 2bpp, without backlight
or frontlight. VRAM is double buffered (VRAM size is at least 96x128 pixels).
The display controller seems to be a Solomon System SSD1850 chip... or similar,
there are a number of datasheets that are more or less matching the LCD
commands used in the firmware:
SSD0852 128x128 would allow double-buffer, but extended commands are wrong
SSD0858 104x65 close, but extended commands are wrong
SSD0859 128x81 could be correct (almost same as SSD1850)
SSD1820 128x65 wrong, lacks palette (command 88h-8Fh)
SSD1820A 128x65 wrong, lacks palette (command 88h-8Fh)
SSD1821 128x81 wrong, lacks palette (command 88h-8Fh)
SSD1850 128x65 could be correct (ysiz is good, but no double-buffering)
SSD1851 128x81 as above, but more lines than needed
SSD1852 128x128 would allow double-buffer, but extended commands are wrong
SSD1854 128x160 wrong, uses 2-byte command B0h,YYh lacks extended commands
(also cmd 18h,20h,4xh,50h,60h-63h,64h,82h,83h,etc. differ)
SSD1858 104x65 close, but lacks many extended commands
SSD1859 128x81 could be correct (almost same as SSD1850)
But, Nintendo's firmware contains extended command F7h,02h (which isn't
mentioned in any of the above datasheets).
And, the firmware seems to use two 64-line framebuffers at DisplayStart=0 and
DisplayStart=64, ie. needing 128 lines in total, which leaves no space for the
"icon" scanline (at least not addressable via cmd B0h+y).
Might do drilling machine, not good honking out paste pretty screenshot?
Official BMA150 register specs are in a Bosch-Captcha, which appears to be
intended to fool humans and bots alike (text on hatched background, undefined
color codes, increasingly unpleasant medusa-like details at closer look).
Anyways, here's a plaintext-hack of the Bosch-Captcha:
00h Chip ID (bit7-3=Unused, bit2-0=02h)
01h Version (bit7-4=al_version, bit3-0=ml_version) (undefined values)
02h Acc X Low (bit7-6=DataLsb, bit5-1=Unused, bit0=NewDataFlag)
03h Acc X High (bit7-0=DataMsb)
04h Acc Y Low (bit7-6=DataLsb, bit5-1=Unused, bit0=NewDataFlag)
05h Acc Y High (bit7-0=DataMsb)
06h Acc Z Low (bit7-6=DataLsb, bit5-1=Unused, bit0=NewDataFlag)
07h Acc Z High (bit7-0=DataMsb)
08h Temperature (bit7-0=DataTempMsb) (Lsb not existing, except in Trimming?)
09h Status Flags (see below)
0Ah Control Flags (see below)
0Bh Config Flags (see below)
0Ch LG Threshold (bit7-0)
0Dh LG Duration (bit7-0)
0Eh HG Threshold (bit7-0)
0Fh HG Duration (bit7-0)
10h Any Motion Threshold (bit7-0)
11h Misc Stuff (bit7-6=AnyMotionDur, bit5-3=HG Hyst, bit2-0=LG Hyst)
12h Customer Reserved 1 (bit7-0)
13h Customer Reserved 2 (bit7-0)
14h Range/Bandwidth (bit7-5=Reserved, bit4-3=Range, bit2-0=Bandwidth)
15h Misc Flags (see below)
16h Trimming X Low (bit7-6=OffsetLsb, bit5-0=Gain)
17h Trimming Y Low (bit7-6=OffsetLsb, bit5-0=Gain)
18h Trimming Z Low (bit7-6=OffsetLsb, bit5-0=Gain)
19h Trimming T Low (bit7-6=OffsetLsb, bit5-0=Gain)
1Ah Trimming X High (bit7-0=OffsetMsb)
1Bh Trimming Y High (bit7-0=OffsetMsb)
1Ch Trimming Z High (bit7-0=OffsetMsb)
1Dh Trimming T High (bit7-0=OffsetMsb)
1Eh-22h BST reserved (official blank/green)
23h BST reserved (official blank/white)
24h-2Ah Not used (official gray/dither)
2Bh-3Dh EEPROM Defaults for Registers 0Bh-1Dh
3Eh-42h BST reserved (official blank/orange)
43h-49h Not used (official gray/dither)
4Ah-4Fh Not mentioned (official not here)
50h-7Fh BST reserved (official blank/cyan)
Obscure Notes: Registers are 00h-06h,21h-22h,43h-7Fh are classifed as NOTHING,
07h-20h as IMAGE, and 23h-42h as EEPROM (whatever that crap means). Also,
Registers 00h-15h are OPERATIONAL, 16h-3Dh are DEFAULT SETTING, 3Eh-7Fh are
BOSCH SENSORTEC RESERVED.
H8/386 SFRs
-----------
H8/386 Exception Vectors (Vector 0000h has highest priority, 004Eh lowest)
Below are for Normal Mode with 16bit addressing (Extended Mode has 32bit
vectors at 0000h..009Fh accordingly).
0000h Reset/Watchdog
0002h Reserved
0004h Reserved
0006h Reserved
0008h Reserved
000Ah Reserved
000Ch Reserved
000Eh External NMI interrupt
0010h Trap 0 opcode
0012h Trap 1 opcode
0014h Trap 2 opcode
0016h Trap 3 opcode
0018h Reserved
001Ah CPU Direct transition by executing SLEEP
001Ch Reserved
001Eh Reserved
0020h External IRQ0 interrupt
0022h External IRQ1 interrupt
0024h External IRQAEC interrupt
0026h Reserved
0028h Reserved
002Ah Comparator COMP0
002Ch Comparator COMP1
002Eh RTC per 0.25 seconds (4Hz) ;0.25-second overflow
0030h RTC per 0.5 seconds (2Hz) ;0.5-second overflow
0032h RTC per second (1Hz) ;Second periodic overflow
0034h RTC per minute ;Minute periodic overflow
0036h RTC per hour ;Hour periodic overflow
0038h RTC per day ;Day-of-week periodic overflow
003Ah RTC per week (7 days) ;Week periodic overflow
003Ch RTC Free-running overflow
003Eh WDT overflow (interval timer)
0040h Asynchronous event counter overflow
0042h Timer B1 Overflow
0044h Serial SPI (or IIC2) (aka I2C ?)
0046h Timer W Overflow or Capture/compare A,B,C,D
0048h Reserved
004Ah IrDA UART Serial 3
004Ch A/D Conversion end
004Eh Reserved
Note: The SSU (aka SPI) and IIC (aka I2C) share the same vector address. When
using the IIC, shift the SSU to standby mode using CKSTPR2.
H8/300H Operands
----------------
CPU Registers
R0..R6 32bit General Purpose ;\can be alternately used as
R7 (SP) 32bit Stack Pointer ;/8bit/16bit registers (see below)
PC 24bit Program Counter
CCR 8bit Flags (occupies 16bit when pushed/stored in memory)
Registers R0..R7 can be split into 8bit/16bit registers (alike 80x86
registers):
.-----------------------.
| ERx | 32bit (ERx)
|-----------+-----------|
| Ex | Rx | 16bit (Rx)
'-----------+-----+-----|
' RxH | RxL | 8bit (RxB)
'-----'-----'
There are no opcodes for splitting upper 16bit in Ex into 8bit ExL,ExH (except,
the sign/zero-extend opcodes seem to allow to extend ExL to Ex).
Memory Addressing
Data is stored in Big-Endian. 16bit/32bit values must be stored at even
addresses (with bit0 cleared) (there is no need to clear bit1 for 32bit values,
namely, push/pop work regardless of bit1).
Native Nocash
@aa:8 [FFaa] Memory at FF00h..FFFFh (upper RAM and SFR's)
@aa:16 [nnnn]
@aa:24 [nnnnnn]
@Erm [Erm]
@(d:16,ERm) [ERm+nnnn]
@(d:24,ERm) [ERm+nnnnnn]
@ERm+ [ERm+] Memory access with post-increment
@-ERm [ERm-] Memory access with pre-decrement
(implied) [ER6+],[ER5+] Memory block transfer (EEPMOV)
Bit Addressing
Native Nocash
#nn:8,@aa:8 [FFaa].n
RnB,@aa:8 [FFaa].RnB
#nn:8,RdB RdB.n
RnB,RdB RdB.RnB
Note: The "#nn:8" suggests native syntax to use "#0x80" to select bit7,
however, the existing disassembler does instead use "#7".
H8/300H Opcodes
---------------
All opcodes are multiples of 2 bytes (2,4,6,8,10 bytes), all opcodes should be
always located at even addresses (ie. bit0 of jump address/disp operands should
be always 0).
Register Encoding
0..7 8bit Registers R0H..R7H (bit8-15) ;\RxB
8..F 8bit Registers R0L..R7L (bit0-7) ;/
0..7 16bit Registers R0..R7 (bit0-15) ;\Rx
8..F 16bit Registers E0..E7 (bit16-31) ;/
0..7 32bit Registers ER0..ER7 (bit0-31) ;-ERx (in normal opcodes)
8..F 32bit Registers ER0..ER7 (bit0-31) ;-ERx (in opcodes marked *m,*s)
H8/300H Not/Neg/Extend
170d NOT.B RdB NOT.B RdB 2 ----nz0-
171d NOT.W Rd NOT.W Rd 2 ----nz0-
173d NOT.L Rd NOT.L ERd 2 ----nz0-
175d EXTU.W Rd UMOV Rd,RdL ;or Ed,EdL? 2 ----0z0-
177d EXTU.L ERd UMOV ERd,Rd 2 ----0z0-
178d NEG.B RdB NEG.B RdB 2 --h-nzvc
179d NEG.W Rd NEG.W Rd 2 --h-nzvc
17Bd NEG.L Rd NEG.L ERd 2 --h-nzvc
17Dd EXTS.W Rd SMOV Rd,RdL ;or Ed,EdL? 2 ----nz0-
17Fd EXTS.L ERd SMOV ERd,Rd 2 ----nz0-
H8/300H N/A
---N/A--- MOV.L @aa:8,ERd MOV.L ERd,[FFaa] - ----nz0-
---N/A--- MOV.L ERs,@aa:8 MOV.L [FFaa],ERs - ----nz0-
---N/A--- MOV.W @aa:8,Rd MOV.W Rd,[FFaa] - ----nz0-
---N/A--- MOV.W Rs,@aa:8 MOV.W [FFaa],Rs - ----nz0-
---N/A--- SUB.B #nn:8,RdB SUB.B RdB,nn - --h-nzvc
The first commercial DS cheat code solution, this device was developed by
Datel. It supports swapping out cartridges after loading the AR software. For
updating, the user may either manually enter codes or use the included
proprietary USB cable that comes with the device. The user has been able to
manually update codes since firmware version 1.52.
> and for the C5 code type it's checked AFTER the counter has
> been incremented (so the counter is always incremented
I love that exceptions ;-)
Hook
The hook codes consist of a series of nine 00000000 XXXXXXXX codes, and must be
marked as (M) code (for not being confused with normal 0XXXXXXX YYYYYYYY
codes). For all nine codes, the left 32bit are actually don't care (but should
be zero), the meaning of the right 32bit varies from 1st to 9th code.
1st: Address used prior to launching game (eg. 23xxxxxh)
2nd: Address to write the hook at (inside the ARM7 executable)
3rd: Hook final address (huh?)
4th: Hook mode selection (0=auto, 1=mode1, 2=mode2)
5th: Opcode that replaces the hooked one (eg. E51DE004h)
6th: Address to store important stuff (default 23FE000h)
7th: Address to store the code handler (default 23FE074h)
8th: Address to store the code list (default 23FE564h)
9th: Must be 1 (00000001h)
For most games, the AR does automatically hook code on the ARM7. Doing that
automatically is nice, but hooking ARM7 means that there is no access to VRAM,
TCM and Cache, which <might> cause problems since efficient games <should>
store all important data in TCM or Cache (though, in practice, I'd doubt that
any existing NDS games are that efficient).
Thanks
To Kenobi and Dualscreenman from Kodewerx for above ARDS cheat info.
Codebreaker DS Codes
---Initialization---
0000CR16 GAMECODE Specify Game ID, use Encrypted codes
8000CR16 GAMECODE Specify Game ID, use Unencrypted codes
BEEFC0DE XXXXXXXX Change Encryption Keys
A0XXXXXX YYYYYYYY Bootup-Hook 1, X=Address, Y=Value
A8XXXXXX YYYYYYYY Bootup-Hook 2, X=Address, Y=Value
F0XXXXXX TYYYYYYY Code-Hook 1 (T=Type,Y=CheatEngineAddr,X=HookAddr)
F8XXXXXX TPPPPPPP Code-Hook 2 (T=Type,X=CheatEngineHookAddr,P=Params)
---General codes---
00XXXXXX 000000YY [X]=YY
10XXXXXX 0000YYYY [X]=YYYY
20XXXXXX YYYYYYYY [X]=YYYYYYYY
60XXXXXX 000000YY ZZZZZZZZ 00000000 [[X]+Z]=YY
60XXXXXX 0000YYYY ZZZZZZZZ 10000000 [[X]+Z]=YYYY
60XXXXXX YYYYYYYY ZZZZZZZZ 20000000 [[X]+Z]=YYYYYYYY
30XXXXXX 000000YY [X]=[X] + YY
30XXXXXX 0001YYYY [X]=[X] + YYYY
38XXXXXX YYYYYYYY [X]=[X] + YYYYYYYY
70XXXXXX 000000YY [X]=[X] OR YY
70XXXXXX 001000YY [X]=[X] AND YY
70XXXXXX 002000YY [X]=[X] XOR YY
70XXXXXX 0001YYYY [X]=[X] OR YYYY
70XXXXXX 0011YYYY [X]=[X] AND YYYY
70XXXXXX 0021YYYY [X]=[X] XOR YYYY
---Memory fill/copy---
40XXXXXX 2NUMSTEP 000000YY 000000ZZ byte[X+(0..NUM-1)*STEP*1]=Y+(0..NUM-1)*Z
40XXXXXX 1NUMSTEP 0000YYYY 0000ZZZZ half[X+(0..NUM-1)*STEP*2]=Y+(0..NUM-1)*Z
40XXXXXX 0NUMSTEP YYYYYYYY ZZZZZZZZ word[X+(0..NUM-1)*STEP*4]=Y+(0..NUM-1)*Z
50XXXXXX YYYYYYYY ZZZZZZZZ 00000000 copy Y bytes from [X] to [Z]
---Conditional codes (bugged)---
60XXXXXX 000000YY ZZZZZZZZ 01c100VV IF [[X]+Z] .. VV THEN [[X]+Z]=YY
60XXXXXX 000000YY ZZZZZZZZ 01c0VVVV IF [[X]+Z] .. VVVV THEN [[X]+Z]=YY
60XXXXXX 0000YYYY ZZZZZZZZ 11c100VV IF [[X]+Z] .. VV THEN [[X]+Z]=YYYY
60XXXXXX 0000YYYY ZZZZZZZZ 11c0VVVV IF [[X]+Z] .. VVVV THEN [[X]+Z]=YYYY
60XXXXXX YYYYYYYY ZZZZZZZZ 21c100VV IF [[X]+Z] .. VV THEN [[X]+Z]=YYYYYYYY
60XXXXXX YYYYYYYY ZZZZZZZZ 21c0VVVV IF [[X]+Z] .. VVVV THEN [[X]+Z]=YYYYYYYY
---Conditional codes (working)---
D0XXXXXX NNc100YY IF [X] .. YY THEN exec max(1,NN) lines
D0XXXXXX NNc0YYYY IF [X] .. YYYY THEN exec max(1,NN) lines
The condition digits (c=0..7), have the following functions:
0 IF [mem] = imm THEN ... 4 IF ([mem] AND imm) = 0 THEN ...
1 IF [mem] <> imm THEN ... 5 IF ([mem] AND imm) <> 0 THEN ...
2 IF [mem] < imm THEN ... (unsigned) 6 IF ([mem] AND imm) = imm THEN ...
3 IF [mem] > imm THEN ... (unsigned) 7 IF ([mem] AND imm) <> imm THEN ...
Notes
GAMECODE Cartridge Header[00Ch] (32bit in reversed byte-order)
CR16 Cartridge Header[15Eh] (16bit in normal byte-order)
XXXXXX 27bit addr (actually 7 digits, XXXXXXX, overlaps 5bit code number)
The "bugged" conditional codes (60XXXXXX) are accidently skipping NN lines when
the condition is false, where NN is taken from the upper 8bit of the code's
last 32bit values (ie. exactly as for the D0XXXXXX codes). For byte-writes,
that would be NN=01h, which can be eventually dealt with, although there may be
compatibility problems which future versions that might fix that bug. For
halfword/word writes, NN would be 11h or 21h, so that codes are about totally
unusable.
Thanks
To Kenobi and Dualscreenman from Kodewerx for above CBDS cheat info.
file.dldi --> driver file (can be small like 1.5Kbyte, or max 32Kbyte)
file.nds --> ROM image (must contain 32Kbyte space with DLDI ID for patching)
Functions
startup, isInserted, clearStatus, shutdown can be dummy functions that do
nothing (other than returning r0=1=okay).
Alternately startup/shutdown can initialize or power down the hardware,
clearStatus is meant to be some sort of soft reset, and isInserted is allowing
to test if the SD card is inserted & working.
read/write sectors are reading/writing one or more sectors. Sector size is 200h
bytes, sector numbers is 0=First 200h bytes, 1=Next 200h bytes, and so on.
buf should be usually 4-byte aligned, however, some drivers do also support
unaligned buffers using slower transfer code (better implement that when making
.dldi drivers, but better don't rely on it being supported when making .nds
files).
The driver functions can support SD and SDHC (or the flashcart manufacturer
might release driver updates if SDHC wasn't supported).
Higher level FAT functions must be contained in the .nds file (so a driver
update won't help if the .nds file lacks FAT32) (and ExFAT most unlikely to be
supported).
Functions should be ARM7 compatible, ie. don't use BLX or POP r15 for mode
switching, so the driver can be used on both ARM9 and ARM7 (or even on GBA).
SLOT_GBA/NDS
SLOT_GBA/NDS seem to relate to GBA and NDS slots, the driver can probably have
only one of the SLOT bits set (the functions don't allow to select which slot
to use).
Purpose is unclear to me, maybe just telling the .nds file that the flashcart
is in the given slot (and thereby shouldn't expect other hardware in that
slot). Or maybe telling telling the installer which hardware the driver is
supposed for.
FIX_xxx does maybe relate to address adjustments made by the dldi installer.
Unknown if/how that's working.
--> DS Cart DLDI Driver - Guessed Address-Adjustments
Some DLDI flashcarts support extra features like Rumble. However, that extra
hardware is accessed via direct I/O, not via DLDI driver. Unknown which I/O
ports are used for that stuff - probably something compatible with official
GBA/NDS rumble cart(s).
The DLDI installer uses some guessing method for address-adjustments (the
FIX_xxx flags are supposed to patch addresses, but not opcodes or other data).
FIX_GOT
GOT does usually contain BF80xxxxh address pointers (plus some 00000000h
words). The guessing works quite stable (the maximum for 32K files is
xxxxh=7FFFh, so there's no risk to encounter xxxx=BF80h) (one could encounter
xxxxh=xxBFh, but the previously patched word is usually in RAM area, eg.
02xxxxxxh, so this would form BF02h, without risk to be seen as BF80h).
BUG: The GOT table is usually located at the end of the .dldi file, meaning
that the over-shooting bug will see three uninitialized bytes at
[got_end+0..2], and may go amok if they are BF80xxh or xxBF80h. The value of
those bytes depends on left-over from previously installed .dldi driver(s) and
on the ddmem base used in the .nds file, so the bug may take place randomly
depending on several factors.
FIX_GLUE
GLUE does usually contain a handful of opcodes and .pool values for switching
between ARM and THUMB code. The intention is to patch the addresses in the
.pool, and to leave the opcodes intact. This can be potentially stable,
assuming that the used opcodes in the GLUE (and the next three bytes after
glue_end) usually won't contain BF80h).
FIX_ALL
This is the mother of all bugs. Fortunately there aren't any .dldi drivers with
FIX_ALL flag - and one should never make drivers that do use it.
ALL is covering the whole dldi space, including the 80h-byte DLDI header, the
code area, including GLUE area, and GOT area, and probably also the yet
uninitialized BSS area, and the next three bytes after end_all.
Patching the whole code area means an increased risk to hit opcodes or data
values that contain BF80h. The over-shooting bug may even destroy the next
three bytes after the 32Kbyte area.
Patching the DLDI header could destroy the header itself, the header in the
.dldi file usually won't contain BF80h at unintended locations, however, the
pointers in that header are adjusted before applying FIX_ALL, for example, RAM
base 0200BF00h (in .nds file) combined with a function at BF800080h (in .dldi
file) would result in 0200BF80h. The nasty thing is that the problem won't
occur with other RAM base values (in other .nds files).
KEY1 encryption is used for KEY1 encrypted gamecart commands (ie. for loading
the secure area). It is also used for resolving the extra decryption of the
first 2K of the secure area, and for firmware decryption, and to decode some
encrypted values in gamecart/firmware header.
encrypt_64bit(ptr) / decrypt_64bit(ptr)
Y=[ptr+0]
X=[ptr+4]
FOR I=0 TO 0Fh (encrypt), or FOR I=11h TO 02h (decrypt)
Z=[keybuf+I*4] XOR X
X=[keybuf+048h+((Z SHR 24) AND FFh)*4]
X=[keybuf+448h+((Z SHR 16) AND FFh)*4] + X
X=[keybuf+848h+((Z SHR 8) AND FFh)*4] XOR X
X=[keybuf+C48h+((Z SHR 0) AND FFh)*4] + X
X=Y XOR X
Y=Z
NEXT I
[ptr+0]=X XOR [keybuf+40h] (encrypt), or [ptr+0]=X XOR [keybuf+4h] (decrypt)
[ptr+4]=Y XOR [keybuf+44h] (encrypt), or [ptr+4]=Y XOR [keybuf+0h] (decrypt)
apply_keycode(modulo)
encrypt_64bit(keycode+4)
encrypt_64bit(keycode+0)
[scratch]=0000000000000000h ;S=0 (64bit)
FOR I=0 TO 44h STEP 4 ;xor with reversed byte-order (bswap)
[keybuf+I]=[keybuf+I] XOR bswap_32bit([keycode+(I MOD modulo)])
NEXT I
FOR I=0 TO 1040h STEP 8
encrypt_64bit(scratch) ;encrypt S (64bit) by keybuf
[keybuf+I+0]=[scratch+4] ;write S to keybuf (first upper 32bit)
[keybuf+I+4]=[scratch+0] ;write S to keybuf (then lower 32bit)
NEXT I
init_keycode(idcode,level,modulo,key)
if key=nds then copy [nds_arm7bios+0030h..1077h] to [keybuf+0..1047h]
if key=dsi then copy [dsi_arm7bios+C6D0h..D717h] to [keybuf+0..1047h]
[keycode+0]=[idcode]
[keycode+4]=[idcode]/2
[keycode+8]=[idcode]*2
IF level>=1 THEN apply_keycode(modulo) ;first apply (always)
IF level>=2 THEN apply_keycode(modulo) ;second apply (optional)
[keycode+4]=[keycode+4]*2
[keycode+8]=[keycode+8]/2
IF level>=3 THEN apply_keycode(modulo) ;third apply (optional)
firmware_decryption
init_keycode(firmware_header+08h,1,0Ch,nds) ;idcode (usually "MACP"), level 1
decrypt_64bit(firmware_header+18h) ;rominfo
init_keycode(firmware_header+08h,2,0Ch,nds) ;idcode (usually "MACP"), level 2
decrypt ARM9 and ARM7 bootcode by decrypt_64bit (each 8 bytes)
decompress ARM9 and ARM7 bootcode by LZ77 function (swi)
calc CRC16 on decrypted/decompressed ARM9 bootcode followed by ARM7 bootcode
Note: The sizes of the compressed/encrypted bootcode areas are unknown (until
they are fully decompressed), one way to solve that problem is to decrypt the
next 8 bytes each time when the decompression function requires more data.
gamecart_decryption
init_keycode(cart_header+0Ch,1,08h,nds) ;gamecode, level 1, modulo 8
decrypt_64bit(cart_header+78h) ;rominfo (secure area disable)
init_keycode(cart_header+0Ch,2,08h,nds) ;gamecode, level 2, modulo 8
encrypt_64bit all NDS KEY1 commands (1st command byte in MSB of 64bit value)
after loading the secure_area, calculate secure_area crc, then
decrypt_64bit(secure_area+0) ;first 8 bytes of secure area
init_keycode(cart_header+0Ch,3,08h,nds) ;gamecode, level 3, modulo 8
decrypt_64bit(secure_area+0..7F8h) ;each 8 bytes in first 2K of secure
init_keycode(cart_header+0Ch,1,08h,dsi) ;gamecode, level 1, modulo 8
encrypt_64bit all DSi KEY1 commands (1st command byte in MSB of 64bit value)
After secure area decryption, the ID field in the first 8 bytes should be
"encryObj", if it matches then first 8 bytes are filled with E7FFDEFFh,
otherwise the whole 2K are filled by that value.
Note
The KEY1 encryption is based on Bruce Schneier's "Blowfish Encryption
Algorithm".
KEY2 Encryption
Relies on two 39bit registers (x and y), which are initialized as such:
x = reversed_bit_order(seed0) ;ie. LSB(bit0) exchanged with MSB(bit38), etc.
y = reversed_bit_order(seed1)
During transfer, x, y, and transferred data are modified as such:
x = (((x shr 5)xor(x shr 17)xor(x shr 18)xor(x shr 31)) and 0FFh)+(x shl 8)
y = (((y shr 5)xor(y shr 23)xor(y shr 18)xor(y shr 31)) and 0FFh)+(y shl 8)
data = (data xor x xor y) and 0FFh
Instruction Codes
06h WREN Write Enable (No Parameters)
04h WRDI Write Disable (No Parameters)
9Fh RDID Read JEDEC Identification (Read 1..3 ID Bytes)
(Manufacturer, Device Type, Capacity)
05h RDSR Read Status Register (Read Status Register, endless repeated)
Bit7-2 Not used (zero)
Bit1 WEL Write Enable Latch (0=No, 1=Enable)
Bit0 WIP Write/Program/Erase in Progess (0=No, 1=Busy)
03h READ Read Data Bytes (Write 3-Byte-Address, read endless data stream)
0Bh FAST Read Data Bytes at Higher Speed (Write 3-Byte-Address, write 1
dummy-byte, read endless data stream) (max 25Mbit/s)
0Ah PW Page Write (Write 3-Byte-Address, write 1..256 data bytes)
(changing bits to 0 or 1) (reads unchanged data, erases the page,
then writes new & unchanged data) (11ms typ, 25ms max)
02h PP Page Program (Write 3-Byte-Address, write 1..256 data bytes)
(changing bits from 1 to 0) (1.2ms typ, 5ms max)
DBh PE Page Erase 100h bytes (Write 3-Byte-Address) (10ms typ, 20ms max)
D8h SE Sector Erase 10000h bytes (Write 3-Byte-Address) (1s typ, 5s max)
B9h DP Deep Power-down (No Parameters) (consumption 1uA typ, 10uA max)
(3us) (ignores all further instructions, except RDP)
ABh RDP Release from Deep Power-down (No Parameters) (30us)
Write/Program may not cross page-boundaries. Write/Program/Erase are rejected
during first 1..10ms after power up. The WEL bit is automatically cleared on
Power-Up, on /Reset, and on completion of WRDI/PW/PP/PE/SE instructions. WEL is
set by WREN instruction (which must be issued before any write/program/erase
instructions). Don't know how RDSR behaves when trying to write to the
write-protected region?
Communication Protocol
Set Chip Select LOW to invoke the command
Transmit the instruction byte
Transmit any parameter bytes
Transmit/receive any data bytes
Set Chip Select HIGH to finish the command
All bytes (and 3-byte addresses) transferred most significant bit/byte first.
DS Firmware Header
------------------
DSi
000h 1Dh Zerofilled (bootcode is in new eMMC chip, not on old FLASH chip)
01Dh 6 Same as on DS (header: Console Type and User Settings Offset)
022h 6 Zerofilled (bootcode is in new eMMC chip, not on old FLASH chip)
028h..1FCh Same as on DS (wifi calibration)
1FDh 1 Wifi Board (01h=DWM-W015, 02h=W024, 03h=W028) ;\this was
1FEh 1 Wifi Flash (20h=With access point 4/5/6) ; FFh-filled
1FFh 1 Same as on DS (FFh) ;/on DS
200h FFh Zerofilled ;\
2FFh 1 Unknown (80h) ; this was
300h 1F000h FFh's (not write-able on 4K chips) ; bootcode
1F300h FFh FFh's (write-able) ;twl-debugger: 00h's ; on DS
1F3FFh 1 FFh ;twl-debugger: 40h ;/
The bytes [000h..027h] cannot be changed on DSi because they are part of the
RSA signature in DSi's Boot Info Block (at eMMC offset 200h..3FFh).
Moreover, a LOT of values are different with Type3 chips (ie. when [040h]=3).
Note
Unlike for Firmware User Settings, the Firmware Header (and Wifi Settings)
aren't stored in RAM upon boot. So the data must be retrieved via SPI bus by
software.
Note
The location of the user settings & connection data varies (eg. 01Fxxxh=DSi,
03Fxxxh=NDS, 07Fxxxh=iQueDS).
Note: There are two User Settings areas in the firmware chip, at offset 3FE00h
and 3FF00h, if both areas have valid CRCs, then the current/newest area is that
whose Update Counter is one bigger than in the other/older area.
IF count1=((count0+1) AND 7Fh) THEN area1=newer ELSE area0=newer
When changing settings, the older area is overwritten with new data (and
incremented Update Counter). The two areas allow to recover previous settings
in case of a write-error (eg. on a battery failure during write).
Battery Removal
Even though the battery is required only for the RTC (not for the firmware
flash memory), most of the firmware user settings are reset when removing the
battery. This appears to be a strange bug-or-feature of the DS bios, at least,
fortunately, it still keeps the rest of the firmware intact.
DS File Formats
---------------
MESG files contain localized strings (like "Okay" and "Cancel" and longer text
messages). Different languages are stored separate message files, usually with
.bmg extension. MESG files are used in NDS/DSi titles (in little endian), and
also on Wii (in big endian).
DSi titles are: DSi Shop, Launcher, System Settings, and DSi Camera (however,
the DSi-to-3DS Transfer Tool uses the newer MsgPrjBn/MsgStdBn format; despite
of being a DSi program).
MESG Header
000h 8 ID "MESGbmg1" ;or "GSEM1gmb" in Super Mario 64 DS
008h 4 Total Filesize ;or Filesize+1 in Super Mario 64 DS
00Ch 4 Number of Chunks (2=INF1+DAT1, 3=INF1+DAT1+MID1)
010h 1 Encoding (1=CP1252, 2=UTF-16, 3=Shift-JIS, 4=UTF-8)
011h 15 Padding (0)
Encoding UTF-16 appears to be most common (Super Mario 64 DS uses Shift-JIS).
Thanks to http://wiki.tockdom.com/wiki/BMG
NTPG File (manual pages) (or rather chapters?) (in "ntpg\xx\" folders)
The pages can contain text, tables, and symbols/images/screenshots (there
appears to be no support for hyperlinks inside of the pages; probably because
they default to be displayed on upper screen, without touchscreen support).
000h 4 ID "NTPC"
004h 2 Byte Order (FEFFh)
006h 2 Version (can be 0200h)
008h 4 Total Filesize
00Ch 2 Header Size (10h)
00Eh 4 Number of Chunks (usually 7 = nap1+txp1+pag1+pan1+pas1+txt1+pae1)
nap1 Chunk
000h 4 Chunk ID "nap1"
004h 4 Chunk Size (10h)
008h 4 Zero (unlike as in NTMC file)
00Ch 4 Unknown (4)
txp1 Chunk
000h 4 Chunk ID "txp1"
004h 4 Chunk Size
008h 4 Number of something?? minus 1 (eg. 02h=03h)
00Ch 4*N Offsets to something?? (from txp1+0Ch)
... .. UTF-16 strings (Headline, Body, Footer?)
pag1 Chunk
000h 4 Chunk ID "pag1"
004h 4 Chunk Size (10h)
008h 2? 0000h text color black?
00Ah 2? 0160h link color or so?
00Ch 2? 7FFFh bg color white?
00Eh 2? 0000h
pan1 Chunk
000h 4 Chunk ID "pan1"
004h 4 Chunk Size (10h)
008h 2? 0000h
00Ah 2? 0000h
00Ch 2? 0100h
00Eh 2? 0160h link color or so?
pas1 Chunk (start?)
000h 4 Chunk ID "pan1"
004h 4 Chunk Size (0Ch)
008h 4? 00000001h
txt1 Chunk
000h 4 Chunk ID "txt1"
004h 4 Chunk Size
008h 2? 0008h
00Ah 2? 0008h
00Ch 2? 00F0h
00Eh 2? 0150h
010h 2? 0001h
012h 2? 0015h Number of 8-byte entries? start/end line-wrapping list?
014h 2? 000Dh
016h 2? 0010h
018h 4? 00000000h
01Ch 4? 00001CE7h
020h 4? 00000000h
024h 4? 00000000h
028h N*8 Unknown 8-byte entries? (00xxh,0010h,0000h,00yyh)
Or maybe positioning for symbols/images/tables?
pae1 Chunk (end?)
000h 4 Chunk ID "pae1"
004h 4 Chunk Size (08h)
Notes
DSi manuals are using the TWLFontTable.dat system font (Flipnote, at least).
3DS manuals consist of CLYT and CLIM files (inside of a manual BCMA darc
archive in a NCCH file).
DS Wireless Communications
--------------------------
Credits
A very large part of the DS Wifi chapters is based on Stephen Stair's great DS
Wifi document, thanks there.
DS Wifi I/O Map
---------------
Notice
Wifi Registers & RAM cannot be written to by STRB opcodes (ignored).
Additionally, there are 69h Baseband Chip Registers (BB), and 0Fh RF Chip
Registers (see BB and RF chapters).
For Wifi Power Managment (POWCNT2), for Wifi Waitstates (WIFIWAITCNT), see:
--> DS Power Control
For the Power LED Blink Feature (conventionally used to indicate Wifi activity)
see:
--> DS Power Management Device
DS Wifi Control
---------------
DS Wifi Interrupts
------------------
The dimensions of the circular Buffer are set with BEGIN/END values, hardware
automatically wraps to BEGIN when an incremented pointer hits END address.
Write Area
Memory between WRCSR and READCSR is free for receiving data, the hardware
writes incoming packets to this region (to WRCSR and up) (but without exceeding
READCSR), once when it has successfully received a complete packet, the
hardware moves WRCSR after the packet (aligned to a 4-byte boundary).
Read Area
Memory between READCSR and WRCSR contains received data, which can be read by
the CPU via RD_ADDR and RD_DATA registers (or directly from memory). Once when
having processed that data, the CPU must set READCSR to the end of it.
Note: W_TXBUF_GAP and W_TXBUF_GAPDISP may be (not TOO probably) also used by
transmits via W_TXBUF_LOCn and W_TXBUF_BEACON (not tested).
Automatic ACKs
Transmit errors occur on missing ACKs. The NDS hardware is automatically
responding with an ACK when receiving a packet (if it has been addressed to the
receipients W_MACADDR setting). And, when sending a packet, the NDS hardware is
automatically checking for ACK responses.
The only exception are packets that are sent to group addresses (ie. Bit0 of
the 48bit MAC address being set to "1", eg. Beacons sent to FF:FF:FF:FF:FF:FF),
the receipient(s) don't need to respond to such packets, and the sender always
passes okay without checking for ACKs.
Error Notification
Transmit Errors can be sensed via W_TX_ERR_COUNT, IRQ03, IRQ05, TX Hardware
Header entry [00h], and W_TXSTAT.Bit1.
W_TXBUF_BEACON Errors
As the name says, W_TXBUF_BEACON is intended for sending Beacons to group
addresses (which do not require to respond by ACKs). So, transmit errors would
occur only when mis-using W_TXBUF_BEACON to send packets to individual
addresses, but the W_TXBUF_BEACON error handling isn't fully implemented:
First of, W_TX_RETRYLIMIT isn't used, instead, W_TXBUF_BEACON errors will
result in infinite retries.
Moreover, W_TXBUF_BEACON errors seem to increment W_TX_ERR_COUNT, but without
generating IRQ03, however, IRQ05 is generated when W_TX_ERR_COUNT>7Fh.
Other Errors
The NDS transmit hardware seems to do little error checking on the packet
headers. The only known error-checked part is byte [04h] in the TX hardware
header (which must be 00h, 01h, or 02h). Aside from that, when sent to a group
address, it is passing okay even with invalid IEEE type/subtypes, and even with
Length/Rate entries set to zero. However, when sending such data to an
individual address, the receiving NDS won't respond by ACKs.
Note
Received ACKs aren't stored in WifiRAM (or, possibly, they ARE stored, but
without advancing W_RXBUF_WRCSR, so that the software won't see them, and so
that they will be overwritten by the next packet).
DS Wifi Status
--------------
DS Wifi Timers
--------------
These registers are used for multiplay host-to-client (aka master to slave)
commands.
At 2MBit/s transfer rate, the values should be set up sorts of like so:
master_time = (master_bytes*4)+(60h) ;60h = 96 decimal = short preamble
slave_time = (slave_bytes*4)+(0D0h..0D2h)
all_slave_time = (EAh..F0h)+(slave_time+0Ah)*num_slaves
txhdr[2] = slave_bits ;hardware header (*)
ieee[2] = all_slave_time ;ieee header (duration/id)
body[0] = slave_time ;duration per slave (for multiboot/pictochat)
body[2] = slave_bits ;frame body -- required (*)
[48080C0h] = all_slave_time ;W_CMD_TOTALTIME
[48080C4h] = slave_time ;W_CMD_REPLYTIME duration per slave
[4808118h] = (388h+(num_slaves*slave_time)+master_time+32h)/10 ;W_CMD_COUNT
[4808090h] = 8000h+master_packet_address ;start transmit ;W_TXBUF_CMD
With the byte values counting the ieee frame header+body+fcs.
(*) The hardware doesn't actually seem to use the "slave_bits" entry in the
hardware header, instead, it is using the "slave_bits" entry in the frame
body(!)
These registers are used for multiplay client-to-host (aka slave to master)
responses.
on client side
The reply transfer is automatically initiated when receiving a MP CMD frame
(this seems to be based on the incoming IEEE header's frame control value
and/or broadcast address, CMD frames typically have FC=0228h).
When receiving the MP CMD frame, the hardware determines its position using its
W_AID_LOW register and the frame's client bitmask, then waits for its turn to
reply.
Reportedly...
It will always send a reply - if W_TXBUF_REPLY1 isn't configured, it will send
an empty reply frame (with frame control 0x0158). W_RXTXADDR isn't modified
when sending a default empty reply.
Important BB Registers
Registers 0..68h are initialized by firmware bootcode, and (most) of these
settings do not need to be changed by other programs, except for:
Addr Initial Meaning
01h 0x9E [unsetting/resetting bit 7 initializes/resets the system?]
02h unknown (firmware is messing with this register)
06h unknown (firmware is messing with this register, too)
13h 0x00 CCA operation - criteria for receiving
0=only use Carrier Sense (CS)
1=only use Energy Detection (ED)
2=receive if CS OR ED
3=receive only if CS AND ED
1Eh 0xBB see change channels flowchart (Ext. Gain when RF[09h].bit16=0)
35h 0x1F Energy Detection (ED) criteria
value 0..61 (representing energy levels of -60dBm to -80dBm)
DS Wifi RF Chip
---------------
RF-Chip RF9008 (compatible to RF2958 from RF Micro Devices, Inc.) (Original DS)
BB/RF-Chip Mitsumi MM3218 (DS-Lite)
---
Below Ports W_X_244h and W_X_228h might be related to deciding when to send
multiplay replies...?
---
---
W_INTERNAL
All registers marked as "W_INTERNAL" aren't used by Firmware part4, and are
probably unimportant, except for whatever special diagnostics purposes.
Wifi DMA
Wifi RAM can be accessed with normal "Start Immediately" DMA transfers
(typically by reading through W_RXBUF_RD_DATA, so the DMA automatically wraps
from END to BEGIN).
Additionally, DMA0 and DMA2 can be reportedly synchronized to "Wireless
Interrupt" (rather than using "Start Immediately" timing), no idea if/how
that's working though... and if it gets started on any Wifi IRQ, or only on
specific IRQs...?
Possibly some of the above unknown registers, or some unknown bits in other
registers, are DMA related...?
Reportedly, early firmwares did use "Wireless Interrupt" DMAs (that'd be
firmware v1/v2... or, only earlier unreleased prototype versions?).
DS Wifi Initialization
----------------------
Initialization sequence
These events must be done somewhat in sequence. There is some flexibility as to
how they can be ordered but it's best to follow this order:
[4000304h].Bit1 = 1 ;POWCNT2 ;-Enable power to the wifi system
W_MACADDR = firmware[036h] ;-Set 48bit Mac address
reg[012h] = 0000h ;W_IE ;-Disable interrupts
Wake Up the wireless system:
reg[036h] = 0000h ;W_POWER_US ;\clear all powerdown bits
delay 8 ms ; (works without that killer-delay ?)
reg[168h] = 0000h ;W_BB_POWER ;/
IF firmware[040h]=02h ;\
temp=BB[01h] ; for wifitype=02h only:
BB[01h]=temp AND 7Fh ; reset BB[01h].Bit7, then restore old BB[01h]
BB[01h]=temp ; (that BB setting enables the RF9008 chip)
ENDIF ;/
delay 30 ms ;-(more killer-delay now getting REALLY slow)
call init_sub_functions ;- same as "Init 16 registers by firmware[..]"
; and "Init RF registers", below.
; this or the other one probably not necessary
Init the Mac system:
reg[004h] = 0000h - W_MODE_RST ;set hardware mode
reg[008h] = 0000h - W_TXSTATCNT ;
reg[00Ah] = 0000h - ? W_X_00Ah ;(related to rx filter)
reg[012h] = 0000h - W_IE ;disable interrupts (again)
reg[010h] = FFFFh - W_IF ;acknowledge/clear any interrupts
reg[254h] = 0000h - W_CONFIG_254h ;
reg[0B4h] = FFFFh - W_TXBUF_RESET ;--reset all TXBUF_LOC's
reg[080h] = 0000h - W_TXBUF_BEACON ;disable automatic beacon transmission
reg[02Ah] = 0000h - W_AID_FULL ;\clear AID
reg[028h] = 0000h - W_AID_LOW ;/
reg[0E8h] = 0000h - W_US_COUNTCNT ;disable microsecond counter
reg[0EAh] = 0000h - W_US_COMPARECNT ;disable microsecond compare
reg[0EEh] = 0001h - W_CMD_COUNTCNT ;(is 0001h on reset anyways)
reg[0ECh] = 3F03h - W_CONFIG_0ECh ;
reg[1A2h] = 0001h - ? ;
reg[1A0h] = 0000h - ? ;
reg[110h] = 0800h - W_PRE_BEACON ;
reg[0BCh] = 0001h - W_PREAMBLE ;disable short preamble
reg[0D4h] = 0003h - W_CONFIG_0D4h ;
reg[0D8h] = 0004h - W_CONFIG_0D8h ;
reg[0DAh] = 0602h - W_RX_LEN_CROP ;
reg[076h] = 0000h - W_TXBUF_GAPDISP ;disable gap/skip (offset=zero)
Init 16 registers by firmware[044h..063h]
reg[146h] = firmware[044h] ;W_CONFIG_146h
reg[148h] = firmware[046h] ;W_CONFIG_148h
reg[14Ah] = firmware[048h] ;W_CONFIG_14Ah
reg[14Ch] = firmware[04Ah] ;W_CONFIG_14Ch
reg[120h] = firmware[04Ch] ;W_CONFIG_120h
reg[122h] = firmware[04Eh] ;W_CONFIG_122h
reg[154h] = firmware[050h] ;W_CONFIG_154h
reg[144h] = firmware[052h] ;W_CONFIG_144h
reg[130h] = firmware[054h] ;W_CONFIG_130h
reg[132h] = firmware[056h] ;W_CONFIG_132h
reg[140h] = firmware[058h] ;W_CONFIG_140h
reg[142h] = firmware[05Ah] ;W_CONFIG_142h
reg[038h] = firmware[05Ch] ;W_POWER_TX
reg[124h] = firmware[05Eh] ;W_CONFIG_124h
reg[128h] = firmware[060h] ;W_CONFIG_128h
reg[150h] = firmware[062h] ;W_CONFIG_150h
Init RF registers
numbits = BYTE firmware[041h] ;usually 18h
numbytes = (numbits+7)/8 ;usually 3
reg[0x184] = (numbits+80h) AND 017Fh -- W_RF_CNT
for i=0 to BYTE firmware[042h]-1 ;number of entries (usually 0Ch) (0..0Bh)
if BYTE firmware[040h]=3
RF[i]=firmware[0CEh+i]
else
RF_Write(numbytes at firmware[0CEh+i*numbytes])
endif
Init the BaseBand System
(this should be not required, already set by firmware bootcode)
reg[160h] = 0100h ;W_BB_MODE
BB[0..68h] = firmware[64h+(0..68h)]
Set Mac address
copy 6 bytes from firmware[036h] to mac address at 0x04800018 (why again ?)
Now just set some default variables
reg[02Ch]=0007h ;W_TX_RETRYLIMIT - XXX needs to be set for every transmit?
Set channel (see section on changing channels)
Set Mode 2 -- sets bottom 3 bits of W_MODE_WEP to 2
Set Wep Mode / key -- Wep mode is bits 3..5 of W_MODE_WEP
BB[13h] = 00h ;CCA operation (use only carrier sense, without ED)
BB[35h] = 1Fh ;Energy Detection Threshold (ED)
-- To further init wifi to the point that you can properly send
-- and receive data, there are some more variables that need to be set.
reg[032h] = 8000h -- W_WEP_CNT ;Enable WEP processing
reg[134h] = FFFFh -- W_POST_BEACON ;reset post-beacon counter to LONG time
reg[028h] = 0000h -- W_AID_LOW ;\clear W_AID value, again?!
reg[02Ah] = 0000h -- W_AID_FULL ;/
reg[0E8h] = 0001h -- W_US_COUNTCNT ;enable microsecond counter
reg[038h] = 0000h -- W_POWER_TX ;disable transmit power save
reg[020h] = 0000h -- W_BSSID_0 ;\
reg[022h] = 0000h -- W_BSSID_1 ; clear BSSID
reg[024h] = 0000h -- W_BSSID_2 ;/
-- TX prepare
reg[0AEh] = 000Dh -- W_TXREQ_SET ;flush all pending transmits (uh?)
-- RX prepare
reg[030h] = 8000h W_RXCNT ;enable RX system (done again below)
reg[050h] = 4C00h W_RXBUF_BEGIN ;(example values)
reg[052h] = 5F60h W_RXBUF_END ;(length = 4960 bytes)
reg[056h] = 0C00h/2 W_RXBUF_WR_ADDR ;fifo begin latch address
reg[05Ah] = 0C00h/2 W_RXBUF_READCSR ;fifo end, same as begin at start.
reg[062h] = 5F60h-2 W_RXBUF_GAP ;(set gap<end) (zero should work, too)
reg[030h] = 8001h W_RXCNT ;enable, and latch new fifo values to hardware
--
reg[030h] = 8000hW_RXCNT enable receive (again?)
reg[010h] = FFFFhW_IF clear interrupt flags
reg[012h] = whatever
W_IE set enabled interrupts
reg[1AEh] = 1FFFhW_RXSTAT_OVF_IE desired STAT Overflow interrupts
reg[1AAh] = 0000hW_RXSTAT_INC_IE desired STAT Increase interrupts
reg[0D0h] = 0181hW_RXFILTER set to 0x581 when you successfully connect
to an access point and fill W_BSSID with a mac
address for it. (W_RXFILTER) [not sure on the values
for this yet]
reg[0E0h] = 000Bh -- W_RXFILTER2 ;
reg[008h] = 0000h -- ? W_TXSTATCNT ;(again?)
reg[00Ah] = 0000h -- ? W_X_00Ah ;(related to rx filter) (again?)
reg[004h] = 0001h -- W_MODE_RST ;hardware mode
reg[0E8h] = 0001h -- W_US_COUNTCNT ;enable microsecond counter (again?)
reg[0EAh] = 0001h -- W_US_COMPARECNT ;enable microsecond compare
reg[048h] = 0000h -- W_POWER_? ;[disabling a power saving technique]
reg[038h].Bit1 = 0 -- W_POWER_TX ;[this too]
reg[048h] = 0000h -- W_POWER_? ;[umm, it's done again. necessary?]
reg[0AEh] = 0002h -- W_TXREQ_SET ;
reg[03Ch].Bit1 = 1 -- W_POWERSTATE ;queue enable power (RX power, we believe)
reg[0ACh] = FFFFh -- W_TXREQ_RESET;reset LOC1..3
That's it, the DS should be now happy to send and receive packets.
It's very possible that there are some unnecessary registers set in here.
DS Wifi Flowcharts
------------------
Channels
The IEEE802.11b standard (and the NDS hardware) support 14 channels (1..14).
Channels 1..13 use frequencies 2412MHz..2472MHz (in 5MHz steps). Channel 14
uses frequency 2484MHz. Which channels are allowed to be used varies from
country to country, as indicated by Bit1..14 of firmware[03Ch]. Channel 14 is
rarely used (dated back to an older japanese standard).
Important note! TX length includes the length of a 4-byte "FCS" (checksum) for
the packet. The hardware generates the FCS for you, but you still must include
it in the packet length. Also note that if the 802.11 WEP enabled bit is set in
the header, the packet will be automatically encrypted via the wep algorithm -
however, the software is responsible for providing the 4-byte IV block with the
WEP key ID and the 24bit IV value. - ALSO, you must include the length of the
*encrypted* FCS used in packets that have wep enabled (increase the tx length
by another 4 bytes) - this value is calculated automaticly for you, but you are
responsible for including it in the length of your packet (if you have data
there, it'll be replaced by the FCS.)
IEEE Header
The above Hardware headers should (must) be followed by valid IEEE headers.
Although that headers are to be generated by software, the hardware does do
some interaction with the IEEE headers, such like comparing address fields with
W_MACADDR and W_BSSID. And, it does modify some entries of it:
1) The sequence control value is replaced by W_TX_SEQNO*10h (when enabled in
W_TXBUF_LOCn.Bit13), this replacement does also overwrite the local TXBUF
value.
2) The frame control value is modified, namely, the hardware tends to set Bit12
of it. This replacement does NOT modify the local TXBUF, but the remote RXBUF
will receive the modified value. Also, Bit0-1 (protocol version) are forcefully
set to 0.
3) Transmits via W_TXBUF_BEACON do additionally modify the 64bit timestamp (so
W_TXBUF_BEACON should be used ONLY for packets WITH timestamp, ie. Beacons or
Probe-Responses). The local TXBUF seems to be left unchanged, but the remote
RXBUF will contain the (sender's) W_US_COUNT value.
C) For Control Frames, the hardware headers Length value is transferred as
normally (ie. excluding the FCS length, remote RXBUF will contain TXBUF length
minus 4), but - no matter of that length value - only 10 or 16 bytes (depending
on the subtype) of the IEEE frame are actually transferred and/or stored in
RXBUF.
X) For Control Frames with Subtype 0Ah, the AID entry is set to C000h, that,
probably ORed with original value in WifiRAM, or with the W_AID_FULL register?
XX) No idea if it's possible to send Control Frames with subtype 0Bh..0Fh, as
for now, it seems that either they aren't sent, or the receipient is ignoring
them (or processing them internally, but without storing them in RXBUF).
Beacons are most commonly used to announce Wifi Internet Access Points. The
special Nintendo Beacons are used to announce Local Network games (randomly
broadcast on channel 1, 7, or 13).
All beacon frames transmitted by a DS host have the following format
TXHDR using 2MBit/s rate
802.11 Management frame header
802.11 Beacon header (Timestamp, BeaconInterval=00xxh, Capability=0021h)
Supported rates (Tag=01h, Len=02h, 82h,84h) ;1Mbit/s and 2Mbit/s
Distribution Channel (Tag=03h, Len=01h, 0xh) ;channel 1, 7, or 13
TIM vector (Tag=05h, Len=05h, 00h,02h,0,0,0) ;adjusted by hardware
Custom extension (Tag=DDh, Len=18h+N, see below)
Authentication/Association process
Connecting to a Host console is done via standard 802.11 managment frames. The
Auth/Assoc Requests must be sent during the listen interval (ie. shortly after
having received beacons).
Host sends beacon(s)
Client sends an Authentication Request (AuthSeq=1) ;\Auth
Host sends an Authentication Response (AuthSeq=2) ;/
Host sends beacon(s)
Client sends an Association Request (with special SSID) ;\Assoc
Host sends an Association Response ;/
Host sends beacon(s) and begins sending CMD/Data packets
The Nintendo Beacons are transferred without public SSID (without Tag=00h).
However, the Association Request must contain a SSID, which is derived from the
custom Tag=DDh area.
SSID for multiboot (20h-byte binary, non-ASCII):
00h 4 Game ID (0040xxxxh) (from Beacon Tag=DDh, entry 0Ch)
04h 2 Stream code (from Beacon Tag=DDh, entry 10h)
06h 1Ah Zerofilled
Multicart games or Pictochat may use whatever SSID's they want (unknown if
there is standard for that).
DS Download Play allows to download small games from other NDS/DSi consoles.
This is also known as Wireless Multiboot (WMB), or Single Gamecart Multiplay.
160h-byte Header
Some Download Play titles have faulty header entries (eg. Table Hockey Tech
Demo, with nonsense Icon offset etc). In such cases, dumps are conventionally
having a manually repaired header & an extra copy of the original header:
0000h 160h Repaired Header (address/size/entrypoint for ARM9,ARM7,Icon,RSA)
0160h A0h Zerofilled
0200h 10h ID "DS DOWNLOAD PLAY" (8bit characters)
0210h 10h ID "----------------" (8bit characters)
0220h 160h Original Header (to be uploaded for RSA check)
0380h 10h ID "----------------" (8bit characters)
0390h 10h ID "Nintendo" (16bit characters)
03A0h 10h ID Zerofilled
03B0h 10h ID "----------------" (8bit characters)
03C0h .. Zerofilled
The 160h-byte Header itself is about same as in ROM-images. The Icon/Title
entry contains the information that is broadcast in Beacons. The Total Size
entry points to the 88h-byte RSA Signature. The File/Overlay entries contain
unused/dummy values.
Beacons
Beacons should be kept sent during transfer, however, the DS Download tool
throws a Deauth message when receiving more than 15 beacons with data traffic
(ie. one must pause uploading at least each 16th beacon).
Also, the download should try to sync itself to the LCD Video Sync value in the
Beacon (supposedly interpreted relative to the IEEE Beacon Timestamp) (with
small uploads, there's probably not enough time to complete the
synchronization, so the uploaded executable may still have to finish the
synchronization by itself).
Entrypoint/Memory
The Entrypoints are supposedly taken from the RSA frame (not from the 160h-byte
header)? There is some error checking on the RSA frame addresses (eg. ARM7 area
must exist and must apparently point to RAM or WRAM). Additionally, there is
some special info in RAM:
27FFC40h 2 Boot Indicator (2=Booted from DS Download Play via Wifi)
27FFC42h 2 Beacon Size (0060h, based on Tag=DDh size: "(88h-08h+41h)/2")
27FFC44h 2 Looks like RSSI Signal Strength AND FEh (eg. 12h=Low, 82h=High)
27FFC46h 6 BSSID (master's MAC address)
27FFC4Ch 2 SSID Size? (0020h)
27FFC4Eh 4 SSID Game Serial ID (0040xxxxh)
27FFC52h 2 SSID Random Stream ID (xxxxh)
27FFC54h 1Ah SSID Padding? (zerofilled)
27FFC6Eh 2 Beacon Capabilities (0021h)
27FFC70h 2 Beacon Rates (bit0/1 = 1/2Mbit/s) (0003h)
27FFC72h 2 Beacon Rates (same as above) (0003h)
27FFC74h 2 Beacon Interval (00Cxh..00Dxh)
27FFC76h 2 Beacon TIM ListenInt (0002h)
27FFC78h 2 Beacon Channel (1, 7, or 13)
27FFC7Ah 04h Unknown (zerofilled)
27FFC7Eh 2 Unused? (zero) (not part of 3Ch-bytes at 27FFC42h)
Multiplayer games can use that info for communicating with each other after the
upload. The player number (needed for more than 2 players) doesn't seem to be
included in that structure, it might be still in W_AID_LOW though?
All Managment Frames have 24-byte Frame Header, with following values:
FC(2), Duration(2), DA(6), SA(6), BSSID(6), Sequence Control(2)
The content of the Frame Body depends on the FC's Subtype:
Subtype Frame Body
0 Association request Capability, ListenInterval, SSID, SuppRates
1 Association response Capability, Status, AID, SuppRates
2 Reassociation request Capability, ListenInterval, CurrAP, SSID, SuppRates
3 Reassociation response Capability, Status, AID, SuppRates
4 Probe request SSID, SuppRates
5 Probe response Same as for Beacon (but without TIM)
8 Beacon Timestamp,BeaconInterval,Capability,SSID,SuppRates,
FH Parameter Set (when using Frequency Hopping),
DS Parameter Set (when using Direct Sequence),
CF Parameter Set (when supporting PCF),
IBSS Parameter Set (when in an IBSS),
TIM (when generated by AP)
9 Announcement traffic indication message (ATIM) Body is "null" (=none?)
A Disassociation ReasonCode
B Authentication AuthAlgorithm, AuthSequence, Status, ChallengeText
C Deauthentication ReasonCode
Subtypes 6..7, and D..F are Reserved.
Capability Information
Bit0 ESS
Bit1 IBSS
Bit2 CF-Pollable
Bit3 CF-Poll Request
Bit4 Privacy
Bit5 Short Preamble (IEEE802.11b only)
Bit6 PBCC (IEEE802.11b only)
Bit7 Channel Agility (IEEE802.11b only)
Bit5-7 Reserved (0) (original IEEE802.11 specs)
Bit8-15 Reserved (0)
Listen Interval
... used to indicate to the AP how often an STA wakes to listen to Beacon
management frames. The value of this parameter is the STA's Listen Interval
parameter of the MLME-Associate. request primitive and is expressed in
units of Beacon Interval.
Reason codes
00h Reserved
01h Unspecified reason
02h Previous authentication no longer valid
03h Deauthenticated because sending station is leaving (or has left) IBSS
or ESS
04h Disassociated due to inactivity
05h Disassociated because AP is unable to handle all currently associated
stations
06h Class 2 frame received from nonauthenticated station
07h Class 3 frame received from nonassociated station
08h Disassociated because sending station is leaving (or has left) BSS
09h Station requesting (re)association is not authenticated with responding
station
0Ah..FFFFh Reserved
Status codes
00h Successful
01h Unspecified failure
02h..09h Reserved
0Ah Cannot support all requested cap's in the Capability Information field
0Bh Reassociation denied due to inability to confirm that association exists
0Ch Association denied due to reason outside the scope of this standard
0Dh Responding station doesn't support the specified authentication algorithm
0Eh Received an Authentication frame with authentication transaction sequence
number out of expected sequence
0Fh Authentication rejected because of challenge failure
10h Authentication rejected due to timeout waiting for next frame in sequence
11h Association denied because AP is unable to handle additional associated
stations
12h Association denied due to requesting station not supporting all of the
data rates in the BSSBasicRateSet parameter
13h Association denied due to requesting station not supporting
the Short Preamble option (IEEE802.11b only)
14h Association denied due to requesting station not supporting
the PBCC Modulation option (IEEE802.11b only)
15h Association denied due to requesting station not supporting
the Channel Agility option (IEEE802.11b only)
13h-15h Reserved (original IEEE802.11 specs)
16h..FFFFh Reserved
Key Data
Key Data does usually consist of element(s) in following form:
00h 1 Element ID (for WPA: DDh=RSNIE - for WPA2: 30h=RSNIE, DDh=KDE)
01h 1 Element Length of [02h..end]
02h .. Element Data (OUI's etc.)
WPA and WPA2 assign different meanings to Element ID value DDh. The 3-byte
maker prefix in OUI values does also differ for WPA/WPA2. And, the meaning of
the OUI's varies depending on WHERE they are used (eg. 00-0F-AC-02 could be a
Cipher Suite entry, or an Authentication entry):
EAPOL Descriptor Type values
WPA WPA2 Meaning
FEh 02h Indicates if ElementIDs and OUIs are WPA or WPA2
EAPOL Key Information flags/values
0089h 008Ah Handshake #1 ;\
0109h 010Ah Handshake #2 ; 4-way Handshake
01C9h 13CAh Handshake #3 ;
0109h(again) 030Ah Handshake #4 ;/
0391h/03A1h 1382h Handshake #5 ;\Group Key Handshake
0311h/0321h 0302h Handshake #6 ;/
EAPOL Key Data Element IDs
DDh 30h Element ID for RSNIE (Robust Network Security info)
- DDh Element ID for KDE (Key Data Encapsulation)
- DDh Element ID for padding (followed by 00h-bytes)
RSNIE Prefix OUI's (WPA only):
00-50-F2-01 - Element Vendor OUI for RSNIE
RSNIE Group Cipher suite selector OUI's (aka Multicast):
00-50-F2-01 00-0F-AC-01 RSNIE Group Cipher WEP-40 (default for US/NSA)
00-50-F2-02 00-0F-AC-02 RSNIE Group Cipher TKIP (default for WPA)
00-50-F2-04 00-0F-AC-04 RSNIE Group Cipher CCMP (default for WPA2)
00-50-F2-05 00-0F-AC-05 RSNIE Group Cipher WEP-104 (default for WEP)
RSNIE Pairwise Cipher suite selector OUI's (aka Unicast):
00-50-F2-00 00-0F-AC-00 RSNIE Pairwise Cipher None (WEP, Group Cipher only)
00-50-F2-02 00-0F-AC-02 RSNIE Pairwise Cipher TKIP (default for WPA)
00-50-F2-04 00-0F-AC-04 RSNIE Pairwise Cipher CCMP (default for WPA2)
RSNIE Authentication AKM suite selector OUI's :
00-50-F2-01 00-0F-AC-01 RSNIE Authentication over IEEE 802.1X (radius?)
00-50-F2-02 00-0F-AC-02 RSNIE Authentication over PSK (default/home use)
KDE Key Data Encapsulation OUI's (WPA2 only):
- 00-0F-AC-01 KDE GTK (followed by 2+N bytes)
- 00-0F-AC-02 KDE STAKey (followed by 2+6+N bytes)
- 00-0F-AC-03 KDE MAC address (followed by 6 bytes)
- 00-0F-AC-04 KDE PMKID (followed by 16 bytes)
TKIP MIC
6 DA
6 SA
1 Priority (0) (reserved for future)
3 Zero (0) (also reserved for future)
.. Data
8 MIC (M0..M7) (aka L0..L3, R0..R3)
TKIP mixing
TTAK = Phase1 (TK, TA, TSC)
WEP seed = Phase2 (TTAK, TK, TSC)
DS Wifi FFC ID
--------------
Wifi FCC ID
The wifi hardware has been registered by Mitsumi, Hon Hai, and Nintendo
themselves:
https://fccid.io/BKE - Nintendo
https://fccid.io/EW4 - Mitsumi
https://fccid.io/MCL - Hon Hai (Foxconn)
The above webpages include some unrelated stuff (like bluetooth), and some
duplicate entries. The wifi/console related entries are:
https://fccid.io/EW4-AGBWA GBA ;\GBA wireless adaptor
https://fccid.io/EW4-OXYWA GBA-Micro ;/(not wifi/wlan compatible)
https://fccid.io/BKENTR001 NDS (non-remove-able board)
https://fccid.io/BKEUSG-001 NDS-Lite (old remove-able board, with MM3155)
https://fccid.io/EW4DWMW006 NDS-Lite (new remove-able board, with MM3218)
https://fccid.io/BKERVL036 Wii
https://fccid.io/EW4DWMW004 Wii (mitsumi) (also W016, and maybe W014 ?)
https://fccid.io/MCLJ27H010 Wii (foxconn) (also H003 ?)
https://fccid.io/EW4DWMW015 DSi (old wifi board, mitsumi)
https://fccid.io/EW4DWMW024 DSi (new wifi board, mitsumi)
https://fccid.io/MCLJ27H020 DSi (new wifi board, foxconn)
https://fccid.io/EW4DWMW028 3DS (mitsumi)
https://fccid.io/MCLJ27H023 3DS (foxconn)
https://fccid.io/MCLJ27H02301 2DS (foxconn) (also in 3DS XL)
https://fccid.io/BKERED001 New3DS (on mainboard)
The pages include test reports, photos (including some prototypes), and most
interestingly, the Mitsumi "Label location" pages are including pinout & signal
names for most wifi boards.
Below is the transfer protocol for nocash "wifiboot" and devkitpro "dslink".
All UDP/TCP message are using Port 17491 (4453h).
DS Xboo
-------
The DS Xboo cable allows to upload NDS ROM-Images (max 3.9MBytes) to the
console via parallel port connection. Should be the best, simpliest, easiest,
and fastest way to test code on real hardware. And, at a relative decent price
of 11 cents per diode it should be by far the least expensive way. You'll have
to touch classic tools (screwdrivers, knifes, saws, tweezers, and solder) which
will probably scare most of you to hell.
DS XBOO Troubleshooting
Be sure that the console is switched on, and that the XBOO cable is connected,
and that you have selected the correct parallel port in no$gba setup (the
"multiboot" options in Various Options screen), and, of course, try avoid to be
fiddling with the joypad during uploads.
I've tested the cable on two computers, the overall upload/download stuff
should work stable. The firmware access functions - which are required only for
(un-)installation - worked only with one of the two computers; try using a
different computer/parallel port in case of problems.
Nocash Firmware
The primary purpose is to receive uploaded NDS-images via parallel port
connection, additionally it's containing bootmenu and setup screens similar to
the original firmware. The user interface is having less cryptic symbols and
should be alltogether faster and easier to use. Important Information about
Whatever is supported (but it can be disabled). The setup contains a couple of
additional options like automatic daylight saving time adjustment.
The bootmenu allows to boot normal NDS and GBA carts, it does additionally
allow to boot NDS-images (or older PassMe-images) from flashcards in GBA slot.
Furthermore, benefits of asm coding, the nocash firmware occupies less than
32KBytes, allowing to store (and boot) smaller NDS-images in the unused portion
of the firmware memory (about 224KBytes), the zero-filled region between cart
header and secure area, at 200h..3FFFh, is automatically excluded, so the image
may be slightly bigger than the available free memory space.
Missing
Unlike the original firmware, the current version cannot yet boot via WLAN.
DSi Reference
-------------
General Info
--> ARM CPU Reference
--> BIOS Functions
--> External Connectors
Interrupts
There are several new interrupt sources in IE/IF registers, plus further ones
in new IE2/IF2 registers.
--> DS Interrupts
Video
Essentially same as for NDS. Some details can be changed in SCFG_EXT9. For the
2D Engine, DISPSTAT.Bit6 contains a new "LCD Initialization Ready" flag on both
ARM7 and ARM9 side (the bit is checked by DSi System Menu) (the bit is
supposedly used at power-up, maybe also for wake-up from certain sleep modes).
Enable Bits
One new DSi invention is that setting Enable Bits (eg. for NDMA or CAM
registers) is write-protecting the corresponding registers (ie. those registers
can be initialized only while the Enable Bits are off).
SPI Bus
The SPI bus works same as on NDS, except, one small change is added support for
8MHz SPI clock (in SPICNT.bit2).
RTC
Should be compatible with NDS. But seems to contain extra registers?
One of the RTC outputs does also seem to supply some (32kHz?) clock to some
other mainboard components?
[XXX see Seiko S-35199A01 datasheet].
Wifi
Supports new WPA and WPA2 encryption and supports higher transfer rates (via a
new SDIO wifi unit). For the old NDS-wifi mode, there are some new control
registers:
4004020h - SCFG_WL
4004C04h - GPIO_WIFI
BPTWL[30h] - Wifi LED related (also needed to enable Atheros Wifi SDIO)
SPI FLASH contains three new access point settings (for WPA/WPA2/proxy
support):
--> DS Firmware Wifi Internet Access Points
The access point configuration can be done via Firmware (unlike as on NDS,
where it needed to be done by the games).
GBA Slot
The GBA Slot has been removed. The memory regions and IRQ bits do still exist
internally, but the DSi does basically behave as if there is no GBA cartridge
inserted. Reading GBA ROM areas does return FFFFh halfwords instead of the
usual open bus values though.
NDS Mode
In NDS mode, the DSi is basically working same as NDS: The new extra hardware
is disabled, original NDS BIOS ROMs are mapped, and the hardware is simulating
the old touchscreen controller.
Nonetheless, there are still a some small differences to real NDS consoles:
- Unlicensed NDS carts don't work (requires RSA, or whitelist for older games)
- GBA Slot is removed (more or less behaves as if no cart inserted)
- DSi ports 4004700h and 4004C0xh can be read (and written?) even in DS mode
- SPI Power Managment has some added/removed/changed registers
- SPI Touchscreen controller doesn't support pressure & temperature
- SPI FLASH exists, but it's smaller, and has extra access point info, etc.
- ARM7 BIOS has only first 20h bytes locked (instead first 1204h bytes)
- Power Button issues a Reset (goes to boot menu) (instead of plain power off)
- Power LED blink feature (for wifi) is replaced by a separate wifi LED
- RTC extra registers (if they do really exist) should exist in DS mode (?)
Unknown: does hot-swapping auto-power-off the nds-cart-slot in nds mode?
ARM7 DSi
4000004h 2 DISPSTAT (new Bit6, LCD Initialization Ready Flag) (as DSi9?)
40001C0h 2 SPICNT (new Bit2, for 8MHz transfer clock)
4000204h 2 EXMEMCNT (removed Bit0-7: GBA-slot related bits) (as DSi9?)
4000210h 4 IE (new interrupt sources, removed GBA-slot IRQ)
4000214h 4 IF (new interrupt sources, removed GBA-slot IRQ)
4000218h IE2 (new register with more new interrupt sources)
400021Ch IF2 (new register with more new interrupt sources)
ARM7 DSi Maybe 2nd ROM slot (DSi prototypes did have 2 cartridge slots)
40021A0h 4 Unknown, nonzero, probably related to below 40021A4h
40021A4h 4 Unknown, related to 40001A4h (Gamecard Bus ROMCTRL)
40021A8h ..
40021Bxh ..
4102010h 4
ARM7 DSi System Control
4004000h 1 SCFG_A9ROM used by BIOS and SystemFlaw (bit0,1)
4004001h 1 SCFG_A7ROM used by BIOS and SystemFlaw (bit0,1,2)
4004004h 2 SCFG_CLK7 used by SystemFlaw
4004006h 2 SCFG_JTAG Debugger Control
4004008h 4 SCFG_EXT7 used by SystemFlaw
4004010h 2 SCFG_MC Memory Card Interface Control (R/W) ;\
4004012h 2 SCFG_CARD_INSERT_DELAY (usually 1988h = 100ms) ; Game Cartridge
4004014h 2 SCFG_CARD_PWROFF_DELAY (usually 264Ch = 150ms) ;/
4004020h 2 SCFG_WL Wireless Disable ;bit0 = wifi?
4004024h 2 SCFG_OP Debugger Type (R) ;bit0-1 = (0=retail, ?=debug)
ARM7 DSi New Shared WRAM Bank Control
4004040h 4 MBK1 WRAM-A Slots for Bank 0,1,2,3 ;\
4004044h 4 MBK2 WRAM-B Slots for Bank 0,1,2,3 ; Global ARM7+ARM9
4004048h 4 MBK3 WRAM-B Slots for Bank 4,5,6,7 ; Slot Mapping (R)
400404Ch 4 MBK4 WRAM-C Slots for Bank 0,1,2,3 ; (set on ARM9 side)
4004050h 4 MBK5 WRAM-C Slots for Bank 4,5,6,7 ;/
4004054h 4 MBK6 WRAM-A Address Range ;\Local ARM7 Side
4004058h 4 MBK7 WRAM-B Address Range ; (R/W)
400405Ch 4 MBK8 WRAM-C Address Range ;/
4004060h 4 MBK9 WRAM-A/B/C Slot Write Protect (R/W)
ARM7 DSi New DMA (NDMA)
4004100h 74h NewDMA (new DMA, as on ARM9i, see there)
ARM7 DSi AES Encryption Unit
4004400h 4 AES_CNT (R/W)
4004404h 4 AES_BLKCNT (W)
4004408h 4 AES_WRFIFO (W)
400440Ch 4 AES_RDFIFO (R)
4004420h 16 AES_IV (W)
4004430h 16 AES_MAC (W)
4004440h 48 AES_KEY0 (W) ;used for modcrypt
4004470h 48 AES_KEY1 (W) ;used for ?
40044A0h 48 AES_KEY2 (W) ;used for JPEG signatures
40044D0h 48 AES_KEY3 (W) ;used for eMMC sectors
ARM7 DSi I2C Bus
4004500h 1 I2C_DATA
4004501h 1 I2C_CNT
ARM7 DSi Microphone
4004600h 2 MIC_CNT Microphone Control
4004604h 4 MIC_DATA Microphone FIFO
ARM7 DSi SNDEX
4004700h 2 SNDEXCNT <-- can be read even in DS mode!
ARM7 DSi SD/MMC Registers for Memory Card access (SD Card and onboard eMMC)
4004800h 2 SD_CMD Command and Response/Data Type
4004802h 2 SD_CARD_PORT_SELECT (SD/MMC:020Fh, SDIO:010Fh)
4004804h 4 SD_CMD_PARAM0-1 Argument (32bit, 2 halfwords)
4004808h 2 SD_STOP_INTERNAL_ACTION
400480Ah 2 SD_DATA16_BLK_COUNT "Transfer Block Count"
400480Ch 16 SD_RESPONSE0-7 (128bit, 8 halfwords)
400481Ch 4 SD_IRQ_STATUS0-1 ;IRQ Status (0=ack, 1=req)
4004820h 4 SD_IRQ_MASK0-1 ;IRQ Disable (0=enable, 1=disable)
4004824h 2 SD_CARD_CLK_CTL Card Clock Control
4004826h 2 SD_DATA16_BLK_LEN Memory Card Transfer Data Length
4004828h 2 SD_CARD_OPTION Memory Card Option Setup (can be C0FFh)
400482Ah 2 Fixed always zero?
400482Ch 4 SD_ERROR_DETAIL_STATUS0-1 Error Detail Status
4004830h 2 SD_DATA16_FIFO Data Port (SD_FIFO?)
4004832h 2 Fixed always zero? ;(TC6371AF:BUF1 Data MSBs?)
4004834h 2 SD_CARD_IRQ_CTL ;(SD_TRANSACTION_CTL)
4004836h 2 SD_CARD_IRQ_STAT ;(SD_CARD_INTERRUPT_CONTROL)
4004838h 2 SD_CARD_IRQ_MASK ;(SDCTL_CLK_AND_WAIT_CTL)
400483Ah 2 Fixed always zero? ;(SDCTL_SDIO_HOST_INFORMATION)
400483Ch 2 Fixed always zero? ;(SDCTL_ERROR_CONTROL)
400483Eh 2 Fixed always zero? ;(TC6387XB: LED_CONTROL)
4004840h 2 Fixed always 003Fh?
4004842h 2 Fixed always 002Ah?
4004844h 6Eh Fixed always zerofilled?
40048B2h 2 Fixed always FFFFh?
40048B4h 6 Fixed always zerofilled?
40048BAh 2 Fixed always 0200h?
40048BCh 1Ch Fixed always zerofilled?
40048D8h 2 SD_DATA_CTL
40048DAh 6 Fixed always zerofilled?
40048E0h 2 SD_SOFT_RESET Software Reset (bit0=SRST=0=reset)
40048E2h 2 Fixed always 0009h? ;(RESERVED2/9, TC6371AF:CORE_REV)
40048E4h 2 Fixed always zero?
40048E6h 2 Fixed always zero? ;(RESERVED3, TC6371AF:BUF_ADR)
40048E8h 2 Fixed always zero? ;(TC6371AF:Resp_Header)
40048EAh 6 Fixed always zerofilled?
40048F0h 2 Fixed always zero? ;(RESERVED10)
40048F2h 2 ? Can be 0003h
40048F4h 2 ? Can be 0770h
40048F6h 2 SD_WRPROTECT_2 (R) ;Write protect for eMMC (RESERVED4)
40048F8h 4 SD_EXT_IRQ_STAT0-1 ;Insert/eject for eMMC (RESERVED5-6)
40048FCh 4 SD_EXT_IRQ_MASK0-1 ;(TC6371AF:Revision) (RESERVED7-8)
4004900h 2 SD_DATA32_IRQ
4004902h 2 Fixed always zero?
4004904h 2 SD_DATA32_BLK_LEN
4004906h 2 Fixed always zero?
4004908h 2 SD_DATA32_BLK_COUNT
400490Ah 2 Fixed always zero?
400490Ch 4 SD_DATA32_FIFO
4004910h F0h Fixed always zerofilled?
ARM7 DSi SD/MMC Registers for SDIO access (for Atheros Wifi)
4004A00h 512 SDIO_xxx (same as SD_xxx at 4004800h..40049FFh, see there)
4004A02h 2 SDIO_CARD_PORT_SELECT (slightly different than 4004802h)
ARM7 DSi General Purpose I/O (GPIO) (headphone connect, power button)
4004C00h 1 GPIO Data In (R) (even in DS mode)
4004C00h 1 GPIO Data Out (W)
4004C01h 1 GPIO Data Direction (R/W)
4004C02h 1 GPIO Interrupt Edge Select (R/W)
4004C03h 1 GPIO Interrupt Enable (R/W)
4004C04h 2 GPIO_WIFI (R/W)
ARM7 DSi CPU/Console ID (used as eMMC key)
4004D00h 8 CPU/Console ID Code (64bit) (R)
4004D08h 2 CPU/Console ID Flag (1bit) (R)
ARM7 DSi Junk?
8030200h 2 GBA area, accessed alongsides with SDIO port [4004A30h] (bug?)
4004010h - DSi9 - SCFG_MC - NDS Slot Memory Card Interface Status (R)
4004010h - DSi7 - SCFG_MC - NDS Slot Memory Card Interface Control (R/W)
0 1st NDS Slot Game Cartridge (0=Inserted, 1=Ejected) (R)
1 1st NDS Slot Unknown/Unused (0)
2-3 1st NDS Slot Power State (0=Off, 1=On+Reset, 2=On, 3=RequestOff) (R/W)
4 2nd NDS Slot Game Cartridge (always 1=Ejected) ;\DSi (R)
5 2nd NDS Slot Unknown/Unused (0) ; prototype
6-7 2nd NDS Slot Power State (always 0=Off) ;/relict (R/W)
8-14 Unknown/Undocumented (0)
15 Swap NDS Slots (0=Normal, 1=Swap) (R/W)
16-31 ARM7: See Port 4004012h, ARM9: Unspecified (0)
Note: Additionally, the NDS slot Reset pin can be toggled (via ROMCTRL.Bit29;
that bit is writeable on ARM7 side on DSi; which wasn't supported on NDS).
Power state values:
0=Power is Off
1=Power On and force Reset (shall be MANUALLY changed to state=2)
2=Power On
3=Request Power Off (will be AUTOMATICALLY changed to state=0)
cart_power_on: (official/insane 1+10+27+120ms, but also works with 1+1+0+1ms)
wait until state<>3 ;wait if pwr off busy
exit if state<>0 AND no_reset_wanted ;exit if already on & no reset wanted
wait 1ms, then set state=1 ;pwr on & force reset
wait 10ms, then set state=2 ;pwr on normal state ;better: 1ms
wait 27ms, then set ROMCTRL=20000000h ;release reset pin ;better: 0ms
wait 120ms (or 270ms on 3DS) ;more insane delay? ;better: 1ms/20ms
;note: the last delay (after releasing reset) can be 1ms for most carts,
;except DSi NAND carts do require 20ms (eg. Face Training)
;XXX other day: needs MORE than 20ms (30ms works), temperature related??
cart_power_off: (official 150ms, when using default [4004014h]=264Ch)
wait until state<>3 ;wait if pwr off busy
exit if state<>2 ;exit if already off
set state=3 ;request pwr off
exit unless you want to know when below pointless delay has ellapsed
wait until state=0 ;default=150ms ;wait until pwr off ;better: skip
Power Off is also done automatically by hardware when ejecting the cartridge.
The Power On sequence does reset ROMCTRL.bit29=0 (reset signal).
Bit15 swaps ports 40001A0h-40001BFh and 4100010h with 40021A0h-40021BFh? and
4102010h?, the primary purpose is mapping the 2nd Slot to the 4xx0xxxh
registers (for running carts in 2nd slot in NDS mode; which of course doesn't
work because the 2nd slot connector isn't installed), theoretically it would
also allow to access the 1st slot via 4xx2xxxh registers (however, that doesn't
seem to be fully implemented, cart reading does merely reply FFh's (cart
inserted) or 00h's (no cart)). 4102010h can be read by manually polling DRQ in
40021A4h.bit23, and probably by NDMA (but not by old DMA which has no known DRQ
mode for 2nd slot).
TeakLite II Processor
--> DSi Teak CPU Registers
--> DSi Teak CPU Control/Status Registers
--> DSi Teak CPU Address Config/Step/Modulo
--> DSi TeakLite II Instruction Set Encoding
--> DSi TeakLite II Operand Encoding
Teak Memory
Memory is addressed in 16bit WORD units (not in bytes) with separate
Instruction and Data busses. Before starting the Teak, store the Teak program
code in New Shared WRAM, and then map that memory to Teak side via MBK
registers:
--> DSi New Shared WRAM (for ARM7, ARM9, DSP)
At Teak side, 16bit is the smallest addressable unit (so there's no
"byte-order" on Teak side - however, 16bit values should be stored in little
endian format on ARM side).
Confusingly, the "movpdw" opcode is doing a 32bit read with two 16bit words
ordered in big-endian (and, on ARM side, byte-fractions ordered in
little-endian). There are a few more opcodes that can read/write 32bits, with
optional address increment/decrement for the 2nd word, so endianness is
selectable in that cases; it's also common to use the SAME address for both
words (probably intended for scaling a 16bit memory value to 32bits).
Teak Speed
Cycles per opcode are defined in the TeakLite document (not covering TeakLite
II opcodes though). Most instructions (even Multiply opcodes) can complete in a
single clock cycle. The main bottleneck appear to be memory access cycles: Code
and Data memory can be accessed in parallel, so the overall rule would be:
NumCycles = max(NumberOfOpcodeWords, NumberOfDataReadsWrites)
Some exceptions with extra cycles are opcodes that are changing PC, or that do
read/write program memory (movd and movp). Opcodes exp, max, maxd, min are
having restrictions saying that the result may not be used by the "following
instruction".
The overall clock speed in the DSi is unknown; some years ago somebody seems to
have claimed it to be around 130MHz, but it's unclear where that info came
from.
Teak actual CPU clock(s) are...
134.055928MHz (aka 134MHz) <-- for Timer 0, SIO, DMA (no "waitstates")
107.244742MHz (aka 134MHz/1.25) <-- for Timer 1, CPU (with "waitstates")
The ARM9 can access WRAM at 33MHz, whilst Teak seems to be capable of fetching
16bit opcodes and 16bit data at 107MHz from the same WRAM (apparently without
even using a cache).
I/O ports are mapped in "data memory" at 8000h-87FFh (2Kwords). All ports are
16bit wide, located at even word addresses (words at odd addresses seem to be
always 0000h, except, there ARE some odd ports used at 806xh).
8000h Mirrors
8000h..8002h 3300 3300 3300 R Mirror of Port 80D6h
8004h JAM
8004h 0000 0000 87FF R/W JAM Unknown
8006h ? ? ? ?? JAM Unknown/Crash, DANGER (crashes on read)
8008h..800Eh 3300 3300 3300 R Mirror of Port 80D6h
8010h GLUE
8010h 0000 0000 0003 R/W GLUE CFG0
8012h 0000 0000 0003 R/W GLUE Unknown 2bit
8014h 0000 0000 FFFF R/W GLUE Unknown 16bit
8016h 0000 0000 0000 R GLUE Unknown (DSi=0000h, New3DS=00BAh)
8018h 0000 0000 BDEF R/W GLUE Whatever Parity/Shuffle
801Ah C902 C902 C902 R GLUE Chip config ID (for xpert_offsets_tbl)
801Ch..801Eh 0003 0003 0003 R Mirror of port 8010h
8020h Timers
8020h 0000 0000 7xDF R/W Timer 0 Control (bit11=DANGER) ;\
8022h 0000 0000 0000 W Timer 0 Trigger Event/Watchdog ;
8024h 0000 0000 FFFF R/W Timer 0 Reload value, bit0-15 ; Timer 0
8026h 0000 0000 FFFF R/W Timer 0 Reload value, bit16-31 ;
8028h 0000 0000 0000 R Timer 0 Counter value, bit0-15 ;
802Ah 0000 0000 0000 R Timer 0 Counter value, bit16-31 ;
802Ch 0000 0000 FFFF R/W Timer 0 PWM Reload value, bit0-15 ;
802Eh 0000 0000 FFFF R/W Timer 0 PWM Reload value, bit16-31 ;/
8030h 0200 0200 7xDF R/W Timer 1 Control (bit11=DANGER) ;\
8032h 0000 0000 0000 W Timer 1 Trigger Event/Watchdog ;
8034h 0000 0000 FFFF R/W Timer 1 Reload value, bit0-15 ; Timer 1
8036h 0000 0000 FFFF R/W Timer 1 Reload value, bit16-31 ;
8038h 0000 0000 0000 R Timer 1 Counter value, bit0-15 ;
803Ah 0000 0000 0000 R Timer 1 Counter value, bit16-31 ;
803Ch 0000 0000 FFFF R/W Timer 1 PWM Reload value, bit0-15 ;
803Eh 0000 0000 FFFF R/W Timer 1 PWM Reload value, bit16-31 ;/
8040h..804Eh 3300 3300 3300 R Mirror of Port 80D6h
8050h Serial Port (SIO)
8050h 7000 0000 F03F R/W SIO Control
8052h 0000 0000 7F7F R/W SIO Clock Divider
8054h 0000 0000 0000 R+W SIO Data (R) and (W)
8056h 0000 0000 0001 R/W SIO Enable
8058h 0000 0000 0000 R SIO Status
805Ah..805Eh F03F F03F F03F R Mirror of port 8050h
8060h Debug (OCEM, On-chip Emulation Module)
8060h 0105 0105 0105 R OCEM Program Flow Trace Buffer, bit0-15
8061h 0000 0000 0000 R OCEM Program Flow Trace Buffer, bit16-31
8062h FFFF 0000 FFFF R/W OCEM Program Break Address 1, bit0-15
8063h 0F03 0000 0F03 R/W OCEM Program Break Address 1, bit16-31
8064h FFFF 0000 FFFF R/W OCEM Program Break Address 2, bit0-15
8065h 0F03 0000 0F03 R/W OCEM Program Break Address 2, bit16-31
8066h FFFF 0000 FFFF R/W OCEM Program Break Address 3, bit0-15
8067h 0F03 0000 0F03 R/W OCEM Program Break Address 3, bit16-31
8068h 00FF 0000 00FF R/W OCEM Program Break Counter 1
8069h 00FF 0000 00FF R/W OCEM Program Break Counter 2
806Ah 00FF 0000 00FF R/W OCEM Program Break Counter 3
806Bh FFFF 0000 FFFF R/W OCEM Data Break Mask
806Ch FFFF 0000 FFFF R/W OCEM Data Break Address
806Dh 0000 0000 R/W OCEM Breakpoint Enable Flags (DANGER)
806Eh 3001 0000 FFFF R/W OCEM Mode/Indication?
806Fh 0000 0000 BFFF R/W OCEM Breakpoint Status Flags
8070h 0000 0000 0001 R/W OCEM Program Flow Trace Update Disable
8072h 0000 0000 FFFF R/W Unknown 16bit?
8074h C000 C000 C000 R OCEM Boot/Debug Mode
8076h..807Eh 0105 0105 0105 R Mirror of port 8060h
8080h PLL and Power (PMU, Power Management Unit)
8080h C00E 0000 FFFF R/W PMU PLL Multiplier
8082h 0001 0000 0001 R/W PMU PLL Power-on config
8084h 8000 R/W PMU PLL Divider/Bypass (DANGER)
8086h 0000 R/W PMU Wake/Shutdown Module(s)
8088h 0000 0000 07BF R/W PMU Recover Module(s) on interrupt 0
808Ah 0000 0000 07BF R/W PMU Recover Module(s) on interrupt 1
808Ch 0000 0000 07BF R/W PMU Recover Module(s) on interrupt 2
808Eh 0000 0000 07BF R/W PMU Recover Module(s) on vectored interrupt
8090h 0000 0000 06BF R/W PMU Recover Module(s) on Timer 0 (no bit8)
8092h 0000 0000 05BF R/W PMU Recover Module(s) on Timer 1 (no bit9)
8094h 0000 0000 07BF R/W PMU Recover Module(s) on NMI
8096h 0000 0000 0002 R/W PMU Recover DMA on external signal (bit1)
8098h 0000 0000 0302 R/W PMU Breakpoint mask module(s) (bit1,8,9 only)
809Ah 0000 0000 0003 R/W PMU Wake/Shutdown BTDMP(s)
809Ch 0000 0000 0003 R/W PMU Recover BTDMP(s) on interrupt 0
809Eh 0000 0000 0003 R/W PMU Recover BTDMP(s) on interrupt 1
80A0h 0000 0000 0003 R/W PMU Recover BTDMP(s) on interrupt 2
80A2h 0000 0000 0003 R/W PMU Recover BTDMP(s) on vectored interrupt
80A4h 0000 0000 0003 R/W PMU Recover BTDMP(s) on Timer 0
80A6h 0000 0000 0003 R/W PMU Recover BTDMP(s) on Timer 1
80A8h 0000 0000 0003 R/W PMU Recover BTDMP(s) on NMI (undoc?)
80AAh 0000 0000 FFFF R/W Unknown 16bit
80ACh 0000 0000 FFFF R/W Unknown 16bit
80AEh 0000 0000 FFFF R/W Unknown 16bit
80B0h..80BEh FFFF FFFF FFFF R Mirror of port 8080h
80C0h APBP (aka HPI Host Port Interface)
80C0h xxxx xxxx xxxx R/W APBP DSP-to-ARM Reply 0
80C2h 4300 4300 4300 R APBP ARM-to-DSP Command 0
80C4h 0000 0000 FFFF R/W APBP DSP-to-ARM Reply 1
80C6h 3123 3123 3123 R APBP ARM-to-DSP Command 1
80C8h 0000 0000 FFFF R/W APBP DSP-to-ARM Reply 2
80CAh 3223 3223 3223 R APBP ARM-to-DSP Command 2
80CCh 0000 0000 FFFF R/W APBP DSP-to-ARM Semaphore Set Flags
80CEh 0000 R/W APBP ARM-to-DSP Semaphore Interrupt Mask
80D0h 0000 W? APBP ARM-to-DSP Semaphore Ack Flags
80D2h AFFE AFFE AFFE R APBP ARM-to-DSP Semaphore Get Flags
80D4h 0000 R/W APBP Control (DANGER: can crash cpu)
80D6h 03C0 03C0 03C0 R APBP DSP-side Status
80D8h 3B00 3B00 3B00 R APBP ARM-side Status (mirror of 400430Ch)
80DAh..80DEh 0000 0000 0000 R Fixed 0000h
80E0h Bus Config for DMA to external ARM-bus (AHBM)
80E0h 0000 0000 0000 R AHBM Status
80E2h+N*6 0000 0000 0FBF R/W AHBM Channel 0..2 Configure Burst/Data
80E4h+N*6 0000 0000 03FF R/W AHBM Channel 0..2 Configure Whatever
80E6h+N*6 0000 0000 00FF R/W AHBM Channel 0..2 Configure DMA
80F4h 0000 0000 FC00 R/W Unknown 6bit? bit10-15 are used
80F6h 0000 0000 0000 R? AHBM Internal FIFO (R) and maybe also (W?)
80F8h 0000 0000 0000 R? Unknown always zero?
80FAh 0000 0000 FFFF R/W Read/write-able(!) mirror of MMIO[80FCh]
80FCh FFFF 0000 FFFF R/W Unknown 16bit?
80FEh 0000 0000 FFFF R/W Unknown 16bit?
8100h MIU (memory limits for X-,Y-,Z-Space, and Memory Mapped I/O base)
8100h FFFF 0000 FFFF R/W MIU Waitstate Settings, bit0-15
8102h 0FFF 0000 0FFF R/W MIU Waitstate Settings, bit16-31
8104h 0000 0000 FFFF R/W MIU Waitstate Area Z0
8106h 0000 0000 FFFF R/W MIU Waitstate Area Z1
8108h 0000 0000 FFFF R/W MIU Waitstate Area Z2
810Ah 0000 0000 FFFF R/W MIU Waitstate Area Z3
810Ch 0014 0014 0014 R Mirror of port 811Ah
810Eh 0000 0000 FFFF R/W MIU X Page (16bit) (or unused)
8110h 0000 0000 00FF R/W MIU Y Page (8bit) (or unused)
8112h 0000 R/W MIU Z Page (16bit) (or absolute page)(DANGER)
8114h 1E20 R/W MIU X/Y Page Size for Page 0 (or all pages)
8116h 1E20 0100 403F R/W MIU X/Y Page Size for Page 1 (or unused)
8118h 1E20 0100 403F R/W MIU X/Y Page Size for Off-chip (or unused)
811Ah 0014 00x4 R/W MIU Config for Misc stuff (DANGER)
811Ch 0004 0000 007F R/W MIU Config for Program Page and Download Mem
811Eh 8000 R/W MIU Base Address for MMIO Registers (DANGER)
8120h 0000 0000 000F R/W MIU Observability Mode
8122h 0000 0000 007F R/W MIU Pin Config?
8124h..813Eh 0014 0014 0014 R Mirror of port 811Ah
8140h Patch (CRU, Code Replacement Unit)
8140h+N*4 0000 0000 FFFF R/W CRU Entry 0..14 Offset, bit0-15
8142h+N*4 0000 0000 803F R/W CRU Entry 0..14 Offset, bit16-31
817Ch 0000 0000 FFFF R/W CRU Entry 15 Offset, bit0-15 ;\with control
817Eh 0000 0000 C03F R/W CRU Entry 15 Offset, bit16-31 ;/status bits
8180h DMA (eight channels, port 81C0h..81Exh are bank-switched via 81BEh)
8180h 0000 0000 0000 R DMA Internal: Channel Size0 Busy or so?
8182h 0000 0000 0000 R DMA Internal: Channel Size1 Busy or so?
8184h 0001 0000 00FF R/W DMA Channel Start Flags (1=Start/Busy)
8186h 0000 0000 00FF R/W DMA Channel Pause Flags (1=Pause)
8188h 0000 0000 0000 R DMA Channel End Flags for Size0
818Ah 0000 0000 0000 R DMA Channel End Flags for Size1
818Ch 0000 0000 0000 R DMA Channel End Flags for Size2 (all done)
818Eh 3210 0000 7777 R/W DMA Whatever Slot Config, bit0-15
8190h 7654 0000 7777 R/W DMA Whatever Slot Config, bit16-31
8192h 0000 0000 7C03 R/W Unknown, R/W mask 7C03h
8194h 0000 0000 0000 R DMA Internal: contains SRC_ADDR_L after DMA
8196h 0000 0000 0000 R DMA Internal: contains DST_ADDR_L after DMA
8198h..81B4h 0000 0000 0000 R Fixed 0000h
81B6h 0000 0000 FFFF R/W Unknown, 16bit
81B8h 0000 0000 FFFF R/W Unknown, 16bit
81BAh 0000 0000 FFFF R/W Unknown, 16bit
81BCh 0000 0000 FFFF R/W Unknown, 16bit
81BEh 0000 0000 0007 R/W DMA Select Channel (bank for 81C0h-81Exh)
81C0h:0..7 0000 0000 FFFF R/W DMA Channel: Source Address, bit0-15
81C2h:0..7 0000 0000 FFFF R/W DMA Channel: Source Address, bit16-31
81C4h:0..7 0000 0000 FFFF R/W DMA Channel: Destination Address, bit0-15
81C6h:0..7 0000 0000 FFFF R/W DMA Channel: Destination Address, bit16-31
81C8h:0..7 FFFF 0001 FFFF R/W DMA Channel: Size0 (usually total len)
81CAh:0..7 0001 0001 FFFF R/W DMA Channel: Size1 (usually 1)
81CCh:0..7 0001 0001 FFFF R/W DMA Channel: Size2 (usually 1)
81CEh:0..7 0001 0000 FFFF R/W DMA Channel: Source Step0 ;-2,4,2,1
81D0h:0..7 0001 0000 FFFF R/W DMA Channel: Source Step1 ;-4,2,2,1
81D2h:0..7 0001 0000 FFFF R/W DMA Channel: Source Step2 ;-2,4,0,1
81D4h:0..7 0001 0000 FFFF R/W DMA Channel: Destination Step0 ;-4,2,0,1
81D6h:0..7 0001 0000 FFFF R/W DMA Channel: Destination Step1 ;-0,0,0,1
81D8h:0..7 0001 0000 FFFF R/W DMA Channel: Destination Step2 ;-0,0,0,1
81DAh:0..7 F200 0000 F7FF R/W DMA Channel: Memory Area Config
81DCh:0..7 0000 0000 1FF7 R/W DMA Channel: Unknown, usually set to 0300h?
81DEh:0..7 0000 0000 00FF R/W DMA Channel: Start/Stop/Control
81E0h:0..7 0000 0000 0000 R DMA Internal: contains SRC_ADDR_L after DMA
81E2h:0..7 0000 0000 0000 R DMA Internal: contains DST_ADDR_L after DMA
81E4h:0..7 0000 0000 0000 R DMA Internal: contains SRC_ADDR_H after DMA
81E6h:0..7 0000 0000 0000 R DMA Internal: contains DST_ADDR_H after DMA
81E8h..81FEh 0000 0000 0000 R Fixed 0000h
8200h ICU (interrupts)
8200h 4020 4020 4020 R ICU Interrupt Pending Flags (1=Pending)
8202h 0000 0000 0000 W ICU Interrupt Acknowledge (1=Clear)
8204h 0000 0000 FFFF R/W ICU Interrupt Manual Trigger (1=Set)
8206h 0000 0000 FFFF R/W ICU Enable Interrupt as int0 (1=Enable)
8208h 0000 0000 FFFF R/W ICU Enable Interrupt as int1 (1=Enable)
820Ah 0000 0000 FFFF R/W ICU Enable Interrupt as int2 (1=Enable)
820Ch 0000 0000 FFFF R/W ICU Enable Interrupt as vint (1=Enable)
820Eh 2000 0000 FFFF R/W ICU Interrupt Trigger mode (0=Level, 1=Edge)
8210h 2000 0000 FFFF R/W ICU Interrupt Polarity (0=Normal, 1=Invert)
8212h+N*4 0003 0000 8003 R/W ICU Vectored Interrupt 0..15 Addr, bit16-31
8214h+N*4 FC00 0000 FFFF R/W ICU Vectored Interrupt 0..15 Addr, bit0-15
8252h 0000 0000 FFFF R/W ICU Interrupt Master Disable (1=Off/undoc)
8254h 0000 0000 5555 R/W Unknown, R/W mask 5555h
8256h 0000 0000 5555 R/W Unknown, R/W mask 5555h
8258h..827Eh 0000 0000 0000 R Mirror of Port 8200h
8280h BTDMP Audio (two channels N=0..1, each with speaker out and mic in)
8280h+N*80h 0005 0000 FFFF R/W BTDMP Receive Control ;\
8282h+N*80h 0000 0000 7FE7 R/W BTDMP Receive Period ;
8284h+N*80h 0000 0000 0FE7 R/W BTDMP Receive Usually 0004h ;
8286h+N*80h 0000 0000 0003 R/W BTDMP Receive Usually 0021h ; RX
8288h+N*80h 1FFF 0000 1FFF R/W BTDMP Receive Usually 0000h ; (microphone)
828Ah+N*80h 0000 0000 0FFF R/W BTDMP Receive Usually 0000h ;
828Ch+N*80h 0000 0000 3FFF R/W BTDMP Receive Usually 0000h ;
828Eh+N*80h 0000 0000 FFFF R/W BTDMP Receive Usually unused ;
8290h+N*80h 0000 0000 FFFF R/W BTDMP Receive Usually unused ;
8292h+... 0000 0000 0000 R Fixed 0000h ;
829Eh+N*80h 0000 0000 8000 R/W BTDMP Receive Enable ;/
82A0h+N*80h 0005 0000 FFFF R/W BTDMP Transmit Control ;\
82A2h+N*80h 0000 0000 7FE7 R/W BTDMP Transmit Period ;
82A4h+N*80h 0000 0000 0FE7 R/W BTDMP Transmit Usually 0004h ;
82A6h+N*80h 0000 0000 0003 R/W BTDMP Transmit Usually 0021h ; TX
82A8h+N*80h 1FFF 0000 1FFF R/W BTDMP Transmit Usually 0000h ; (audio out)
82AAh+N*80h 0000 0000 0FFF R/W BTDMP Transmit Usually 0000h ;
82ACh+N*80h 0000 0000 3FFF R/W BTDMP Transmit Usually 0000h ;
82AEh+N*80h 0000 0000 FFFF R/W BTDMP Transmit Usually unused ;
82B0h+N*80h 0000 0000 FFFF R/W BTDMP Transmit Usually unused ;
82B2h+... 0000 0000 0000 R Fixed 0000h ;
82BEh+N*80h 0000 0000 8000 R/W BTDMP Transmit Enable ;/
82C0h+N*80h 001x 001F 001F R BTDMP Receive FIFO Status ;\
82C2h+N*80h 0057 005x 0057 R BTDMP Transmit FIFO Status ;
82C4h+N*80h E0A1 FFFF E0A1 R BTDMP Receive FIFO Data ; RX/TX
82C6h+N*80h 0000 0000 0000 W BTDMP Transmit FIFO Data ;
82C8h+N*80h 0000 0000 0003 R/W BTDMP Receive FIFO Control ;
82CAh+N*80h 0000 0000 0003 R/W BTDMP Transmit FIFO Control ;/
82CCh+... 0000 0000 0000 R Fixed 0000h
8380h..867Eh 03C0 03C0 03C0 R Mirror of Port 80D6h
8680h ? (listed in "xpert_offsets_tbl", but there are just mirrors)
8680h..87FEh 03C0 03C0 03C0 R Mirror of Port 80D6h
8800h ? (listed in "perxteak.per", but seems to be always 0) (dbg aka H2C)
(this is called "Host-to-Core JAM protocol" and consists of 11bit values)
(not sure if that are MMIO registers, or some 11bit data transfer protocol)
8800h..8807h 0000 0000 0000 R? Fixed 0 (reportedly H2C aka dbg stuff?)
Unknown what below is... maybe MMIO[8800h..8807h] or maybe 11bit values for JAM
registers at MMIO[8004h..8006h]... and/or Input-only direction GPIO?
DSi Teak MMIO[8080h] - PLL and Power (PMU, Power Management Unit)
-----------------------------------------------------------------
The APBP (aka HPI Host Port Interface) registers are used to communicate
between ARM and DSP.
AHBM does allow the Teak CPU to access the ARM-side memory (in combination with
DMA interface at MMIO[8180h]).
MMIO[8114h] - MIU X/Y Page Size for Page 0 (or all pages) (R/W)
MMIO[8116h] - MIU X/Y Page Size for Page 1 (or unused) (R/W)
MMIO[8118h] - MIU X/Y Page Size for Off-chip Pages (or unused) (R/W)
0-5 X memory size (0..3Fh)
6-7 Unused (0)
8-14 Y memory size (1..40h)
15 Unused (0)
The register meaning depends on the PGM paging mode:
When PGM=0?--> MMIO[8114h,8116h,8118h] used for Page 0, 1, and Off-chip pages
When PGM=1?--> MMIO[8114h] used for all pages
For Y memory size, the hardware does automatically replace the written value by
min=01h or max=40h when trying to to write 00h or 41h-7Fh.
MMIO[811Ch] - MIU Config for Program Page and Download Memory (R/W)
0 Select Z-space data memory (0=Regular Memory, 1=Download memory)
1 Download mem is/was selected (bit1 can be cleared during Trap only)
2-5 Alternative Program Page for movd/movp opcodes (PDLPAGE) (4bit)
6 Select program page for movd/movp (0=2bit/movpd, 1=4bit/PDLPAGE)
7-15 Unused (0)
Bit1 gets set when setting bit0=1 (bit1 is usually readonly, except, trap
handler may clear bit1 by writing to it). Unknown what Download means, maybe
off-chip data memory?
The CRU is intended to fix bugs in ROM-based programs (rather useless for
RAM-based DSi code).
STEP0, STEP1 and STEP2 specify the address stepping between elements for each
dimension. Below is an example showing how it works.
With the source address configuration:
SRC_ADDR = 0
SIZE0 = 3
SIZE1 = 5
SIZE2 = 2
SRC_STEP0 = 2
SRC_STEP1 = 1
SRC_STEP2 = 7
The data transfer copies data from the following addresses:
<--------------------------size1-------------------------->
<--size0--> <--size0--> <--size0--> <--size0--> <--size0-->
0, 2, 4, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22, 24 <-- size2 (1st)
31, 33, 35, 36, 38, 40, 41, 43, 45, 46, 48, 50, 51, 53, 55 <-- size2 (2nd)
The 32bit double word mode also automatically aligns down the addresses to
32bit boundaries.
Interrupt Behaviour
Pending flags are set somewhat as so:
new_state=incoming_hw_signal ;always 0 for interrupt 0..8
if polarity=1 then new_state=new_state xor 1
new_state=new_state OR manual_trigger ;done AFTER above polarity invert
new_state=new_state AND NOT master_disable
if new_state=1 and old_state=0 then pending=1
old_state=new_state
Acknowlege is required for clearing pending bits, this is required in both
Egde- and Level-triggered modes (the difference is that Level-triggered mode
will ignore the acknowledge if new_state is still on).
Manual Trigger won't appear in Pending until after two NOP opcodes (or similar
delay).
IRQ-to-interrupt translator
The main job of ICU is to translate 16 IRQ signals to 4 processor interrupt
signals (int0, int1, int2 and vint), specified by I0x, I1x, I2x and IVx
registers. When an IRQ is signaled, ICU will generate interrupt signal and the
processor starts to execute interrupt handling procedure if the core interrupt
is enabled. The procedure is supposed check IPx reigster to know the exact IRQ
index, and to set IAx registers to clear the IRQ signal.
Software interrupt
The processor can writes to ITx to generate a software interrupt manually. A
use case for this in many 3DS games is that IRQ 0 is used as the reschedule
procedure for multithreading. When a thread wants to yield, it triggers IRQ 0,
which switches thread context and resume another thread.
There are two BTDMP units. The weird name "Buffered Time Division Multiplexing
Port" does essentially mean "FIFO with sample rate timer".
BTDMP 0 is used for Receive (microphone) and Transmit (audio out).
BTDMP 1 isn't actually used for anything.
Some of the above unknown stuff might be... volume, bias, sample.size,
mono/stereo, dummy-value-when-fifo-empty, beep generator, filter/equalizer,
sample rate interpolation, whatever...?
32bit Multiply Result and 16bit Muliply Parameters: p0,p1, and x0,y0,x1,y1
x0 ;TL ;16bit ;-
y0 ;TL ;16bit ;-
x1 ;TL2 ;16bit ;-
y1 ;TL2 ;16bit ;-
p0 ;TL ;33bit! ;\Px ;TL2: 33bit p0e:p0 ? ;TL1: 32bit?
p1 ;TL2 ;33bit! ;/ ;TL2: 33bit p1e:p1 ? ;TL1: N/A
p0h ;TL ;16bit ; ;<-- aka ph ;<-- called "p0" (aka "p") in "RegisterP0"
The "load ps" and "load ps01" opcodes allow to specify a multiply shifter, this
is useful when dealing with signed/unsigned parameters:
Unsigned = Unsigned * Unsigned ;use shift 0
Unsigned = Unsigned * Signed ;use shift +1
Unsigned = Signed * Signed ;use shift +2
Signed = Unsigned * Unsigned ;use shift -1
Signed = Unsigned * Signed ;use shift 0
Signed = Signed * Signed ;use shift +1
TeakLite Misc
pc ;TL ;18bit! ;-program counter (TL2: 18bit, TL1: 16bit)
sp ;TL ;16bit ;-stack pointer (decreasing on push/call)
sv ;TL ;16bit ;-shift value (negative=right) (for shift-by-register)
mixp ;TL ;16bit ;-related to min/max/mind/maxd
lc ;TL ;16bit ;-Loop Counter (of block repeat)
repc ;TL ;16bit ;-Repeat Counter (for "rep" opcode)
dvm ;TL ;16bit ;-Data Value Match (OCEM data breakpoints) (and for trap)
Shadow Registers
Some registers (or in case of st0-st2: fractions thereof) exist as "shadows"...
related to "cntx", "swap", "banke" (and maybe "bankr"?) opcodes, and
"reti/retid" opcodes with "context" suffix, and interrupts with context
switching enabled.
st0 bit0,2-11 ;\control/status (cntx)
st1 bit10-11 (and "swap": bit0-7) ; (TL2: probably also SttMod)
st2 bit0-7 ;/
a0 <--> b0 manualswap only? ;\accumulators (swap)
a1 <--> b1 autoswapped? ;/
r0 <--> r0b ;\
r1 <--> r1b ;
r4 <--> r4b ; BankFlags (banke)
r7 <--> r7b ;TL2 ;
cfgi <--> cfgib ;
cfgj <--> cfgjb ;TL2 ;/
Ar,Arp <--> ? ;TL2 ;-? (bankr and/or cntx)
Registers b0/b1 can be used as normal opcode operands, the other shadow
registers are used only when doing bank/cntx stuff.
These registers allow to reconfigure opcodes. For example, opcodes with operand
MemR45 can normally use only R4/R5 operands; if desired that can be changed to
anything else like R3/R0. The selection if Offset/Step operands can be changed
in similar way.
Unknown which settings affect which opcodes exactly.
The DSi Sound code is using a default configuration for most of its code, but
it does also have some functions with alternate configurations.
ar0/ar1
0-2 R/W PM1/PM3 Post Modify Step (0..7 = +0,+1,-1,+s,+2,-2,+2,-2)
3-4 R/W CS1/CS3 Offset (0..3 = +0,+1,-1,-1)
5-7 R/W PM0/PM2 Post Modify Step (0..7 = +0,+1,-1,+s,+2,-2,+2,-2)
8-9 R/W CS0/CS2 Offset (0..3 = +0,+1,-1,-1)
10-12 R/W RN1/RN3 Register (0..7 = R0..R7)
13-15 R/W RN0/RN2 Register (0..7 = R0..R7)
arp0/arp1/arp2/arp3
0-2 R/W PIn Post Modify Step I (0..7 = +0,+1,-1,+s,+2,-2,+2,-2)
3-4 R/W CIn Offset I (0..3 = +0,+1,-1,-1)
5-7 R/W PJn Post Modify Step J (0..7 = +0,+1,-1,+s,+2,-2,+2,-2)
8-9 R/W CJn Offset J (0..3 = +0,+1,-1,-1)
10-11 R/W RIn Register I (0..3 = R0..R3)
12 - - Unused (always zero)
13-14 R/W RJn Register J (0..3 = R4..R7)
15 - - Unused (always zero)
The opcodes are 16bits wide (some followed by an additional 16bit parameter
word, namely those with "@16" operands). The encoding is very messy (fixed
opcode bits randomly mixed/interleaved with variable parameter bits, and with
new TL2 opcodes squeezed in formerly unused locations), making it pretty much
impossible to decode that unpleasant stuff by software/logic.
The only reasonable decoding way is using a huge table with 65536 entries
(which could be generated temporarily from the information in below table,
using the Base number plus all variable bit combinations, for example, "6100h
TL mov MemImm8@0, Ab@11" has variable bits in bit0-7 and bit11-12, so the
opcode would be mapped at 6100h-61FFh, 6900h-69FFh, 7100h-71FFh, 7900h-79FFh).
Syntax Notes
The official Teak syntax specifies all operands in "source,dest" order, that's
opposite of most other ASM languages which use "dest,source" order (except
68000 processors, which the Teak is apparently inspired on). One exception are
instructions tagged "NoReverse" in the opcode list: These ones do have the
operands ordered as how one would usually expect them.
Operands tagged as "Implied xx" are effectively used by the hardware, although
the official syntax doesn't specify them in source code. On the other hand,
operands tagged as "Bogus xx" are specified in official source code syntax,
although the hardware doesn't actually use that operands in that form.
The nocash (dis-)assembler syntax reverses the operand order (except those
flagged as NoReverse), removes Bogus operands, and inserts Implied operands.
Moreover, immediates and memory operands are specified differently...
Memory Operands
name native nocash
MemRn (Rn) [Rn]
MemSp (sp) [sp]
ProgMemRn (Rn) [code:movpd:Rn]
ProgMemAxl (Axl) [code:movpd:Axl]
ProgMemAx (Ax) [code:Ax]
ProgMemAx_.. (Ax),(Ax+) [code:Ax]:[code:Ax+]
MemImm8 0xNN [page:NNh]
MemImm16 [##0xNNNN] [NNNNh]
MemR7Imm7s (r7+#0xNN), (r7+#-NNN) [r7+/-NNh]
MemR7Imm16 (r7+##0xNNNN) [r7+NNNNh]
Immediates/Addresses
Address18 0xNNNNN NNNNNh ;for bkrep/br/call
Address16 0xNNNN NNNNh ;for bkrep
RelAddr7 0xNNNN NNNNh ;for jmp
ImmN: #0xNNNN NNNNh
ImmNs: #0xNN, #-NNN +/-NNh
Imm16: ##0xNNNN NNNNh
Imm4bitno: ... 1 shl N
ConstZero <implied> 0000h
Const1 <implied> 0001h
Const4 <implied> 0004h
Const8000h <implied> 8000h
Operand Encoding
Below shows the binary encoding for registers/conditions. For example, "Ab@10"
in the opcode list can be "b0,b1,a0,a1" encoded in bit10-11. Some instructions
re-use the same bitfield for multiple operands (eg. when performing two
operations on the SAME operand, or when expecting DIFFERENT operands: for
"Ax@12,Ax@not12" one of the registers must "a0", and the other must be "a1").
SwapTypes:
val native nocash ;meaning
0: (a0,b0) a0,b0 ;a0 <--> b0 ;flags(a0)
1: (a0,b1) a0,b1 ;a0 <--> b1 ;flags(a0)
2: (a1,b0) a1,b0 ;a1 <--> b0 ;flags(a1)
3: (a1,b1) a1,b1 ;a1 <--> b1 ;flags(a1)
4: (a0,b0),(a1,b1) a0:a1,b0:b1 ;a0 <--> b0 and a1 <--> b1 ;flags(a0)
5: (a0,b1),(a1,b0) a0:a1,b1:b0 ;a0 <--> b1 and a1 <--> b0 ;flags(a0)
6: (a0,b0,a1) a1,b0,a0 ;a0 --> b0 --> a1 ;flags(a1)
7: (a0,b1,a1) a1,b1,a0 ;a0 --> b1 --> a1 ;flags(a1)
8: (a1,b0,a0) a0,b0,a1 ;a1 --> b0 --> a0 ;flags(a0)
9: (a1,b1,a0) a0,b1,a1 ;a1 --> b1 --> a0 ;flags(a0)
A: (b0,a0,b1) b1,a0,b0 ;b0 --> a0 --> b1 ;flags(a0)!
B: (b0,a1,b1) b1,a1,b0 ;b0 --> a1 --> b1 ;flags(a1)!
C: (b1,a0,b0) b0,a0,b1 ;b1 --> a0 --> b0 ;flags(a0)!
D: (b1,a1,b0) b0,a1,b1 ;b1 --> a1 --> b0 ;flags(a1)!
E: reserved reserved ;- ;-
F: reserved reserved ;- ;-
The DSi has four New DMA channels for ARM7 and ARM9 each (eight New DMA
channels in total). The old NDS-style DMA channels do still exist, too [though
unknown which priority they have in relation to new channels].
Start/repeat modes
There are three different transfer modes.
1) Start immediately (without repeat):
the transfer ends after one Logical Block, without repeat. With single IRQ
(after last/only block).
2) Start by Hardware events, Repeat until NDMAxTCNT:
the transfer repeats Logical Blocks until reaching the Total Length. With
single IRQ (after last block).
3) Start by Hardware events, Repeat infinitely:
the transfer repeats Logical Blocks infinitely. With multiple IRQs (one IRQ
after EACH logical block).
Read-only Effect
There is something that can make port 4004104h..4004173h read-only. For
example, when FFh-filling all DSi registers, and then 00h-filling them, then
most DMA bits stay set (00h-filling them another time does clear them).
Maybe, during enabled transfers, ONLY the enable/busy bit is writeable?
DSi Microphone and SoundExt
---------------------------
DMA
The AES data would be usually transferred via two NDMA channels, one for
WRFIFO, one for RDFIFO. The NDMAs should be started BEFORE setting AES_CNT.31
(else the DMA will miss the first WRFIFO data request; and DMA won't start).
The DMAs 'Logical Block' sizes should match up with the block sizes selected in
AES_CNT (a bigger logical block size would cause FIFO overruns/underruns, a
smaller logical block size could work theoretically, but it practice it causes
the DMA to hang after the first data request; apparently data requests are
somewhat generated upon "empty-not-empty" transitions, rather than upon "enough
data/space" status).
AES-CTR (Counter)
aes_crypt_ctr(src,dst,len,nc_off,iv)
aes_setkey(ENCRYPT,key,key_size] ;-init key
[ctr+0..15] = [iv+0..15] ;-init ctr
n=[nc_off]
while len>0 ;code is 100% same for ENCRYPT and DECRYPT ;\
if n=0 ; encrypt
aes_crypt_block(ENCRYPT,ctr,tmp) ; or decrypt
littleendian(ctr)=littleendian(ctr)+1 ;increment counter ; message
[dst] = [src] xor [tmp+n] ;
src=src+1, dst=dst+1, len=len-1, n=(n+1) and 0Fh ;/
[nc_off]=n
AES-Key-Wrap/Unwrap
This is used for EAPOL Key Data in WPA2 Wifi packets, however, neither DSi-ARM7
nor DSi-Wifi do support that by hardware, so the unwrap (decrypt) must be
implemented by software. For details see:
--> DS Wifi WPA/WPA2 Encryption
Below are some other AES variants (just for curiosity - those variants aren't
used in DSi):
aes_crypt_block(mode,src,dst):
Y0 = RK[0] xor [src+00h]
Y1 = RK[1] xor [src+04h]
Y2 = RK[2] xor [src+08h]
Y3 = RK[3] xor [src+0Ch]
;below code depending on mode: <---ENCRYPT---> -or- <---DECRYPT--->
for i=1 to nr-1
X0 = RK[i*4+0] xor scatter32(FT,Y1,Y2,Y3,Y0) -or- (RT,Y3,Y2,Y1,Y0)
X1 = RK[i*4+1] xor scatter32(FT,Y2,Y3,Y0,Y1) -or- (RT,Y0,Y3,Y2,Y1)
X2 = RK[i*4+2] xor scatter32(FT,Y3,Y0,Y1,Y2) -or- (RT,Y1,Y0,Y3,Y2)
X3 = RK[i*4+3] xor scatter32(FT,Y0,Y1,Y2,Y3) -or- (RT,Y2,Y1,Y0,Y3)
Y0=X0, Y1=X1, Y2=X2, Y3=X3
[dst+00h] = RK[nr*4+0] xor scatter8(FSb,Y1,Y2,Y3,Y0) -or- (RSb,Y3,Y2,Y1,Y0)
[dst+04h] = RK[nr*4+1] xor scatter8(FSb,Y2,Y3,Y0,Y1) -or- (RSb,Y0,Y3,Y2,Y1)
[dst+08h] = RK[nr*4+2] xor scatter8(FSb,Y3,Y0,Y1,Y2) -or- (RSb,Y1,Y0,Y3,Y2)
[dst+0Ch] = RK[nr*4+3] xor scatter8(FSb,Y0,Y1,Y2,Y3) -or- (RSb,Y2,Y1,Y0,Y3)
scatter32(TAB,a,b,c,d): scatter8(TAB,a,b,c,d):
w= (TAB[a.bit0..7] ror 24) w.bit0..7 = TAB[a.bit0..7]
w=w xor (TAB[b.bit8..15] ror 16) w.bit8..15 = TAB[b.bit8..15]
w=w xor (TAB[c.bit16..23] ror 8) w.bit16..23 = TAB[c.bit16..23]
w=w xor (TAB[d.bit24..31]) w.bit24..31 = TAB[d.bit24..31]
return w return w
aes_generate_tables:
for i=0 to 0FFh ;compute pow and log tables...
if i=0 then x=01h, else x=x xor x*2, if x>0FFh then x=x xor 11Bh
pow[i]=x, log[x]=i
for i=0 to 0FFh ;generate the forward and reverse S-boxes...
x=pow[0FFh-log[i]]
x=x xor (x rol 1) xor (x rol 2) xor (x rol 3) xor (x rol 4) xor 63h
if i=0 then x=63h
FSb[i]=x, RSb[x]=i
for i=0 to 0FFh ;generate the forward and reverse tables...
x=FSb[i]*2, if x>0FFh then x=x xor 11Bh
FT[i]=(FSb[i]*00010101h) xor (x*01000001h)
w=00000000h, x=RSb[i]
if x<>00h then ;ie. not at i=63h
w=w+pow[(log[x]+log[0Eh]) mod 00FFh]*1000000h
w=w+pow[(log[x]+log[09h]) mod 00FFh]*10000h
w=w+pow[(log[x]+log[0Dh]) mod 00FFh]*100h
w=w+pow[(log[x]+log[0Bh]) mod 00FFh]*1h
RT[i]=w
aes_generate_tables_results:
pow[00h..FFh] = 01,03,05,0F,11,..,C7,52,F6,01 ;pow ;\needed temporarily
log[00h..FFh] = 00,FF,19,01,32,..,C0,F7,70,07 ;log ;/for table creation
FSb[00h..FFh] = 63,7C,77,7B,F2,..,B0,54,BB,16 ;Forward S-box
RSb[00h..FFh] = 52,09,6A,D5,30,..,55,21,0C,7D ;Reverse S-box
FT[00h..FFh] = C66363A5,F87C7C84,..,2C16163A ;Forward Table
RT[00h..FFh] = 51F4A750,7E416553,..,D0B85742 ;Reverse Table
aes_setkey_results:
key = "AES-Test-Key-Str-1234567-Abcdefg" ;use only 1st bytes for 128/192bit
128bit ENCRYPT --> RK[0..9..30..43] = 2D534541..2783080F..93AF7DF0..827EE10D
192bit ENCRYPT --> RK[0..9..30..51] = 79654B2D..9708FA95..2529372B..C66C19FA
256bit ENCRYPT --> RK[0..9..30..59] = 3332312D..DF5C92A5..74174E2E..3C8ADAE6
128bit DECRYPT --> RK[0..9..30..43] = AEABCD4D..ECD33F19..8C87B246..7274532D
192bit DECRYPT --> RK[0..9..30..51] = AFA9796F..72A3EFE5..455646C7..37363534
256bit DECRYPT --> RK[0..9..30..59] = 0ED52830..4601F929..415A7D65..67666564
aes_crypt_results:
[key+0..15] = "AES-Test-Key-Str-1234567-Abcdefg"
[iv+0..15] = "Nonce/InitVector"
[xtra+0..20] = "Extra-Associated-Data" ;\for CCM
iv_len=12, mac_len=16, xtra_len=xx ;/
Unencrypted: [dta+0..113Fh] = "Unencrypted-Data", 190h x "TestPadding"
AES-ECB: [dta+0..113Fh] = 20,24,73,88,..,44,A8,D6,A8 ;\
AES-CBC: [dta+0..113Fh] = A4,6F,7A,F2,..,58,C9,02,B4 ;
AES-CFB128: [dta+0..113Fh] = 20,C6,DB,35,..,9A,83,7F,DB ; keysize=128
AES-CFB8: [dta+0..113Fh] = 55,C7,75,1C,..,24,6E,A6,D1 ;
AES-CTR: [dta+0..113Fh] = 20,C6,DB,35,..,AB,09,0C,75 ;
AES-CCM: [dta+0..113Fh] = C8,37,D7,F1,..,7B,EF,FC,12 ;
AES-CCM (ori): [mac+0..0Fh] = xx,xx,xx,xx,..,xx,xx,xx,xx ;
AES-CCM (DSi): [mac+0..0Fh] = xx,xx,xx,xx,..,xx,xx,xx,xx ;/
AES-ECB: [dta+0..113Fh] = CC,B6,4D,17,..,D3,56,3E,64 ;-keysize=192
AES-ECB: [dta+0..113Fh] = A9,A9,9B,3E,..,8A,C6,13,A1 ;-keysize=256
AES-CTR (Counter)
aes_crypt_ctr(src,dst,len,nc_off,iv)
aes_setkey(ENCRYPT,key,key_size] ;-init key
[ctr+0..15] = [iv+0..15] ;-init ctr
n=[nc_off]
while len>0 ;code is 100% same for ENCRYPT and DECRYPT ;\
if n=0 ; encrypt
aes_crypt_block(ENCRYPT,ctr,tmp) ; or decrypt
bigendian(ctr)=bigendian(ctr)+1 ;increment counter ; message
[dst] = [src] xor [tmp+n] ;
src=src+1, dst=dst+1, len=len-1, n=(n+1) and 0Fh ;/
[nc_off]=n
AES-Key-Wrap/Unwrap
This is used for EAPOL Key Data in WPA2 Wifi packets, however, neither DSi-ARM7
nor DSi-Wifi do support that by hardware, so the unwrap (decrypt) must be
implemented by software. For details see:
--> DS Wifi WPA/WPA2 Encryption
Below are some other AES variants (just for curiosity - those variants aren't
used in DSi):
aes_crypt_block(mode,src,dst):
Y0 = RK[0] xor [src+00h]
Y1 = RK[1] xor [src+04h]
Y2 = RK[2] xor [src+08h]
Y3 = RK[3] xor [src+0Ch]
;below code depending on mode: <---ENCRYPT---> -or- <---DECRYPT--->
for i=1 to nr-1
X0 = RK[i*4+0] xor scatter32(FT,Y0,Y1,Y2,Y3) -or- (RT,Y0,Y3,Y2,Y1)
X1 = RK[i*4+1] xor scatter32(FT,Y1,Y2,Y3,Y0) -or- (RT,Y1,Y0,Y3,Y2)
X2 = RK[i*4+2] xor scatter32(FT,Y2,Y3,Y0,Y1) -or- (RT,Y2,Y1,Y0,Y3)
X3 = RK[i*4+3] xor scatter32(FT,Y3,Y0,Y1,Y2) -or- (RT,Y3,Y2,Y1,Y0)
Y0=X0, Y1=X1, Y2=X2, Y3=X3
[dst+00h] = RK[nr*4+0] xor scatter8(FSb,Y0,Y1,Y2,Y3) -or- (RSb,Y0,Y3,Y2,Y1)
[dst+04h] = RK[nr*4+1] xor scatter8(FSb,Y1,Y2,Y3,Y0) -or- (RSb,Y1,Y0,Y3,Y2)
[dst+08h] = RK[nr*4+2] xor scatter8(FSb,Y2,Y3,Y0,Y1) -or- (RSb,Y2,Y1,Y0,Y3)
[dst+0Ch] = RK[nr*4+3] xor scatter8(FSb,Y3,Y0,Y1,Y2) -or- (RSb,Y3,Y2,Y1,Y0)
scatter32(TAB,a,b,c,d): scatter8(TAB,a,b,c,d):
w= (TAB[a.bit0..7]) w.bit0..7 = TAB[a.bit0..7]
w=w xor (TAB[b.bit8..15] rol 8) w.bit8..15 = TAB[b.bit8..15]
w=w xor (TAB[c.bit16..23] rol 16) w.bit16..23 = TAB[c.bit16..23]
w=w xor (TAB[d.bit24..31] rol 24) w.bit24..31 = TAB[d.bit24..31]
return w return w
aes_generate_tables:
for i=0 to 0FFh ;compute pow and log tables...
if i=0 then x=01h, else x=x xor x*2, if x>0FFh then x=x xor 11Bh
pow[i]=x, log[x]=i
for i=0 to 0FFh ;generate the forward and reverse S-boxes...
x=pow[0FFh-log[i]]
x=x xor (x rol 1) xor (x rol 2) xor (x rol 3) xor (x rol 4) xor 63h
if i=0 then x=63h
FSb[i]=x, RSb[x]=i
for i=0 to 0FFh ;generate the forward and reverse tables...
x=FSb[i]*2, if x>0FFh then x=x xor 11Bh
FT[i]=(FSb[i]*01010100h) xor (x*01000001h)
w=00000000h, x=RSb[i]
if x<>00h then ;ie. not at i=63h
w=w+pow[(log[x]+log[0Eh]) mod 00FFh]*1h
w=w+pow[(log[x]+log[09h]) mod 00FFh]*100h
w=w+pow[(log[x]+log[0Dh]) mod 00FFh]*10000h
w=w+pow[(log[x]+log[0Bh]) mod 00FFh]*1000000h
RT[i]=w
aes_generate_tables_results:
pow[00h..FFh] = 01,03,05,0F,11,..,C7,52,F6,01 ;pow ;\needed temporarily
log[00h..FFh] = 00,FF,19,01,32,..,C0,F7,70,07 ;log ;/for table creation
FSb[00h..FFh] = 63,7C,77,7B,F2,..,B0,54,BB,16 ;Forward S-box
RSb[00h..FFh] = 52,09,6A,D5,30,..,55,21,0C,7D ;Reverse S-box
FT[00h..FFh] = A56363C6,847C7CF8,..,3A16162C ;Forward Table
RT[00h..FFh] = 50A7F451,5365417E,..,4257B8D0 ;Reverse Table
aes_setkey_results:
key = "AES-Test-Key-Str-1234567-Abcdefg" ;use only 1st bytes for 128/192bit
128bit ENCRYPT --> RK[0..9..30..43] = 2D534541..ED0DC6FA..43DAC81C..0F5026BB
192bit ENCRYPT --> RK[0..9..30..51] = 2D534541..4AAB3D82..29CA38D2..CA4DFE3B
256bit ENCRYPT --> RK[0..9..30..59] = 2D534541..1AA51359..CCB886C8..88956C9C
128bit DECRYPT --> RK[0..9..30..43] = F653079B..47DD8A1C..1C2070A7..7274532D
192bit DECRYPT --> RK[0..9..30..51] = 3CEC6AFF..C4F96B6F..AE36B4AE..7274532D
256bit DECRYPT --> RK[0..9..30..59] = DE7ADCD9..8C559ADD..067A387E..7274532D
aes_crypt_results:
[key+0..15] = "AES-Test-Key-Str-1234567-Abcdefg"
[iv+0..15] = "Nonce/InitVector"
[xtra+0..20] = "Extra-Associated-Data" ;\for CCM
iv_len=12, mac_len=16, xtra_len=21 ;/
Unencrypted: [dta+0..113Fh] = "Unencrypted-Data", 190h x "TestPadding"
AES-ECB: [dta+0..113Fh] = 5F,BD,04,DB,..,E4,07,F4,B6 ;\
AES-CBC: [dta+0..113Fh] = 0B,BB,53,FA,..,DD,28,6D,AE ;
AES-CFB128: [dta+0..113Fh] = F4,75,4F,0E,..,73,B5,D7,E7 ; keysize=128
AES-CFB8: [dta+0..113Fh] = F4,10,6A,83,..,BF,1B,16,3E ;
AES-CTR: [dta+0..113Fh] = F4,75,4F,0E,..,04,DF,EB,BA ;
AES-CCM: [dta+0..113Fh] = FD,1A,6D,98,..,EE,FD,68,F6 ;
AES-CCM (ori): [mac+0..0Fh] = FD,F9,FE,85,..,4F,50,3C,AF ;
AES-CCM (DSi): [mac+0..0Fh] = xx,xx,xx,xx,..,xx,xx,xx,xx ;/
AES-ECB: [dta+0..113Fh] = 0E,69,F5,1A,..,9A,5F,7A,9A ;-keysize=192
AES-ECB: [dta+0..113Fh] = C6,FB,68,C1,..,14,89,6C,E0 ;-keysize=256
ES Block Encryption, for lack of a better name, is a Nintendo DSi specific data
encryption method. It's used for some SD/MMC files:
FAT16:\sys\dev.kp
FAT16:\ticket\000300tt\4ggggggg.tik (tickets)
SD Card: .bin files (aka Tad Files) (contains multiple blocks)
.twl-*.der files (within the "verdata" NARC file)
Block Layout
00000h BLKLEN Data Block (AES-CCM encrypted)
BLKLEN+00h 10h Data Checksum (AES-CCM MAC value on above Data)
BLKLEN+10h 1 Fixed 3Ah (AES-CTR encrypted)
BLKLEN+11h 0Ch Nonce (unencrypted)
BLKLEN+1Dh 1 BLKLEN.bit16-23 (AES-CTR encrypted)
BLKLEN+1Eh 1 BLKLEN.bit8-15 (AES-CTR encrypted)
BLKLEN+1Fh 1 BLKLEN.bit0-7 (AES-CTR encrypted)
BLKLEN can be max 20000h. If the Data is bigger than 128Kbytes, then it's split
into multiple block(s) with BLKLEN=20000h (the last block can have smaller
BLKLEN).
DSiware/System Utilities
Files saved on SD card or internal eMMC memory are having the same header as
ROM carts, with some differences:
No need for NDS backwards compatibility (since DSiware is DSi only)
Entry 3A0h can be zero-filled (in LAUNCHER)
DSiware files are usually marked as [012h]=03h=DSi (exceptions are the DS
Download Play and PictoChat utilities, which are marked [012h]=00h=NDS, since
they are actually running in NDS mode (yet having at least two DSi-specific
features: 1st is allowing to reboot into DSi menu via Powerman SPI, 2nd is
requiring enabled wifi channels in 2FFFCFAh)).
SHA1-HMAC
The SHA1-HMAC's in cart header and Digest tables are SHA1 checksums with a
40h-byte HMAC key (values 21h, 06h, C0h, DEh, BAh, ..., 24h), the key is
contained in the Launcher, and it's also stored in most DSi cartridges
(probably used for verifying Digest values when loading additional data after
booting). The key can be used for verifying checksums, but (due to the RSA
signature) not for changing them. See BIOS chapter for SHA1/HMAC pseudo code.
RSA-SHA1
The RSA-SHA1 value is a normal SHA1 (not SHA1-HMAC) across header entries
[000h..DFFh], the 20-byte value is padded to 127-byte size (01h, 105xFFh, 00h,
followed by the 20 SHA1 bytes). It can be decrypted (via SWI 22h) using the
80h-byte RSA public keys located in ARM9BIOS (note that there are at least four
different RSA keys, one is used for games, and others for system files), and
can be then verfied against the SHA1 checksum (computed via SWI 27h).
--> BIOS RSA Functions (DSi only)
The private key needed for encryption is unknown, which is unfortunately
preventing to boot unlicensed (homebrew) software.
Cartridge Protocol
The DSi cartridge protocol is same as on NDS; with one new command (3Dh) for
unlocking DSi specific memory regions. For details,
--> DS Cartridge Protocol
AIC3000D Registers
--> DSi TSC, Register Summary
--> DSi TSC[0:00h..1Ah], Basic PLL and Timing Control
--> DSi TSC[0:1Bh..23h], Codec Control
--> DSi TSC[0:24h..32h], Status and Interrupt Flags
--> DSi TSC[0:33h..3Bh], Pin Control
--> DSi TSC[0:3Ch..55h], DAC/ADC and Beep
--> DSi TSC[0:56h..7Fh], AGC and ADC
--> DSi TSC[1:xxh], DAC and ADC Routing, PGA, Power-Controls and MISC Logic
--> DSi TSC[3:xxh], Touchscreen/SAR Control and TSC[FCh:xxh], Buffer
--> DSi TSC[04h..05h:xxh], ADC Digital Filter Coefficient RAM
--> DSi TSC[08h..0Fh:xxh], DAC Digital Filter Coefficient RAM
--> DSi TSC[20h..2Bh:xxh], TSC[40h..5Fh:xxh] ADC/DAC Instruction RAM
The Touch Screen Controller (for lower LCD screen) is accessed via SPI bus,
--> DS Serial Peripheral Interface Bus (SPI)
so far, it's same as on NDS, but the SPI touchscreen commands are having an
entirely different format in DSi mode:
The DSi touchscreen registers are selected via a combination of a PAGE byte and
an INDEX byte. The PAGE byte is located at INDEX=00h, and it does somewhat
'bankswitch' the contents of INDEX=01h..7Fh. And INDEX can be incremented
manually, or automatically (but, confusingly, the manual increment doesn't work
for reading Y coordinates).
SPI clock should be set to 4MHz for DSi Mode touchscreen access (unlike NDS,
which used 2MHz). The PENIRQ bit in port 4000136h is always zero in DSi mode.
When reading data: Write dummy 00h-bytes in output direction.
AIC3000D
Microphone
The microphone input was part of the TSC on NDS. In DSi mode it is reportedly
somehow changed, using a new "CODEC" (whatever that means). Maybe it's accessed
directly via an ARM7 port (and/or TEAK port?), instead of via SPI bus?
touch_enable_tsc_init_list:
TSC[3:0Eh]=00h ;Undoc (RMW: bit7=0)
TSC[3:02h]=18h ;SAR ADC clk divider, Div8 (12bit mode) (RMW bit34=3, bit7=?)
TSC[3:0Fh]=A0h ;Scan Mode Timer
TSC[3:0Eh].28h ;Undoc (RNW: bit345=5)
TSC[3:0Eh].28h ;Undoc (RMW: bit6=0)
TSC[3:03h]=87h ;SAR ADC Control 2 (SelfByPenDown, ScanXY, /PENIRQ)
TSC[3:05h].04h ;Stabilization time = 30us (RMW bit012=4)
TSC[3:04h].02h ;Sense time = 3us (RMW bit012=2)
TSC[3:04h].22h ;Precharge time = 3us (RMW bit456=2)
TSC[3:12h].00h ;Debounce Time = 0us (RMW bit012=0)
TSC[3:0Eh].A8h ;Undoc (RMW bit7=1)
mic_enable_tsc_init_list:
This is needed to unmute the microphone (otherwise microphone will return only
0000h or FFFFh.
TSC[1:2Eh]=03h ;MICBIAS=AVDD
TSC[0:51h]=80h ;ADC Digital Mic, on
TSC[0:52h]=00h ;ADC Digital Volume Control Fine Adjust, unmute
TSC[1:2Fh]=37h ;MIC PGA=27.5dB (or use other value, if desired)
mic_disable_tsc_init_list:
TSC[0:52h]=80h ;ADC Digital Volume Control Fine Adjust, mute
TSC[0:51h]=00h ;ADC Digital Mic, off
TSC[1:2Eh]=00h ;MICBIAS=Off
basic_tsc_init_list:
This is done by DSi Launcher/Unlaunch (and other titles usually won't need to
do this.
TSC[0:01h]=01h ;Software Reset
TSC[0:39h]=66h ;ADC DC Measurement 1
TSC[1:20h]=16h ;Class-D Speaker Amplifier (RMW:bit4=1)
TSC[0:04h]=00h ;Clock-Gen Muxing
TSC[0:12h]=81h ;ADC NADC Value
TSC[0:13h]=82h ;ADC MADC Value
TSC[0:51h]=82h ;ADC Digital Mic
TSC[0:51h]=00h ;ADC Digital Mic again
TSC[0:04h]=03h ;Clock-Gen Muxing
TSC[0:05h]=A1h ;PLL P and R-Values
TSC[0:06h]=15h ;PLL J-Value
TSC[0:0Bh]=87h ;DAC NDAC Value
TSC[0:0Ch]=83h ;DAC MDAC Value
TSC[0:12h]=87h ;ADC NADC Value
TSC[0:13h]=83h ;ADC MADC Value
TSC[3:10h]=88h ;Scan Mode Timer Clock (RMW:bit0-6)
TSC[4:08h..0Dh]=7Fh,E1h,80h,1Fh,7Fh,C1h ;some coeff's
TSC[0:41h]=08h ;DAC Left Volume Control
TSC[0:42h]=08h ;DAC Right Volume Control
TSC[0:3Ah]=00h ;GPI3 Pin Control
TSC[4:08h..0Dh]=7Fh,E1h,80h,1Fh,7Fh,C1h ;some coeff's ;again?
TSC[1:2Fh]=2Bh ;MIC PGA
TSC[1:30h]=40h ;P-Terminal Delta-Sigma Mono ADC Channel Fine-Gain Input
TSC[1:31h]=40h ;M-Terminal ADC Input Selection
TSC[1:32h]=60h ;Input CM Settings
TSC[0:74h]=82h ;VOL/MICDET-Pin SAR ADC - Volume Control (RMW)
TSC[0:74h]=92h ;VOL/MICDET-Pin SAR ADC - Volume Control (RMW)
TSC[0:74h]=D2h ;VOL/MICDET-Pin SAR ADC - Volume Control (RMW)
TSC[1:21h]=20h ;HP Output Drivers POP Removal Settings
TSC[1:22h]=F0h ;Output Driver PGA Ramp-Down Period Control
TSC[0:3Fh]=D4h ;DAC Data-Path Setup (RMW)
TSC[1:23h]=44h ;DAC_L and DAC_R Output Mixer Routing
TSC[1:1Fh]=D4h ;Headphone Drivers
TSC[1:28h]=4Eh ;HPL Driver (Left Headphone)
TSC[1:29h]=4Eh ;HPR Driver (Right Headphone)
TSC[1:24h]=9Eh ;Analog Volume to HPL (Left Headphone)
TSC[1:25h]=9Eh ;Analog Volume to HPR (Right Headphone)
TSC[1:20h]=D4h ;Class-D Speaker Amplifier
TSC[1:2Ah]=14h ;SPL Driver (Left Speaker)
TSC[1:2Bh]=14h ;SPR Driver (Right Speaker)
TSC[1:26h]=A7h ;Analog Volume to SPL (Left Speaker)
TSC[1:27h]=A7h ;Analog Volume to SPR (Right Speaker)
TSC[0:40h]=00h ;DAC Volume Control
(should set DSi.GPIO.data.bit7 here, but can be also done elsewhere)
TSC[0:3Ah]=60h ;GPI3 Pin Control
nds_mode_tsc_init_list:
Switches to NDS Touchscreen/sound mode. Usually done when starting NDS titles
(or DSi titles that request NDS-TSC mode in carthdr[1BFh]).
TSC[1:26h]=ACh ;\special setting (when found special gamecode)
TSC[1:27h]=ACh ;/
TSC[1:26h]=A7h ;\normal setting (for any other gamecodes)
TSC[1:27h]=A7h ;/
TSC[1:2Eh]=03h ;MICBIAS=AVDD
TSC[3:03h]=00h ;SAR ADC Control 2
TSC[1:21h]=20h ;HP Output Drivers POP Removal Settings
TSC[1:22h]=F0h ;Output Driver PGA Ramp-Down Period Control (70h OR 80h)
TSC[1:22h]=70h ;Output Driver PGA Ramp-Down Period Control (bit7=0)
TSC[0:52h]=80h ;ADC Digital Volume Control Fine Adjust
TSC[0:51h]=00h ;ADC Digital Mic
READ[3:02h] (returns 00h)
TSC[3:02h].Bit7=1 ;SAR ADC Control 1 (set to 80h) (or 98h?) (RMW)
TSC[FFh:05h]=00h ;TSC final enter NDS mode
And, set powerman[0].bit0=1 (bit0=sound amplifier on) (this is actually part of
TSC chip, accessed via "POWERMAN" SPI chipselect signal).
TSC[page:index] registers are accessed via SPI bus with 15bit address space:
7bit index: selected via the first SPI byte, with direction flag in bit0
8bit page: selected by writing to index 00h, ie. to TSC[xxh:00h]
DSi TSC[1:xxh], DAC and ADC Routing, PGA, Power-Controls and MISC Logic
-----------------------------------------------------------------------
TSC[3:0Eh] - Reserved / Undocumented (read by DSi for Pen Down Test) (0Fh)
7-0 Reserved. Write only the reset value to these bits.
However, in DSi this is used as so... (seems to resemble TSC[3:0Dh])...
7 Undoc Enable (0=Disabled, 1=Enabled) (R/W)
6 Undoc Whatever (0=Normal) (R/W)
5-3 Undoc Whatever (5=Normal) (R/W)
2 Undoc Unused (?)
1 Undoc Pendown/DataAvailable? (R?)
0 Undoc Unused (R?)
Default values shown for this page only become valid 100us following a hardware
or software reset.
Default values shown for this page only become valid 100us following a hardware
or software reset.
I2C Bus
--> DSi I2C I/O Ports
--> DSi I2C Signals
Below is some pseudo code for the I2C signal transmission. The DSi hardware is
doing most of that stuff automatically. The pseudo code may be useful for
understanding the purpose of the start/stop/ack flags in the control register.
SDA should be changed at/after falling SCL edge (except for Start/Stop
conditions, which are output during SCL=High).
The Device/Direction Byte is sent by master (the byte contains a 7bit device
address in bit7-1, and a direction flag in bit0). The direction of the follwing
index/data byte(s) depends on that direction flag (0=Write, 1=Read). The ACK
bit responses are sent in opposite direction as the preceeding byte.
The SCL line is driven by master, however, when the master changes SCL from Low
to HighZ, then the slave may keep SCL held Low to signalize that it isn't yet
ready for the next bit.
i2c_write_byte(send_start,send_stop,databyte):
if (send_start) then i2c_start_cond() ;-start (if so)
for i=7 downto 0, i2c_write_bit(databyte.bit(i)), next i ;-write 8bit
nack = i2c_read_bit() ;-read nack
if (send_stop) then i2c_stop_cond() ;-stop (if so)
return nack ;return 0 if ack by the slave. ;-return nack
i2c_read_byte(send_stop):
for i=7 downto 0, databyte.bit(i)=i2c_read_bit(), next i ;-read 8bit
i2c_write_bit(nack) ;-write nack
if (send_stop) then ;\
i2c_write_bit(1) ;NACK (ack=high=Last byte) ; nack (finish)
i2c_stop_cond() ;STOP ;/
else ;\ack (want more)
i2c_write_bit(0) ;ACK (ack=low=More bytes) ;/
return databyte ;-return databyte
i2c_write_bit(bit):
if (bit) then SDA=HighZ else SDA=Low ;-
I2C_delay() ;-
SCL=HighZ
wait until SCL=High (or timeout) ;-wait (for clock stretching)
if (bit=1 and SDA=Low) then arbitration_lost();-errif other HW pulls SDA=low
I2C_delay() ;-
SCL=Low ;-
i2c_read_bit():
SDA=HighZ ;-let the slave drive data
I2C_delay() ;-delay (one half clk)
SCL=HighZ
wait until SCL=High (or timeout) ;-wait (for clock stretching)
bit = SDA ;-
I2C_delay() ;-delay (one half clk)
SCL=Low ;-
return bit ;-
i2c_start_cond():
if (started) then ;if started, do a restart cond
SDA=HighZ ;-set SDA to 1
I2C_delay()
SCL=HighZ
wait until SCL=High (or timeout) ;-wait (for clock stretching)
I2C_delay() ;Repeated start setup time, minimum 4.7us
if (SDA=Low) then arbitration_lost()
SDA=Low ;-
I2C_delay()
SCL=Low
started = true
i2c_stop_cond():
SDA=Low ;-
I2C_delay() ;-
SCL=HighZ ;-
wait until SCL=High (or timeout) ;-wait (for clock stretching)
I2C_delay() ;Stop bit setup time, minimum 4us
if (SDA=Low) then arbitration_lost()
I2C_delay()
started = false
I2C ACK/NACK Notes
There are five conditions that lead to the generation of a NACK:
1. No receiver is present on the bus with the transmitted address so there
is no device to respond with an acknowledge.
2. The receiver is unable to receive or transmit because it is performing
some real-time function and is not ready to start communication with the
master.
3. During the transfer, the receiver gets data or commands that it does not
understand.
4. During the transfer, the receiver cannot receive any more data bytes.
5. A master-receiver must signal the end of the transfer to the slave
transmitter.
Sending the I2C Stop condition is done by sending a "corrupted" databit
(instead of sending the first databit of the next byte) on the SDA output pin.
However, in receive mode, SDA would be in input direction (for receiving the
first databit of next byte). So the master simply cannot output the Stop
condition in that state (unless when using the ACK bit to notify the slave that
the transfer will be stopped now).
I2C Bus Caution: The BPTWL chip requires swiWaitByLoop(180h) after each I2C
byte transfer (if the Version/Speed byte at BPTWL[00h] indicates "Fast", then
the delay can be reduced to 90h instead of 180h).
And, SPI bus Powerman chip does somehow interact with I2C BPTWL chip; there
must be a similar delay between Powerman writes and BPTWL writes.
Older blurb...
0x10 1 Power flags. When bit0 is set, arm7 does a system reset.
When bit1 or bit3 are set, arm7 does a shutdown. Bits 0-2
are used for DSi IRQ6 IF flags (uh, rather IF2 maybe?).
0x20 1 Battery flags. When zero the battery is at critical level,
arm7 does a shutdown. Bit7 is set when the battery is
charging. Battery levels in the low 4-bits: battery icon
bars full 0xF, 3 bars 0xB, 2 bars 0x7, one solid red bar
0x3, and one blinking red bar 0x1. When plugging in or
removing recharge cord, this value increases/decreases
between the real battery level and 0xF, thus the battery
level while bit7 is set is useless.
Overview
Launcher (and unlaunch) can be commanded to autoload a different title.
2000000h Autoload Parameters for newly loaded title ;<-- optional extra
2000300h Autoload via numeric Title ID ;<-- official method
2000800h Autoload via string "device:\path\filename" ;<-- alternate method
2FFD800h Title List (jump-able titles for use at 2000300h)
BPTWL[70h].bit0 Warmboot flag ;<-- required flag
BPTWL[11h].bit0 Trigger reset ;<-- trigger reset
Moreover, autoload can occur on warmboot & coldboot: Launcher autoloads any ROM
cartridge with carthdr[01Fh].Bit2. Unlaunch defaults to autoload any file named
"sdmc:\bootcode.dsi".
Examples
DSi Browser settings screen allows to autoload System Settings (via 2000300h),
and automatically enter the Internet options page (via 2000000h).
Nintendo Zone, if started with Wireless Communications disabled, allows to
reboot itself (via specifying it's own Title ID in 2000300h).
Homebrew frontends for unlaunch could start themselves (via bootcode.dsi) and
then command unlaunch to load another title (via 2000800h or 2000300h).
Aptina I2C registers are accessed via 16bit index, and one or more data bytes
at auto-increasing indices (usually, all transfers are done as big-endian
2-byte (16bit) values at even indices). Additional MCU Variables are accessed
indirectly via XMDA registers.
aptina_get_chip_id:
Reading a 16bit value from index 0000h returns the CHIP_VERSION_REG (always
2280h=MT9V113 for DSi/3DS/New3DS), the DSi games are actually reading that
register, but they seem to ignore it's value.
If the DSi isn't fitted with Aptina cameras, then reading anything from device
78h/7Ah would most likely return FFh-bytes.
aptina_code_list_init:
Below is some minimal initialization (though it might still include some
unnecessary stuff). Most important sections are leaving standby mode, matching
PLL to DSi timings, selecting desired resolution(s) and YUV color format.
DSi games are usually initializing further stuff like P0..P4 Coefficients,
Gamma Tables, and Color Correction Matrices - but the cameras are also working
when leaving those settings at their power-on defaults.
It's recommended to initialize both cameras in parallel (eg. issue Wakeup to
<both> cameras, and <then> wait for Wakeup completion; this is faster than
doing it separately for each camera).
AptWr ,0001Ah,00003h ;RESET_AND_MISC_CONTROL (issue reset) ;\reset
AptWr ,0001Ah,00000h ;RESET_AND_MISC_CONTROL (release reset) ;/
AptWr ,00018h,04028h ;STANDBY_CONTROL (wakeup) ;\
AptWr ,0001Eh,00201h ;PAD_SLEW ; wakeup
AptWr ,00016h,042DFh ;CLOCKS_CONTROL ;
AptWaitClr,00018h,04000h ;STANDBY_CONTROL (wait for WakeupDone) ;
AptWaitSet,0301Ah,00004h ;UNDOC_CORE_301A (wait for WakeupDone) ;/
AptWrMcu ,002F0h,00000h ;UNDOC! RAM?
AptWrMcu ,002F2h,00210h ;UNDOC! RAM?
AptWrMcu ,002F4h,0001Ah ;UNDOC! RAM?
AptWrMcu ,02145h,002F4h ;UNDOC! SEQ?
AptWrMcu ,0A134h, 001h ;UNDOC! SEQ?
AptSetMcu ,0A115h, 002h ;SEQ_CAP_MODE (set bit1=video)
AptWrMcu ,02755h,00002h ;MODE_OUTPUT_FORMAT_A (bit5=0=YUV) ;\select
AptWrMcu ,02757h,00002h ;MODE_OUTPUT_FORMAT_B ;/YUV mode
AptWr ,00014h,02145h ;PLL_CONTROL ;\
AptWr ,00010h,00111h ;PLL_DIVIDERS ; match
AptWr ,00012h,00000h ;PLL_P_DIVIDERS ; PLL
AptWr ,00014h,0244Bh ;PLL_CONTROL ; to DSi
AptWr ,00014h,0304Bh ;PLL_CONTROL ; timings
AptWaitSet,00014h,08000h ;PLL_CONTROL (wait for PLL Lock okay) ;
AptClr ,00014h,00001h ;PLL_CONTROL (disable PLL Bypass) ;/
AptWrMcu ,02703h,00100h ;MODE_OUTPUT_WIDTH_A ;\Size A
AptWrMcu ,02705h,000C0h ;MODE_OUTPUT_HEIGHT_A ;/ 256x192
AptWrMcu ,02707h,00280h ;MODE_OUTPUT_WIDTH_B ;\Size B
AptWrMcu ,02709h,001E0h ;MODE_OUTPUT_HEIGHT_B ;/ 640x480
AptWrMcu ,02715h,00001h ;MODE_SENSOR_ROW_SPEED_A ;\
AptWrMcu ,02719h,0001Ah ;MODE_SENSOR_FINE_CORRECTION_A ;
AptWrMcu ,0271Bh,0006Bh ;MODE_SENSOR_FINE_IT_MIN_A ; Sensor A
AptWrMcu ,0271Dh,0006Bh ;MODE_SENSOR_FINE_IT_MAX_MARGIN_A ;
AptWrMcu ,0271Fh,002C0h ;MODE_SENSOR_FRAME_LENGTH_A ;
AptWrMcu ,02721h,0034Bh ;MODE_SENSOR_LINE_LENGTH_PCK_A ;/
AptWrMcu ,0A20Bh, 000h ;AE_MIN_INDEX ;\AE min/max
AptWrMcu ,0A20Ch, 006h ;AE_MAX_INDEX ;/
AptWrMcu ,0272Bh,00001h ;MODE_SENSOR_ROW_SPEED_B ;\
AptWrMcu ,0272Fh,0001Ah ;MODE_SENSOR_FINE_CORRECTION_B ;
AptWrMcu ,02731h,0006Bh ;MODE_SENSOR_FINE_IT_MIN_B ; Sensor B
AptWrMcu ,02733h,0006Bh ;MODE_SENSOR_FINE_IT_MAX_MARGIN_B ;
AptWrMcu ,02735h,002C0h ;MODE_SENSOR_FRAME_LENGTH_B ;
AptWrMcu ,02737h,0034Bh ;MODE_SENSOR_LINE_LENGTH_PCK_B ;/
AptSet ,03210h,00008h ;COLOR_PIPELINE_CONTROL (PGA pixel shading..)
AptWrMcu ,0A208h, 000h ;UNDOC! RESERVED_AE_08
AptWrMcu ,0A24Ch, 020h ;AE_TARGETBUFFERSPEED
AptWrMcu ,0A24Fh, 070h ;AE_BASETARGET
If Device=7Ah ;\
AptWrMcu,02717h,00024h ;MODE_SENSOR_READ_MODE_A ; Read Mode
AptWrMcu,0272Dh,00024h ;MODE_SENSOR_READ_MODE_B ; with x-flip
Else (xflip) ; on internal
AptWrMcu,02717h,00025h ;MODE_SENSOR_READ_MODE_A ; camera
AptWrMcu,0272Dh,00025h ;MODE_SENSOR_READ_MODE_B ;/
If Device=7Ah ;\
AptWrMcu,0A202h, 022h ;AE_WINDOW_POS ;
AptWrMcu,0A203h, 0BBh ;AE_WINDOW_SIZE ;
Else (?) ;
AptWrMcu,0A202h, 000h ;AE_WINDOW_POS ;
AptWrMcu,0A203h, 0FFh ;AE_WINDOW_SIZE ;/
AptSet ,00016h,00020h ;CLOCKS_CONTROL (set bit5=1, reserved)
AptWrMcu ,0A115h, 072h ;SEQ_CAP_MODE (was already manipulated above)
AptWrMcu ,0A11Fh, 001h ;SEQ_PREVIEW_1_AWB ;\
If Device=7Ah ;
AptWr ,0326Ch,00900h ;APERTURE_PARAMETERS ;
AptWrMcu,0AB22h, 001h ;HG_LL_APCORR1 ;
Else (?) ;
AptWr ,0326Ch,01000h ;APERTURE_PARAMETERS ;
AptWrMcu,0AB22h, 002h ;HG_LL_APCORR1 ;/
AptWrMcu ,0A103h, 006h ;SEQ_CMD (06h=RefreshMode)
AptWaitMcuClr,0A103h, 00Fh ;SEQ_CMD (wait above to become ZERO)
AptWrMcu ,0A103h, 005h ;SEQ_CMD (05h=Refresh)
AptWaitMcuClr,0A103h, 00Fh ;SEQ_CMD (wait above to become ZERO)
Above does set two Mode/Contexts, 256x192 and 640x480. Yet unknown how to
activate the latter one.
aptina_code_list_activate:
AptClr ,00018h,00001h ;STANDBY_CONTROL (bit0=0=wakeup) ;\
AptWaitClr,00018h,04000h ;STANDBY_CONTROL (wait for WakeupDone) ; Wakeup
AptWaitSet,0301Ah,00004h ;UNDOC_CORE_301A (wait for WakeupDone) ;/
AptWr ,03012h,000xxh ;COARSE_INTEGRATION_TIME (Y Time)
AptSet ,0001Ah,00200h ;RESET_AND_MISC_CONTROL (Parallel On) ;-Data on
Also, don't forget to activate the Camera LED via BPTWL chip (when using the
external camera).
aptina_code_list_deactivate:
Before activating another camera: First disable the Parallel output of the old
camera (for avoiding collisions on the camera's parallel databus). When not
using the camera for longer time, also enter standby mode (for reducing power
consumption).
AptClr ,0001Ah,00200h ;RESET_AND_MISC_CONTROL (Parallel Off) ;-Data off
AptSet ,00018h,00001h ;STANDBY_CONTROL (set bit0=1=Standby) ;\
AptWaitSet,00018h,04000h ;STANDBY_CONTROL (wait for StandbyDone) ; Standby
AptWaitClr,0301Ah,00004h ;UNDOC_CORE_301A (wait for StandbyDone) ;/
References
There aren't any MT9V113 specs released, but info for MT9D113 (a higher
resolution variant) does exist: a pdf datasheet, and an xml reference for the
I2C registers.
There are several source code files for MT9V113 cameras (different files from
different people; for use with linux/android/whatever) including samples for
adjusting stuff like contrast and sharpness. However, observe that the source
code may need some adjustments: PLL register matched to DSi timings, and, use
YUV 8bit parallel databus transfer for DSi.
SYSCTL (0000h-0051h)
0000h 2 CHIP_VERSION_REG Model ID (2280h=MT9V113 on DSi/3DS) (R)
0006h .. RESERVED_SYSCTL_06 Reserved
0010h 2 PLL_DIVIDERS PLL Dividers (def=0366h)
0-7 PLL M-Divider value (uh, actually a Multiplier?!)
8-13 PLL N-Divider value
14-15 Unused (0)
Because the input clock frequency is unknown, the sensor starts
up with the PLL disabled. The PLL takes time to power up. During
this time, the behavior of its output clock signal is not
guaranteed. The PLL output frequency is determined by two
constants, M and N, and the input clock frequency.
VCO = Fin * 2 * M / (N+1)
PLL_output_frequency = VCO / (P1+1)
The PLL can generate a master clock signal whose frequency is up
to 85 MHz (input clock from 6 MHz through 54 MHz).
0012h 2 PLL_P_DIVIDERS PLL P Dividers (def=00F5h)
0-3 P1 (00h..0Fh)
4-7 Unspecified
8-11 P3 (00h..0Fh)
12-13 Division ratio of word clock/clockn from bit_clock (0..3)
14 Unused (0)
15 Unspecified
0014h 2 PLL_CONTROL PLL Control (def=21F9h)
0 PLL Bypass
1 PLL Enable
2-3 Reserved (0..3)
4-7 Reserved (0..0Fh)
8 Reset_cntr
9 Reserved
10 Reserved
11 Reserved
12 Reserved
13 Reserved
14 Unused (0)
15 PLL Lock (R)
0016h 2 CLOCKS_CONTROL Clocks Control
0 Reserved
1 Reserved
2 Reserved
3 Reserved
4 Reserved
5 Reserved/UNDOC/USED (manipulated by DSi)
6 Reserved
7 Reserved
8 Reserved
9 clk_clkin_en
11-12 Reserved
13 Reserved
15 Reserved
0018h 2 STANDBY_CONTROL Standby Control and Status (def=4029h)
0 Ship (uh?) (0=Enable various regs, 1=Standby)
1 Reserved
2 Stop MCU
3 en_IRQ
4 Reserved
5 Reserved
6-13 Unused (0)
14 Standby_done (0=WakeupDone, 1=StandbyDone) (R?)
(takes MUCH time?)
15 Reserved (R)
001Ah 2 RESET_AND_MISC_CONTROL Reset and Control (def=0050h) (0-0333h)
0 Reset SOC I2C
1 MIPI_TX_Reset
2 Unused (0)
3 MIPI_TX_en (=Serial Data?)
4 IP_PD_en (=Parallel Data or what?)
5 Reserved
6 Sensor_full_res
7 Unused (0)
8 OE_N_Enable
9 Parallel_enable (=Parallel Data?)
10 Unused (0)
11 Reserved
12-15 Unused (0)
001Ch 2 MCU_BOOT_MODE MCU Boot Mode
0 Reset MCU
1 Reserved
2 Reserved
3 Reserved
4-7 Reserved (0..0Fh)
8-15 Reserved (0..FFh) (R)
001Eh 2 PAD_SLEW Pad Slew Control (def=0400h)
0-2 Parallel Data Output Slew Rate Control (0-7)
3 Unused (0)
4-6 GPIO Slew Rate Control (0-7)
7 Unused (0)
8-10 PCLK aka PXLCLK Slew Rate Control (0-7)
11-15 Unused (0)
0020h .. RESERVED_SYSCTL_20 Reserved
0022h 2 VDD_DIS_COUNTER VDD_DIS_COUNTER (0..FFFFh, def=0438h)
0024h 2 GPI_STATUS GPI_STATUS (0..000Fh) (R)
0026h .. RESERVED_SYSCTL_26 Reserved
0028h 2 EN_VDD_DIS_SOFT EN_VDD_DIS_SOFT (0..0001h, def=0001h)
0050h .. RESERVED_SYSCTL_50 Reserved
RX_SS (0100h-0117h)
0100h .. RESERVED_RX_SS_100 Reserved
0102h 2 TEST_PXL_RED Test Pixel Red ;\Default value is 1FFh
0104h 2 TEST_PXL_G1 Test Pixel Green1 ; for Gray Flat Field
0106h 2 TEST_PXL_G2 Test Pixel Green2 ; (0..03FFh, def=01FFh)
0108h 2 TEST_PXL_BLUE Test Pixel Blue ;/
010Ah .. RESERVED_RX_SS_10A-116 Reserved
FUSE_ROM (0800h-081Fh)
Reserved, unknown purpose, all zero in DSi.
0800h .. RESERVED_FUSE_ROM_800-81E Reserved
XDMA (0982h-099Fh)
Access to internal LOGICAL "driver" variables.
0982h .. RESERVED_XDMA_982 Reserved
098Ch 2 MCU_ADDRESS MCU Address (0000h..FFFFh)
0-7 driver_variable (0..FFh)
8-12 driver_id (0..1Fh) (eg. 3=AWB, 7=MODE, etc.)
13-14 address space (0=Physical/RAM/SFR, 1=Logical/Variables)
15 access_8_bit (0=16bit, 1=8bit; converted to 16bit)
0990h 8x2 MCU_DATA_0-7 MCU Data 0..7 (8 x 16bit)
For reading, it's best to use "16bit" mode, no matter if reading an 8bit BYTE,
or a 16bit MSB,LSB value. The "8bit" mode is converting bytes to 16bit values
(MSB=00h, LSB=BYTE), which is a rather contraproductive idiotism; intended for
I2C functions that implement only 16bit data transfers, but no 8bit transfers.
Unknown what exactly is mapped at MCU_DATA_0-7 (probably the 16 bytes at
MCU_ADDRESS+0..15, probably with direct mapping / ie. without latching a copy
of that memory).
MCU_ADDRESS doesn't seem to increment after reading data, however, the i2c
index does increase, so one can probably read up to 16 bytes from MCU_DATA_0-7.
SOC2 (3400h-3729h)
3400h 2 MIPI_CONTROL MIPI_Control (def=782Eh)
0 MIPI restart enable
1 MIPI standby
2 Continuous MIPI clock
3 Frame boundary sync bit (R)
4 Wait until eof to react to standby
5 Reserved
6-8 MIPI channel number
9 Unused (0) or Reserved (REV3)
10-15 Data Type (1Eh=YUV422_8bit, 20h=RGB444, 21h=RGB555,
22h=RGB565, 2Ah=RAW8, 2Bh=RAW10)
3402h 2 MIPI_STATUS MIPI_Status (def=0011h)
0 MIPI in standby (R)
1-3 Unused (0)
4 MIPI aka MIPICCP idle (R)
5 MIPI ready to receive data (R)
6-8 Unused (0)
9 Reserved (R)
10 Reserved (R)
11 Reserved
12 Reserved
13-15 Unused (0)
3404h 2 CUSTOM_SHORT_PKT MIPI_Custom_Short_Packet (0000h-3F00h)
0-5 Unused (0)
6 frame_cnt_reset (sent in frame start/end short packets)
7 frame_cnt_en (Insert frame counter value in WC field)
8-10 custom_short_packet_data_type
11 custom_short_packet_request
12 custom_short_packet_frame_sync
13 custom_short_packet_reset (R)
14-15 Unused (0)
3408h 2 LINE_BYTE_CNT MIPI line byte count (def=0C80h)
340Ch 2 CUSTOM_SHORT_PKT_WC WC field of a custom short packet
340Eh .. RESERVED_SOC2_340E-341A Reserved
3580h 2 AE_ZONE_X AE Window/Zone X (def=1300h)
0-7: ae_zone_x_start (00h..FFh) (div8) ;for WINDOW
8-15: ae_zone_x_width (00h..FFh) (div8, minus 1) ;for each ZONE
3582h 2 AE_ZONE_Y AE Window/Zone Y (def=0E00h)
0-7: ae_zone_y_start (00h..FFh) (div8) ;for WINDOW
8-15: ae_zone_y_width (00h..FFh) (div8, minus 1) ;for each ZONE
3584h 2 AE_WINDOW_SIZE_LO LSBs ;\Size of each AE zone in pixels
3586h 2 AE_WINDOW_SIZE_HI MSBs ;/(0..0001FFFFh, def=000x4B00h ?)
3588h .. RESERVED_SOC2_3588-35AE Reserved
35B0h UNDOC_SOC2_35B0 (mask=FFFFh, 0..FFFFh, def=05FAh) USED!
35B2h .. RESERVED_SOC2_35B2-3602 Reserved
3604h 20 R_GAMMA_CURVE_KNEES_0-18 Red Gamma Curve Knees 0..18 (1B00h,..)
3618h 20 G_GAMMA_CURVE_KNEES_0-18 Green Gamma Curve Knees 0..18 (1B00h,..)
362Ch 20 B_GAMMA_CURVE_KNEES_0-18 Blue Gamma Curve Knees 0..18 (1B00h,..)
Above 20-byte knees consist of ten 16bit values (Knee0 in LSB)
Due to the 16bit-big-endian format, the byte-order is:
Knee1,Knee0,Knee3,Knee2,...,Knee17,Knee16,UNUSED,Knee18
3640h .. RESERVED_SOC2_3640 Reserved
3642h 2 POLY_ORIGIN_R Center Row (max 07FFh, def=025Ch)
3644h 2 POLY_ORIGIN_C Center Column (max 07FFh, def=0324h)
3646h .. RESERVED_SOC2_3646-364C Reserved
364Eh 5x2 P_GR_P0Q0-4 P0Q for Green1 ;\P0 Coefficients
3658h 5x2 P_RD_P0Q0-4 P0Q for Red ; (5 x float16 each)
3662h 5x2 P_BL_P0Q0-4 P0Q for Blue ; (0010h,... each)
366Ch 5x2 P_GB_P0Q0-4 P0Q for Green2 ;/
3676h 5x2 P_GR_P1Q0-4 P1Q for Green1 ;\
3680h 5x2 P_RD_P1Q0-4 P1Q for Red ; P1 Coefficients
368Ah 5x2 P_BL_P1Q0-4 P1Q for Blue ; (5 x float16 each)
3694h 5x2 P_GB_P1Q0-4 P1Q for Green2 ;/
369Eh 5x2 P_GR_P2Q0-4 P2Q for Green1 ;\
36A8h 5x2 P_RD_P2Q0-4 P2Q for Red ; P2 Coefficients
36B2h 5x2 P_BL_P2Q0-4 P2Q for Blue ; (5 x float16 each)
36BCh 5x2 P_GB_P2Q0-4 P2Q for Green2 ;/
36C6h 5x2 P_GR_P3Q0-4 P3Q for Green1 ;\
36D0h 5x2 P_RD_P3Q0-4 P3Q for Red ; P3 Coefficients
36DAh 5x2 P_BL_P3Q0-4 P3Q for Blue ; (5 x float16 each)
36E4h 5x2 P_GB_P3Q0-4 P3Q for Green2 ;/
36EEh 5x2 P_GR_P4Q0-4 P4Q for Green1 ;\
36F8h 5x2 P_RD_P4Q0-4 P4Q for Red ; P4 Coefficients
3702h 5x2 P_BL_P4Q0-4 P4Q for Blue ; (5 x float16 each)
370Ch 5x2 P_GB_P4Q0-4 P4Q for Green2 ;/
3716h .. RESERVED_SOC2_3716-3278 Reserved
unknown_cam_get_chip_id:
Reading an 8bit value from index 00h (in any bank?) seems to return some Chip
ID, at least the DSi is reading that register before initialization (despite of
reading it, the DSi does appear to ignore that value though).
Note: On a DSi with Aptina cameras, trying to read anything from IC2 devices
A0h/E0h does just return FFh-bytes.
Formatting Note
Below tables consist of "Index,Length,Data[Length]" entries.
unknown_cam_type_code_list_init:
003h, 1,001h ;<-- bank maybe?
009h, 3,0E2h,002h,002h
004h, 1,010h
004h, 1,0A0h
004h, 2,090h,04Ch
00Dh, 1,0FFh
016h, 1,053h
018h, 3,002h,001h,00Fh
020h, 1,000h
023h, 2,000h,000h
034h, 8,000h,003h,000h,003h,001h,002h,000h,0C2h
03Dh, 4,050h,050h,000h,067h
042h, 1,01Ch
04Ah, 2,043h,0F8h
04Eh, 7,028h,0FCh,000h,024h,014h,008h,008h
056h,13,000h,018h,028h,034h,044h,056h,06Eh,080h,0A4h,0C2h,0D6h,0E8h,0F4h
065h,12,00Fh,038h,008h,000h,01Fh,01Fh,01Fh,01Fh,01Fh,01Fh,01Fh,01Fh
07Ah,17,039h,03Bh,03Ah,036h,03Ch,03Ch,03Ah,03Ch,03Ch,03Ch,03Ah,03Ch,038h
03Ah,031h,03Ah,082h
08Dh,22,08Ah,090h,096h,09Ch,0A4h,0AAh,0B0h,0B6h,0BCh,0C4h,0CAh,0D0h,0D6h
0DCh,0E4h,0EAh,0F0h,0F2h,0F4h,0F6h,0F8h,0FAh
0A9h, 1,02Bh
0ABh, 3,02Eh,000h,050h
0AFh, 1,070h
0B2h, 4,03Ch,068h,049h,070h
0B7h,21,032h,000h,00Eh,0F8h,00Ch,07Ah,040h,000h,000h,010h,044h,064h,052h
012h,001h,0D7h,004h,002h,024h,002h,024h
0D4h, 5,004h,004h,008h,00Ah,010h
016h, 1,0F7h
0DEh, 2,002h,024h
016h, 1,053h
0E1h, 1,034h
0FFh, 1,00Fh
003h, 1,002h ;<-- bank maybe?
005h, 2,06Dh,004h
011h, 4,004h,048h,004h,048h
016h, 2,00Ch,0D8h
019h, 2,00Ch,0D8h
01Eh, 6,002h,024h,070h,000h,001h,06Eh
026h, 7,008h,00Fh,00Fh,006h,0FFh,0FFh,003h
02Eh,19,07Eh,088h,074h,07Eh,008h,010h,080h,008h,084h,078h,001h,003h,00Ah
025h,060h,0B0h,006h,000h,000h
042h, 7,080h,010h,010h,010h,040h,080h,0FFh
04Ah,30,000h,000h,001h,0E5h,001h,0E0h,000h,070h,002h,0F0h,000h,02Eh,001h
0F3h,000h,005h,000h,000h,001h,000h,000h,0C0h,000h,026h,000h,01Ch
000h,0B3h,000h,086h
069h,36,000h,000h,006h,014h,014h,01Fh,000h,000h,000h,000h,000h,01Fh,000h
000h,010h,010h,010h,01Fh,000h,000h,004h,004h,004h,01Fh,000h,000h
000h,000h,000h,01Fh,000h,000h,010h,010h,010h,01Fh
095h, 1,084h
097h,18,002h,000h,0FFh,0FFh,000h,0FFh,0FFh,000h,000h,0FFh,0FFh,000h,0FFh
0FFh,000h,0F8h,014h,010h
0AAh,13,044h,098h,08Ch,09Ch,048h,08Ch,08Ah,09Ch,046h,02Ah,080h,008h,026h
0B8h, 8,02Ah,084h,000h,026h,02Ah,080h,008h,020h
0C1h,10,038h,020h,01Fh,01Dh,034h,020h,01Fh,01Dh,045h,05Dh
0CCh, 2,020h,020h
0D0h, 3,080h,000h,0FFh
003h, 1,000h ;<-- bank maybe?
013h, 2,000h,04Ch
01Dh, 2,000h,04Ch
015h, 2,001h,05Fh
055h, 2,001h,05Eh
031h, 6,006h,068h,00Ch,005h,004h,047h
047h, 2,000h,003h
04Ah, 3,0A0h,000h,003h
04Fh, 2,000h,003h
059h, 2,000h,001h
05Fh, 2,000h,001h
066h, 1,09Eh
06Eh, 2,07Fh,003h
075h, 1,050h
07Ah, 2,000h,001h
07Eh, 1,020h
082h, 1,038h
084h,14,003h,040h,003h,040h,000h,000h,040h,003h,0FFh,002h,008h,020h,018h,006h
093h,11,020h,040h,040h,01Fh,002h,000h,000h,000h,000h,000h,000h
003h, 1,001h ;<-- bank maybe?
00Fh, 1,0C9h ;or, for Device E0h: 00Fh, 1,0C8h
052h, 3,004h,008h,008h ;or, for Device E0h: N/A
003h, 1,002h ;<-- bank maybe?
026h, 1,008h ;or, for Device E0h: 026h, 1,000h
0CCh, 2,0C0h,0C0h ;or, for Device E0h: N/A
0B4h, 1,000h ;or, for Device E0h: N/A
0B6h, 1,026h ;or, for Device E0h: N/A
0B9h, 3,000h,008h,026h ;or, for Device E0h: N/A
0BDh, 1,000h ;or, for Device E0h: N/A
026h, 1,008h ;or, for Device E0h: N/A
003h, 1,001h ;<-- bank maybe?
02Dh, 1,0FFh
004h, 1,020h
unknown_cam_type_code_list_activate:
003h, 1,002h ;<-- bank maybe?
0A7h, 1,014h
003h, 1,001h ;<-- bank maybe?
004h, 1,0A0h
004h, 1,090h
02Dh, 1,000h
004h, 1,098h
Random Note
This info is probably not really helpful, but the DSi firmware contains code
for setting Register C1h..C9h (within unknown bank) to one of the following
twelve settings.
C1h, 8,038h,030h,01Fh,01Fh,02Ch,030h,01Fh,01Fh
C1h, 8,038h,030h,01Fh,01Fh,038h,030h,01Fh,01Fh
C1h, 8,02Ch,030h,01Fh,01Fh,02Ch,030h,01Fh,01Fh
C1h, 8,02Ch,030h,01Fh,01Fh,02Ch,030h,01Fh,01Fh
C1h, 8,02Ch,030h,01Fh,01Fh,02Ch,030h,01Fh,01Fh
C1h, 8,02Ch,030h,01Fh,01Fh,02Ch,030h,01Fh,01Fh
C1h, 8,030h,028h,018h,018h,034h,028h,008h,018h
C1h, 8,030h,028h,018h,018h,030h,028h,008h,018h
C1h, 8,028h,028h,018h,018h,028h,028h,008h,018h
C1h, 8,028h,028h,018h,018h,028h,028h,008h,018h
C1h, 8,028h,028h,018h,018h,028h,028h,008h,018h
C1h, 8,028h,028h,018h,018h,028h,028h,008h,018h
DSi Cameras
-----------
Camera registers
Cameras are controlled and initialized via I2C bus (on ARM7 side).
--> DSi I2C Bus
The actual camera data transfers are done with below registers (on ARM9 side).
Camera Detection
There are four possible I2C camera devices, although usually only two of them
should be installed. The firmware detects the cameras by reading their Chip ID
registers (but without actually insisting on any specific ID values, instead,
it's merely checking the ACK error flag in the I2C register - if all four
devices are returning ACK=okay, then it's actually initializing all four
cameras; though unknown if the GUI is actually supporting that many cameras).
Camera Init
[4004004h]=[4004004h] OR 0004h ;SCFG_CLK, CamInterfaceClock = ON
[4004200h]=0000h, delay(1Eh) ;CAM_MCNT, Camera Module Control
[4004004h]=[4004004h] OR 0100h, delay(1Eh) ;SCFG_CLK, CamExternal Clock = ON
[4004200h]=0022h, delay(2008h) ;CAM_MCNT, Camera Module Control
[4004004h]=[4004004h] AND NOT 0100h ;SCFG_CLK, CamExternal Clock = OFF
[4004202h]=[4004202h] AND NOT 8000h ;CAM_CNT, allow changing params
[4004202h]=[4004202h] OR 0020h ;CAM_CNT, flush data fifo
[4004202h]=([4004202h] AND NOT 0300h) OR 0200h
[4004202h]=[4004202h] OR 0400h
[4004202h]=[4004202h] OR 0800h ;CAM_CNT, irq enable
[4004004h]=[4004004h] OR 0100h, delay(14h) ;SCFG_CLK, CamExternal Clock = ON
issue "aptina_code_list_init" via I2C bus on ARM7 side
[4004004h]=[4004004h] AND NOT 0100h ;SCFG_CLK, CamExternal Clock = OFF
[4004004h]=[4004004h] OR 0100h, delay(14h) ;SCFG_CLK, CamExternal Clock = ON
issue "aptina_code_list_activate" via I2C bus on ARM7 side
[4004202h]=[4004202h] OR 2000h ;CAM_CNT, enable YUV-to-RGB555
[4004202h]=([4004202h] AND NOT 000Fh) OR 0003h
[4004202h]=[4004202h] OR 0020h ;CAM_CNT, flush data fifo
[4004202h]=[4004202h] OR 8000h ;CAM_CNT, start transfer
[4004120h]=04004204h ;NDMA1SAD, source CAM_DTA
[4004124h]=0xxxxxxxh ;NDMA1DAD, dest RAM/VRAM
[4004128h]=00006000h ;NDMA1TCNT, len for 256x192 total
[400412Ch]=00000200h ;NDMA1WCNT, len for 256x4 blocks
[4004130h]=00000002h ;NDMA1BCNT, timing interval or so
[4004138h]=8B044000h ;NDMA1CNT, start camera DMA
Specifications
The Nintendo DSi contains two cameras. The cameras can be used in the Nintendo
DSi Camera application or DSi games that are compatible.
640*480 VGA (0.3 Megapixel)
No zoom and no flash.
Photos saved in JPG format (saved in DCIM/ folder on the SD/SDHC or in the
internal memory).
Camera Applications
Nintendo DSi Camera
System Menu (can take photos, and can display JPG's with "Star" sticker)
Flipnote (doesn't directly support camera hardware, but can import JPG's)
Camera Games
Asphalt 4 : Elite Racing (DSiWare)
Brain Challenge (DSiWare)
Classic Word Games
Cooking Coach
Pop SuperStar : Road To Celebrity (DSiWare)
Real Football 2009 (DSiWare)
WarioWare : Snapped! (DSiWare)
iCarly
Pokemon Black,White (2010,JP)
Castle of Magic (DSiWare)
Photo Dojo (DSiWare)
System Flaw (mis-uses camera as gyro sensor)
I/O Ports
--> DSi SD/MMC I/O Ports: Command/Param/Response/Data
--> DSi SD/MMC I/O Ports: Interrupt/Status
--> DSi SD/MMC I/O Ports: Control Registers
--> DSi SD/MMC I/O Ports: Unknown/Unused Registers
--> DSi SD/MMC I/O Ports: Misc
SD/MMC Protocol
--> DSi SD/MMC Protocol: Command/Response/Register Summary
--> DSi SD/MMC Protocol: General Commands
--> DSi SD/MMC Protocol: Block Read/Write Commands
--> DSi SD/MMC Protocol: Special Extra Commands
--> DSi SD/MMC Protocol: CSR Register (32bit Card Status Register)
--> DSi SD/MMC Protocol: SSR Register (512bit SD Status Register)
--> DSi SD/MMC Protocol: OCR Register (32bit Operation Conditions Register)
--> DSi SD/MMC Protocol: CID Register (128bit Card Identification)
--> DSi SD/MMC Protocol: CSD Register (128bit Card-Specific Data)
--> DSi SD/MMC Protocol: EXT_CSD Register (4096bit Extended CSD Register) (MMC)
--> DSi SD/MMC Protocol: RCA Register (16bit Relative Card Address)
--> DSi SD/MMC Protocol: DSR Register (16bit Driver Stage Register) (Optional)
--> DSi SD/MMC Protocol: SCR Register (64bit SD Card Configuration Register)
--> DSi SD/MMC Protocol: PWD Register (128bit Password plus 8bit Password len)
--> DSi SD/MMC Protocol: State
--> DSi SD/MMC Protocol: Signals
SDIO Protocol
--> DSi SDIO Special SDIO Commands
--> DSi SDIO Memory and I/O Maps
--> DSi SDIO Common Control Registers (CCCR)
--> DSi SDIO Function Basic Registers (FBR)
--> DSi SDIO Card Information Structures (CIS)
The DSi is using SDIO for the new DSi Wifi interface,
--> DSi Atheros Wifi SDIO Interface
--> DSi Atheros Wifi Internal Hardware
Pinouts
--> AUX DSi SD/MMC Pin-Outs
DATA16 vs DATA32
Data can be transferred in 16bit or 32bit units (as selected in DATA_CTL.bit1
and DATA32_IRQ.bit1). There are separate data, block len, and block count
registers for 16bit and 32bit mode. 16bit mode uses two FIFOs (each with
200h-byte capactity). 32bit adds another FIFO (also with 200h-byte capacity):
.----------. CPU
o--| FIFO16_A |--o o---------------- 4004830h
serial '----------' \ 16bit
SD/MMC ---o o---------o
bus \ .----------. \ .--------. CPU/NDMA
o--| FIFO16_B |--o o---| FIFO32 |--- 400490Ch
'----------' '--------' 32bit
The 32bit mode is some odd patchwork, apparently Nintendo/Toshiba considered it
easier to add an extra 32bit FIFO (rather than to figure out how to add native
32bit access to Toshiba's original 16bit chip design).
The DSi firmware does use both 32bit and 16bit mode once and then; 32bit mode
can be faster, and it's required for NDMA transfers (which don't support
16bit).
40048D8h/4004AD8h - SD_DATA_CTL
15-13 Always zero
12 Unknown (usually 1) (R?)
11-6 Always zero
5 Unknown (read/write-able) (usually 0) (R/W)
4 Unknown (usually 1) (R?)
3-2 Always zero
1 Select 16bit/32bit Data Mode (0=DATA16, 1=DATA32, see 4004900h) (R/W)
0 Always zero
DATA32 mode requires setting both 40048D8h.bit1 and 4004900h.bit1. For DATA16
mode, both bits should be zero (though DATA16 seems to be also working the same
way when only either of the bits is zero).
All SD/MMC IRQs are triggering IF2.8, CardIRQ does ADDITIONALLY trigger IF2.9
All SDIO IRQs are triggering IF2.10, CardIRQ does ADDITIONALLY trigger IF2.11?
4004900h/4004B00h - SD_DATA32_IRQ
15-13 Always zero
12 TX32RQ IRQ Enable (0=Disable, 1=Enable) (R/W)
11 RX32RDY IRQ Enable (0=Disable, 1=Enable) (R/W)
10 Clear FIFO32 (0=No change, 1=Force FIFO32 Empty) (W)
9 TX32RQ IRQ Flag (0=IRQ, 1=No) (0=FIFO32 Empty) (R)
8 RX32RDY IRQ Flag (0=No, 1=IRQ) (1=FIFO32 Full) (R)
7-2 Always zero
1 Select 16bit/32bit Data Mode (0=DATA16, 1=DATA32, see 40048D8h) (R/W)
0 Always zero
Bit8,9 are extra IRQ flags, the flags get set ONLY in DATA32 mode (not in
DATA16 mode).
Bit8,9 are somewhat edge-triggered (setting the IF2 bit only on NoIRQ-to-IRQ
transitions; whilst Disable-to-Enable transitions don't trigger IF2).
Bit8,9 don't need to be acknowledged, they are automatically switched to "No
IRQ" by hardware (when reading/writing DATA32_FIFO, ie. when the FIFO is no
longer empty/full).
IRQ Edge-Triggering
One nasty "feature" for both IRQ_STATUS and DATA32_IRQ is that the interrupts
are edge-triggered (IF2.bit8 gets set only on No-IRQ-to-IRQ transitions) (IF2
can be acknowledged even if IRQ(s) are still requested, which would mean that
those IRQ(s) would get lost). Workaround would be:
- first acknowledge IF2.bit8 (must be done before next step)
- then check for pending IRQs in IRQ_STATUS and DATA32_IRQ, and process
all of them
Ie. if you would process only a single IRQ, then any other IRQs would get lost.
For IRQ_STATUS, one could also force unprocessed IRQs to re-trigger IF2 by
temporarily disabling IRQ_MASK bits (disable-to-enable for pending IRQs is also
edge-triggering IF2). That trick works for IRQ_STATUS only, not for DATA32_IRQ.
4004802h/4004A02h - SD_CARD_PORT_SELECT
15-11 Always zero
10 Unknown (should be set on write) (reads as zero) (1=CardIRQ off!) (W)
9-8 Unknown (Always 2 for SD/4004802h, always 1 for SDIO/4004A02h) (R)
7-4 Always zero
3-1 Unknown (read/write-able) (R/W)
0 Port Select (0=SD Card Slot, 1=Onboard eMMC) (for SDIO: Unknown) (R/W)
Known written values are 0400h and 0401h for SD/MMC. The register is left
uninitialized for SDIO.
4004808h/4004A08h - SD_STOP_INTERNAL_ACTION
15-9 Always zero
8 Auto-Stop (1=Automatically send CMD12 after BLK_COUNT blocks) (R/W)
7-1 Always zero
0 Unknown (firmware often clears this bit, but never sets it?) (R/W)
Existing code does set bit8 (prior to changing SD_DATA16_BLK_COUNT).
Existing code does clear bit0 (alongsides with IRQ enable/acknowledge or so).
Note: Bit8 MUST be also set for SDIO with multiple blocks (although SDIO
doesn't literally have CMD12).
Timeout Notes
Timeouts are counted in SDCLK units (the CLK-Pin rate selected in
SD_CARD_CLK_CTL register). For Response-Timeouts, the timeout is fixed: Around
290h SDCLK's (preceeded by 30h SDCLK's for sending the command). For
Data-Timeouts, the timeout can be selected in SD_CARD_OPTION.bit4-7, which is
apparently what toshiba tried to describe as "RTO" bits. Values 0..14 select
timeout "2000h SHL 0..14 SDCLK's" and value 15 selects "100h SDCLK's" (that,
oddly, resulting in Data-timeout getting triggered before Response-timeout,
which is rather nonsense since it's opposite of the actual transfer order).
For data/read, the timeout starts counting after transferring Command+Response.
For data/write it starts after transferring Command+Response+DataBlock. The
maximum duration for data timeouts (with RTO=14) would be around 8 seconds (at
SDCLK=HCLK/2), or up to about 30 minutes (at HCLK/512).
One odd effect is that Response-Timeouts can occur (after 290h SDCLKs, and
recursing the selected SDCLK=HCLK/n rate) even if SDCLK is stopped via
SD_CARD_CLK_CTL.Bit8 (ie. the selected clock is kept running internally, and
only the CLK-Pin output is forced LOW when Bit8=0).
Toshiba Chips
The DSi SDIO/MMC port addresses and status bits appear to be identical to those
on Toshiba SD/MMC/SDIO controller chips.
One small difference is that the DSi can set SD_IRQ_MASK.Bit27 (which wasn't
used on (older) Toshiba chips). The Toshiba chips seem to include additional
"CNF" configuration registers (which seem to be missing on DSi).
Chip Year Pages Features
Toshiba TC6371AF 2000-2002 58 SD/MMC/Smart/PCI (old/basic specs, no SDIO)
Toshiba TC6380AF 2001-2002 90 SD/MMC/SDIO/SmartMedia
Toshiba TC6387XB 2001-2002 62 SD/MMC/SDIO/SDLED
Toshiba TC6391XB 2002 202 SD/MMC/SDIO/SmartMedia/USB/LCD/etc.
Toshiba TC6393XB ? ;\unknown features, no datasheet exists (the chips
Toshiba T7L66XB ? ;/are mentioned in tmio_mmc.h and tmio_mmc.c source)
Related source code:
https://github.com/torvalds/linux/tree/master/drivers/mmc/host/
(see files toshsd.* and tmio_mmc.*)
(that just as historic references, meanwhile there's better source code
around, written specifically for DSi and 3DS hardware)
The TC6380AF/TC6387XB/TC6391XB datasheets are more or less identical on the
SD/MMC/SDIO section, TC6387XB is probably the best reference because it doesn't
contain offtopic extras like SmartMedia, USB, LCD, etc. The datasheets contain
I/O Maps with port addresses, but no description tables for the bits in those
ports (though some bits are mentioned here and there in the text, scattered
across many different pages, and other bits are left completely undocumented).
Card Registers
CSR 32bit sd/mmc spi Card Status: command error & state information
OCR 32bit sd/mmc spi Operation Conditions Register
CID 128bit sd/mmc spi Card Identification
CSD 128bit sd/mmc spi Card-Specific Data (CSD Version 1.0 and 2.0)
RCA 16bit sd/mmc Relative Card Address (not used in SPI mode)
DSR 16bit sd/mmc spi Driver Stage Register (optional)
SSR 512bit sd spi SD Card Status Register: Extended status field
SCR 64bit sd spi SD Card Configuration Register
EXT_CSD 4096bit mmc spi MMC Extended CSD Register (status & config)
PWD 128bit sd/mmc spi Password (Card Lock) (max 16 bytes)
PWD_LEN 8bit sd/mmc spi Password Length (0..16 max) (0=no password)
Misnamed Commands
Official command names include various SEND_xxx commands, which are misleading
because they don't indicate if they "send" information <to> or <from> the card
(or both). Better naming would be GET_xxx, SET_xxx, or GET_SET_xxx.
Official Name Renamed
ALL_SEND_CID ALL_GET_CID
SEND_CID GET_CID
SEND_CSD GET_CSD
SEND_STATUS GET_STATUS
SEND_RELATIVE_ADDR GET_RELATIVE_ADDR
SEND_SCR GET_SCR
SEND_EXT_CSD GET_EXT_CSD
SEND_WRITE_PROT GET_WRITE_PROT
SEND_WRITE_PROT_TYPE GET_WRITE_PROT_TYPE
SEND_NUM_WR_BLOCKS GET_NUM_WR_BLOCKS
SEND_IF_COND SET_IF_COND ;-to card
SEND_TUNING_BLOCK SET_TUNING_BLOCK ;-to card
SEND_OP_COND ...
SD_SEND_OP_COND ...
Other misnamed commands include SET_BLOCKLEN occassionally spelled
SET_BLOCK_LEN in SD specs. SELECT_DESELECT_CARD is officially spelled
SELECT/DESELECT_CARD.
Note
All future reserved commands shall have a codeword length of 48 bits, as well
as their responses (if there are any).
CMD32-34,37 - SPI - MMC - Reserved for compatibility with older MMC cards
MMC only. Unknown, maybe also Erase related?
CMD34-35 - SD - Reserved
Reserved for each command system set by switch function command (CMD6).
Detailed definition is referred to each command system specification.
Maybe related to above "function group 5..6"?
CSR Card Status Register (full 32bit, as returned in SD Mode Response: R1)
Bit Typ Clr Identifier Meaning
31 ERX C OUT_OF_RANGE (1=Command's argument was out of range)
30 ERX C ADDRESS_ERROR (1=Misaligned address/block len mismatch)
29 ERX C BLOCK_LEN_ERROR (1=Wrong block length, bytelen mismatch)
28 ER C ERASE_SEQ_ERROR (1=Error in erase command sequence)
27 ERX C ERASE_PARAM (1=Wrong erease selection of write-blocks)
26 ERX C WP_VIOLATION (1=Write failed due to write-protection)
25 SX A CARD_IS_LOCKED (1=Card is locked by the host)
24 ERX C LOCK_UNLOCK_FAILED (1=Lock/unlock sequence or password error)
23 ER B COM_CRC_ERROR (1=CRC check of previous command failed)
22 ER B ILLEGAL_COMMAND (1=Command not legal for the card state)
21 ERX C CARD_ECC_FAILED (1=Internal error correction failed)
20 ERX C CC_ERROR (1=Internal card controller error)
19 ERX C ERROR (1=General error, or Unknown error)
18 - - Reserved (eMMC: UNDERRUN)
17 - - Reserved (eMMC: OVERRUN) (eSD: DEFERRED_RESPONSE)
16 ERX C CSD_OVERWRITE (1=read-only CSD section doesn't match card
content, or attempted to reverse the
Copy/WP bits)
15 ERX C WP_ERASE_SKIP (1=partial erase error due to write-protect)
14 SX A CARD_ECC_DISABLED (1=Internal error correction wasn't used)
13 SR C ERASE_RESET (1=Erase sequence was aborted)
12-9 SX B CURRENT_STATE (00h..0Fh=state, see below)
8 SX A READY_FOR_DATA (1=Ready/buffer is empty)
7 EX C SWITCH_ERROR (1=SWITCH command refused, MMC only)
6 - - Reserved/Unspecified (description is left blank)
5 SR C APP_CMD (1=Card will expect ACMD)
4 - - Reserved for SD I/O Card
3 ER C AKE_SEQ_ERROR (1=Authentication Sequence Error)
2 - - Reserved for application specific commands
1-0 - - Reserved for manufacturer test mode
Values for CURRENT_STATE (bit12-9):
These bits indicate the OLD state of card when receiving the command,
(ie. if the command does change the state, then the NEW state won't be
seen until the NEXT command returns the new updated status bits)
00h = idle
01h = ready
02h = ident
03h = stby
04h = tran ;<-- normal state (when waiting for read/write commands)
05h = data ;data read (CMD8,CMD11,CMD17,CMD18,CMD30,CMD56/R)
06h = rcv ;data write (CMD20?,CMD24,CMD25,CMD26,CMD27,CMD42,CMD56/W)
07h = prg ;erase/wprot (CMD6,CMD28,CMD29,CMD38)
08h = dis
09h = btst ;bus test write (CMD19, MMC only)
0Ah = slp ;sleep (CMD5, MMC only)
0Bh-0Eh = reserved
0Fh = reserved for I/O mode (SDIO-only devices, without SD-memory)
N/A = ina ;inactive (CMD15) (card is killed, and can't send status)
N/A = irq ;interrupt mode (CMD40, MMC only)
N/A = pre ;pre-idle (MMC only)
Type aka Typ column (in above table):
E: Error bit.
S: Status bit.
R: Flag may get set within response of current command.
X: Flag may get set within response of NEXT command (with R1 response)
Clear Condition aka Clr column (in above table):
A: According to the card current state.
B: Always related to the previous command. Reception of a valid command
will clear it (with a delay of one command).
C: Clear by read.
CMD1 (MMC) and ACMD41 (SD) are intended to exchange OCR information. That is,
the OCR parameter bits should indicate the host conditions (eg. for DSi:
40100000h, ie. bit20=3.3V supply, and bit30=HCS support for High Capacity carts
with more than 2GBytes). The OCR response may then return something like
007f8000h when busy, and 807f8000h when ready (bit20 indicating the voltage
being actually supported, bit30 indicating if it's High Capacity card, and
bit31 indicating if the card is ready & switched from "idle" to "ready" state).
Cards do usually send at least one response with bit31=0 (busy), one should
repeat sending CMD1/ACMD51 until bit31=1 (ready).
Note: All card(s) on the bus will respond to CMD1/ACMD51: with the response
bits ANDed together (thus returning nonsense in bit30=HCS when actually sharing
the same bus for multiple cards).
Note: The card switches to "ina" state if the voltage in param bits isn't
supported.
OCR register
The 32-bit operation conditions register stores the VDD voltage profile of the
non UHS-II card and VDD1 voltage profile of the UHS-II card. Additionally, this
register includes status information bits. One status bit is set if the card
power up procedure has been finished. This register includes another status bit
indicating the card capacity status after set power up status bit. The OCR
register shall be implemented by the cards.
The 32-bit operation conditions register stores the VDD voltage profile of the
card.
Bit 7 of OCR is newly defined for Dual Voltage Card and set to 0 in default. If
a Dual Voltage Card does not receive CMD8, OCR bit 7 in the response indicates
0, and the Dual Voltage Card which received CMD8, sets this bit to 1.
31 Card power up status bit (0=Busy, 1=Ready)
30 Card Capacity Status (CCS) (valid only if above Bit31 indicates Ready)
CCS=0 SDSC Card (addressed in 1-byte units) ;MMC max 2GB
CCS=1 SDHC/SDXC card (addressed in 512-byte units) ;MMC > 2GB
29 UHS-II Card Status
28-25 Reserved
24 Switching to 1.8V Accepted (S18A) (Only UHS-I card supports this bit)
23 3.5-3.6 ;\
22 3.4-3.5 ;
21 3.3-3.4 ;
20 3.2-3.3 ;<-- this used by DSi ;
19 3.1-3.2 ; VDD Voltage Window
18 3.0-3.1 ;
17 2.9-3.0 ;
16 2.8-2.9 ;
15 2.7-2.8 ;
14-8 Reserved (MMC: 2.0V .. 2.6V) ; ;<-- uh, probably in opposite order?
7 Reserved for Low Voltage Range ;
6-4 Reserved ;
3-0 Reserved ;/
The supported voltage range is coded as shown in Table 5-1. A voltage range is
not supported if the corresponding bit value is set to LOW. As long as the card
is busy, the corresponding bit (31) is set to LOW.
VDD Voltage Window of OCR indicates VDD1 voltage range in case of UHS-II Card.
UHS-II Card Status bit is added in Bit 29 to indicate whether the card supports
UHS-II Interface. Non UHS-II Card sets Bit 29 to 0 and UHS-II Card sets Bit 29
to 1. This bit is not affected by whether VDD2 is supplied or not.
CID register
The Card IDentification (CID) register is 128 bits wide. It contains the card
identification information used during the card identification phase. Every
individual Read/Write (RW) card shall have a unique identification number.
For SD Cards (short product name, but bigger date field, 2000..2255?):
Bit Siz Field Name
127-120 8 MID Manufacturer ID (binary) ;\assigned by SD-3C, LLC
119-104 16 OID OEM/Application ID (ASCII) ;/
103-64 40 PNM Product name (ASCII)
63-56 8 PRV Product revision (BCD, 00h-99h) (eg 62h = rev 6.2)
55-24 32 PSN Product serial number (32bit)
23-20 4 - Reserved (zero)
19-8 12 MDT Manufacturing date (yymh) (m=1..12, yy=0..255?; +2000)
7-1 7 CRC CRC7 checksum
0 1 1 Stop bit (always 1)
For MMC Cards (smaller date field, range 1997..2012 only):
Bit Siz Field Name
127-120 8 MID Manufacturer ID (binary) ;\assigned by MMCA
119-104 16 OID OEM/Application ID (binary) ;/ ... or ...
127-120 8 MID Manufacturer ID (binary) ;\assigned by MMCA/JEDEC
119-114 6 - Reserved (0) ;
113-112 2 CBX Device (0=Card, 1=BGA, 2=POP) ;
119-104 8 OID OEM/Application ID (binary) ;/
103-56 48 PNM Product name (ASCII)
55-48 8 PRV Product revision (BCD, 00h-99h) (eg 62h = rev 6.2)
47-16 32 PSN Product serial number (32bit)
15-8 8 MDT Manufacturing date (myh) (m=1..12, y=0..15; +1997)
7-1 7 CRC CRC7 checksum
0 1 1 Stop bit (always 1)
Known CID's for DSi eMMC chips (excluding CRC in LSB, padded 00 in MSB)
MY ss ss ss ss 03 4D 30 30 46 50 41 00 00 15 00 ;DSi Samsung KMAPF0000M-S998
MY ss ss ss ss 32 57 37 31 36 35 4D 00 01 15 00 ;DSi Samsung KLM5617EFW-B301
MY ss ss ss ss 30 36 35 32 43 4D 4D 4E 01 FE 00 ;DSi ST NAND02GAH0LZC5 rev30
MY ss ss ss ss 31 36 35 32 43 4D 4D 4E 01 FE 00 ;DSi ST NAND02GAH0LZC5 rev31
MY ss ss ss ss 03 47 31 30 43 4D 4D 00 01 11 00 ;3DS whatever chiptype?
MY ss ss ss ss 07 43 59 31 47 34 4D 00 01 15 00 ;3DS Samsung KLM4G1YE0C-B301
See also:
--> DSi Console IDs
CSD Register
The types of the entries in the table below are coded as follows: R=readable,
W(1)=writable once, W=multiple writable.
Bit Siz Type Name Field Value
127-126 2 R CSD structure version CSD_STRUCTURE 00b
125-122 4 R MMC: System spec version SPEC_VERS ..
125-122 4 R SD: reserved - 0000b
121-120 2 R reserved - 00b
119-112 8 R data read access-time-1 TAAC xxh
111-104 8 R data read access-time-2 NSAC xxh
103-96 8 R max data transfer rate TRAN_SPEED 32h or 5Ah
95-84 12 R card command classes CCC 01x110110101b
83-80 4 R max read data block len READ_BL_LEN xh
79 1 R partial blocks for read allowed READ_BL_PARTIAL 1b
78 1 R write block misalignment WRITE_BLK_MISALIGN xb
77 1 R read block misalignment READ_BLK_MISALIGN xb
76 1 R DSR implemented DSR_IMP xb
75-74 2 R reserved - 00b
73-70 4 R SDHC/SDXC: reserved - 0000b
69-48 22 R SDHC/SDXC: device size C_SIZE ...
47 1 R SDHC/SDXC: reserved - 0
73-62 12 R MMC/SDSC: device size C_SIZE xxxh
61-59 3 R MMC/SDSC: max read current @VDD min VDD_R_CURR_MIN xxxb
58-56 3 R MMC/SDSC: max read current @VDD max VDD_R_CURR_MAX xxxb
55-53 3 R MMC/SDSC: max write current @VDD min VDD_W_CURR_MIN xxxb
52-50 3 R MMC/SDSC: max write current @VDD max VDD_W_CURR_MAX xxxb
49-47 3 R MMC/SDSC: device size multiplier C_SIZE_MULT xxxb
46-42 5 R MMC: Erase Group Size ERASE_GRP_SIZE ..
41-37 5 R MMC: Erase Group Multiplier ERASE_GRP_MULT ..
36-32 5 R MMC: Write Protect Grp Size WP_GRP_SIZE ..
46 1 R SD: erase single block enable ERASE_BLK_EN xb
45-39 7 R SD: erase sector size SECTOR_SIZE xxxxxxxb
38-32 7 R SD: write protect group size WP_GRP_SIZE xxxxxxxb
31 1 R write protect group enable WP_GRP_ENABLE xb
30-29 2 R MMC: Manufacturer default ECC DEFAULT_ECC ..
30-29 2 R SD: reserved (do not use) - 00b
28-26 3 R write speed factor R2W_FACTOR xxxb
25-22 4 R max write data block len WRITE_BL_LEN xxxxb
21 1 R partial blocks for write allowed WRITE_BL_PARTIAL xb
20-17 4 R reserved - 0000b
16 1 R SD: reserved - 0
16 1 R MMC: Content Protection Applicat. CONTENT_PROP_APP ..
15 1 R/W(1) File format group FILE_FORMAT_GRP xb
15 1 R SDHC/SDXC: reserved (FILE_FORMAT_GRP)0
14 1 R/W(1) copy flag COPY xb
13 1 R/W(1) permanent write protection PERM_WRITE_PROTECT xb
12 1 R/W temporary write protection TMP_WRITE_PROTECT xb
11-10 2 R/W(1) File format FILE_FORMAT xxb
11-10 2 R SDHC/SDXC: reserved (FILE_FORMAT) 00b
9-8 2 R/W MMC: ECC Code ECC ..
9-8 2 R/W SDSC: reserved, R/W - 00b
9-8 2 R SDHC/SDXC: reserved, R - 00b
7-1 7 R/W CRC CRC xxxxxxxb
0 1 - not used, always '1' - 1b
Known CSD's for DSi eMMC chips (excluding CRC in LSB, padded 00 in MSB)
8 16 24 32 40 48 56 64 72 80 88 96 104112120pad ;<--bit numbers
40 40 96 E9 7F DB F6 DF 01 59 0F 2A 01 26 90 00 ;DSi Samsung KMAPF0000M-S998
40 40 8E FF 03 DB F6 DF 01 59 0F 32 01 27 90 00 ;DSi Samsung KLM5617EFW-B301
00 40 8A E0 BF FF 7F F5 80 59 0F 32 01 2F 90 00 ;DSi ST NAND02GAH0LZC5 rev30
00 40 8A E0 BF FF 7F F5 80 59 0F 32 01 2F 90 00 ;DSi ST NAND02GAH0LZC5 rev31
? 00 ;3DS whatever chiptype?
40 40 8A E7 FF DB F6 6B 02 5A 0F 32 01 27 D0 00 ;3DS Samsung KLM4G1YE0C-B301
That is, differences are:
bit name KMAPF0000M KLM5617EFW NAND02GAH0LZC5 KLM4G1YE0C
126-127 CSD_STRUCTURE 2=v1.2 2=v1.2 2=v1.2 3=SeeEXT_CSD
112-119 TAAC 26h=1.5ms 27h=15ms 2Fh=20ms 27h=15ms
96-103 TRAN_SPEED 2Ah=20MHz 32h=25MHz 32h=25MHz 32h=25MHz
80-83 READ_BL_LEN 9=512 9=512 9=512 0Ah=1024
79 READ_BL_PARTIAL 0=No(?) 0=No(?) 1=Yes 0=No(?)
62-73 C_SIZE 77Fh=240MB 77Fh=240MB 3D5h=245.5MB 9AFh=1240MB
59-61 VDD_R_CURR_MIN 6=60mA 6=60mA 7=100mA 6=60mA
56-58 VDD_R_CURR_MAX 6=80mA 6=80mA 7=200mA 6=80mA
53-55 VDD_W_CURR_MIN 6=60mA 6=60mA 7=100mA 6=60mA
50-52 VDD_W_CURR_MAX 6=80mA 6=80mA 7=200mA 6=80mA
47-49 C_SIZE_MULT 6=256 6=256 7=512 7=512
42-46 ERASE_GRP_SIZE 1Fh=32x32 00h=1x32 1Fh=32x32 1Fh=32x32
32-36 WP_GRP_SIZE 09h=10 1Fh=32 00h=1 07h=8
26-28 R2W_FACTOR 05h=32x 03h=8x 02h=4x 02h=4x
14 COPY 1=Copy 1=Copy 0=Original 1=Copy
Not sure if that values are really correct, or if the manufacturer has screwed
up some bits. TAAC being 10x slower in newer chips looks weird, 20MHz would be
for 1bit MCC (whilst 4bit MMCplus/MMCmobile should support 26MHz), erase group
32x32x512 bytes would somewhat require 512Kbyte clusters, write protect group
size 10 decimal looks a bit odd (though it could be true), and, well, faster
writing in newer chips looks plausible.
TAAC
Defines the asynchronous part of the data access time.
7 Reserved
6-3 Time value
0=reserved, 1=1.0, 2=1.2, 3=1.3, 4=1.5, 5=2.0, 6=2.5, 7=3.0,
8=3.5, 9=4.0, A=4.5, B=5.0, C=5.5, D=6.0, E=7.0, F=8.0
2-0 Time unit
0=1ns, 1=10ns, 2=100ns, 3=1us, 4=10us, 5=100us, 6=1ms, 7=10ms
NSAC
Defines the worst case for the clock-dependent factor of the data access time.
The unit for NSAC is 100 clock cycles. Therefore, the maximal value for the
clock-dependent part of the data access time is 25500 clock cycles.
The total access time NAC is the sum of TAAC and NSAC. It should be computed by
the host for the actual clock rate. The read access time should be interpreted
as a typical delay for the first data bit of a data block or stream.
TRAN_SPEED
The following table defines the maximum data transfer rate PER ONE data line:
7 Reserved
6-3 Time value
0=reserved, 1=1.0, 2=1.2, 3=1.3, 4=1.5, 5=2.0, 6=2.5, 7=3.0,
8=3.5, 9=4.0, A=4.5, B=5.0, C=5.5, D=6.0, E=7.0, F=8.0
2-0 Transfer rate unit
0=100kbit/s, 1=1Mbit/s, 2=10Mbit/s, 3=100Mbit/s, 4..7=reserved
MMC: same as above, but specified in <Hz> instead of <bits/s>
Note that for current SD Memory Cards, this field shall be always 32h which is
equal to 25 MHz - the mandatory maximum operating frequency of SD Memory Card.
In High-Speed mode, this field shall be always 5Ah which is equal to 50 MHz,
and when the timing mode returns to the default by CMD6 or CMD0 command, its
value will be 32h.
READ_BL_LEN
The maximum read data block length is computed as 2^READ_BL_LEN. The maximum
block length might therefore be in the range 512...2048 bytes (Refer to 4.3.3
for details). Note that in an SD Memory Card the WRITE_BL_LEN is always equal
to READ_BL_LEN.
3-0 Setting
Values:
00h..08h Reserved
09h Block length 512 Bytes (2^9)
0Ah Block length 1024 Bytes (2^10)
0Bh Block length 2048 Bytes (2^11)
0Ch..0Fh Reserved
MMC allows any values from 2^0 to 2^14, and uses 0Fh for Extension (see TBD
field in EXT_CSD) (uh, but "TBD" isn't yet defined in KMCEN0000M datasheet,
maybe TBD means to-be-defined?).
WRITE_BLK_MISALIGN
Defines if the data block to be written by one command can be spread over more
than one physical block of the memory device. The size of the memory block is
defined in WRITE_BL_LEN.
WRITE_BLK_MISALIGN=0 crossing physical block boundaries is invalid
WRITE_BLK_MISALIGN=1 crossing physical block boundaries is allowed
READ_BLK_MISALIGN
Defines if the data block to be read by one command can be spread over more
than one physical block of the memory device. The size of the memory block is
defined in READ_BL_LEN.
READ_BLK_MISALIGN=0 crossing physical block boundaries is invalid
READ_BLK_MISALIGN=1 crossing physical block boundaries is allowed
DSR_IMP
Defines if the configurable driver stage is integrated on the card. If set, a
driver stage register (DSR) shall be implemented (also see Chapter 5.5).
DSR_IMP=0 no DSR implemented
DSR_IMP=1 DSR implemented
VDD_R_CURR_MIN, VDD_W_CURR_MIN
Maximum values for read and write currents at the MINIMAL power supply VDD:
2-0 0=0.5mA, 1=1mA, 2=5mA, 3=10mA, 4=25mA, 5=35mA, 6=60mA, 7=100mA
VDD_R_CURR_MAX, VDD_W_CURR_MAX
Maximum values for read and write currents at the MAXIMAL power supply VDD:
2-0 0=1mA, 1=5mA, 2=10mA, 3=25mA, 4=35mA, 5=45mA, 6=80mA, 7=200mA
C_SIZE_MULT
This parameter is used for coding a factor MULT for computing the total device
size (see 'C_SIZE'). Defined as "MULT = 2^(C_SIZE_MULT+2)".
2-0 Device Size Factor (0..7 = Factor 4,8,16,32,64,128,256,512)
SD: ERASE_BLK_EN
The ERASE_BLK_EN defines the granularity of the unit size of the data to be
erased. The erase operation can erase either one or multiple units of 512 bytes
or one or multiple units (or sectors) of SECTOR_SIZE (see definition below).
If ERASE_BLK_EN=0, the host can erase one or multiple units of SECTOR_SIZE. The
erase will start from the beginning of the sector that contains the start
address to the end of the sector that contains the end address. For example, if
SECTOR_SIZE=31 and the host sets the Erase Start Address to 5 and the Erase End
Address to 40, the physical blocks from 0 to 63 will be erased as shown in
Figure 5-1.
Figure 5-1: ERASE_BLK_EN = 0 Example
Physical Block (per CSD)
0 1 2 3 4 5 6
0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
<----- Host Erase Address Range ------->
<---------- Erase Area ---------------------------------------------->
<---------- Erase Unit Size ------><------- Erase Unit Size --------->
If ERASE_BLK_EN=1 the host can erase one or multiple units of 512 bytes. All
blocks that contain data from start address to end address are erased. For
example, if the host sets the Erase Start Address to 5 and the Erase End
Address to 40, the physical blocks from 5 to 40 will be erased as shown in
Figure 5-2.
Figure 5-2: ERASE_BLK_EN = 1 Example
Physical Block (per CSD)
0 1 2 3 4 5 6
0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
<----- Host Erase Address Range ------->
<----- Erase Area --------------------->
SD: SECTOR_SIZE
The size of an erasable sector. The content of this register is a 7-bit binary
coded value, defining the number of write blocks (see WRITE_BL_LEN). The actual
size is computed by increasing this number by one. A value of zero means one
write block, 127 means 128 write blocks.
MMC: ERASE_GRP_SIZE
The contents of this register is a 5 bit binary coded value, used to calculate
the size of the erasable unit of the moviNAND. The size of the erase unit (also
referred to as erase group) is determined by the ERASE_GRP_SIZE and the
ERASE_GRP_MULT entries of the CSD, using the following equation:
size of erasable unit = (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULT + 1)
This size is given as minimum number of write blocks that can be erased in a
single erase command.
MMC: ERASE_GRP_MULT
A 5 bit binary coded value used for calculating the size of the erasable unit
of the moviNAND. See ERASE_GRP_SIZE section for detailed description.
MMC: DEFAULT_ECC
Set by the moviNAND manufacturer. It defines the ECC code which is recommended
for use. The field definition is the same as for the ECC field described later.
MMC: CONTENT_PROT_APP
This field in the CSD indicates whether the content protection application is
supported. MultiMediaCards which implement the content protection application
will have this bit set to '1'.
MMC: ECC
Defines the ECC code that was used for storing data on the moviNAND. This field
is used by the host (or application) to decode the user data. The following
table defines the field format:
ECC ECC type Maximum number of correctable bits per block
00h None (default) Mone
01h BCH (542,512) 3
02h-03h Reserved -
WP_GRP_ENABLE
A value of 0 means no group write protection possible.
R2W_FACTOR
Defines the typical block program time as a multiple of the read access time.
2-0 Multiples of read access time (0..5=Mul 1,2,4,8,16,32, 6..7=Reserved)
For example, value 5 means that writing is 32 times slower than reading.
WRITE_BL_LEN
The maximum write data block length is computed as 2^WRITE_BL_LEN. The maximum
block length might therefore be in the range from 512 to 2048 bytes. Write
Block Length of 512 bytes is always supported.
Note that in the SD Memory Card, the WRITE_BL_LEN is always equal to
READ_BL_LEN.
3-0 Block Length
Values:
00h..08h Reserved
09h 512 bytes (2^9)
0Ah 1024 Bytes (2^10)
0Bh 2048 Bytes (2^11)
0Ch..0Fh Reserved
MMC: See READ_BL_LEN
WRITE_BL_PARTIAL
Defines whether partial block sizes can be used in block write commands.
WRITE_BL_PARTIAL=0 means that only the WRITE_BL_LEN block size and its partial
derivatives, in resolution of units of 512 bytes, can be used for block
oriented data write.
WRITE_BL_PARTIAL=1 means that smaller blocks can be used as well. The minimum
block size is one byte.
COPY
Defines whether the contents is original (=0) or has been copied (=1). Setting
this bit to 1 indicates that the card content is a copy. The COPY bit is a one
time programmable bit except ROM card.
PERM_WRITE_PROTECT
TMP_WRITE_PROTECT
Permanently/temporarily write-protects the entire card (by disabling all write
and erase commands). The default values are 0, ie. not write protected.
FILE_FORMAT
FILE_FORMAT_GRP
Indicates the file format on the card. These fields are read-only for ROM. The
following formats are defined:
FILE_FORMAT_GRP FILE_FORMAT Type
0 0 Hard disk-like file system with partition table
0 1 DOS FAT (floppy-like) with boot sector only
(no partition table)
0 2 Universal File Format
0 3 Others/Unknown
1 0, 1, 2, 3 Reserved
A more detailed description is given in the Filesystem Specification.
DSi SD/MMC Protocol: CSD Register (128bit Card-Specific Data) Version 2.0
-------------------------------------------------------------------------
C_SIZE
This field is expanded to 22 bits and can indicate up to 2 TBytes (that is the
same as the maximum memory space specified by a 32-bit block address.)
This parameter is used to calculate the user data area capacity in the SD
memory card (not include the protected area). The user data area capacity is
calculated from C_SIZE as follows:
memory capacity = (C_SIZE+1) * 512KByte
The Minimum user area size of SDHC Card is 4,211,712 sectors (2GB + 8.5MB).
The Minimum value of C_SIZE for SDHC in CSD Version 2.0 is 001010h (4112).
The Maximum user area size of SDHC Card is (32GB - 80MB).
The Maximum value of C_SIZE for SDHC in CSD Version 2.0 is 00FF5Fh (65375).
The Minimum user area size of SDXC Card is 67,108,864 sectors (32GB).
The Minimum value of C_SIZE for SDXC in CSD Version 2.0 is 00FFFFh (65535).
TRAN_SPEED
TRAN_SPEED is variable depends on bus speed mode of SD Interface.
When CMD0 is received, this field is reset to 32h.
On SDSC (but not SDHC/SDXC), CMD6 does the same reset stuff?
32h SDSC/SDHC/SDXC in Default Speed mode (25MHz)
5Ah SDSC/SDHC/SDXC in High Speed mode (50MHz)
0Bh SDHC/SDXC in SDR50 or DDR50 mode (100Mbit/sec)
2Bh SDHC/SDXC in SDR104 mode (200Mbit/sec)
UHS-II mode is not related to this field.
READ_BL_LEN, WRITE_BL_LEN
These two fields are fixed to 9h (which indicates 512 Bytes).
SECTOR_SIZE
This field is fixed to 7Fh, which indicates 64 KBytes. This value is not
related to erase operation. SDHC and SDXC Cards indicate memory boundary by AU
size and this field should not be used.
ERASE_BLK_EN
This field is fixed to 1, which means the host can erase one or multiple units
of 512 bytes.
WP_GRP_SIZE, WP_GRP_ENABLE
These field are fixed to WP_GRP_SIZE=00h, and WP_GRP_ENABLE=0.
SDHC and SDXC Cards do not support write protected groups.
FILE_FORMAT_GRP
FILE_FORMAT
These fields are set to 0. Host should not use these fields.
DSi SD/MMC Protocol: EXT_CSD Register (4096bit Extended CSD Register) (MMC)
---------------------------------------------------------------------------
S_CMD_SET
This field defines which command sets are supported by the card.
Bit Command Set
7-5 Reserved
4 moviNAND only: ATA on MMC
3 moviNAND only: SecureMCC 2.0
2 Content Protection SecureMMC
1 SecureMMC
0 Standard MMC
MIN_PERF_a_b_ff
These fields defines the overall minimum performance value for the read and
write access with different bus width and max clock frequency modes. The value
in the register is coded as follows. Other than defined values are illegal.
Value Performance
0x00 For Cards not reaching the 2.4MB/s minimum value
0x08 Class A: 2.4MB/s and is the lowest allowed value for MMCplus and
MMCmobile(16x150kB/s)
0x0A Class B: 3.0MB/s and is the next allowed value (20x150kB/s)
0x0F Class C: 4.5MB/s and is the next allowed value (30x150kB/s)
0x14 Class D: 6.0MB/s and is the next allowed value (40x150kB/s)
0x1E Class E: 9.0MB/s and is the next allowed value (60x150kB/s)
This is also the highest class which any MMCplus or MMCmobile card
is needed to support in low bus category operation mode (26MHz with
4bit data bus).
A MMCplus or MMCmobile card supporting any higher class than this
have to support this class also (in low category bus operation mode).
0x28 Class F: Equals 12.0MB/s and is the next allowed value (80x150kB/s)
0x32 Class G: Equals 15.0MB/s and is the next allowed value (100x150kB/s)
0x3C Class H: Equals 18.0MB/s and is the next allowed value (120x150kB/s)
0x46 Class J: Equals 21.0MB/s and is the next allowed value (140x150kB/s)
This is also the highest class which any MMCplus or MMCmobile card
is needed to support in mid bus category operation mode (26MHz with
8bit data bus or 52MHz with 4bit data bus).
A MMCplus or MMCmobile card supporting any higher class than this
have to support this Class (in mid category bus operation mode) and
Class E also (in low category bus operation mode).
0x50 Class K: Equals 24.0MB/s and is the next allowed value (160x150kB/s)
0x64 Class M: Equals 30.0MB/s and is the next allowed value (200x150kB/s)
0x78 Class O: Equals 36.0MB/s and is the next allowed value (240x150kB/s)
0x8C Class R: Equals 42.0MB/s and is the next allowed value (280x150kB/s)
0xA0 Class T: Equals 48.0MB/s and is the last defined value (320x150kB/s)
PWR_CL_ff_vvv
These fields define the supported power classes by the card. By default, the
card has to operate at maximum frequency using 1 bit bus configuration, within
the default max current consumption, as stated in the table below. If 4 bit/8
bits bus configurations, require increased current consumption, it has to be
stated in these registers.
By reading these registers the host can determine the power consumption of the
card in different bus modes. Bits [7:4] code the current consumption for the 8
bit bus configuration. Bits [3:0] code the current consumption for the 4 bit
bus configuration.
The PWR_52_vvv registers are not defined for 26MHz MultiMediaCards.
Voltage Value Max RMS Current Max Peak Current Remarks
3.6V 0 100 mA 200 mA Default current
1 120 mA 220 mA consumption for
2 150 mA 250 mA high voltage cards
3 180 mA 280 mA
4 200 mA 300 mA
5 220 mA 320 mA
6 250 mA 350 mA
7 300 mA 400 mA
8 350 mA 450 mA
9 400 mA 500 mA
10 450 mA 550 mA
11-15 Reserved for future use
1.95V 0 65 mA 130 mA Default current
1 70 mA 140 mA consumption for
2 80 mA 160 mA Dual voltage cards
3 90 mA 180 mA (if any, not moviNAND)
4 100 mA 200 mA
5 120 mA 220 mA
6 140 mA 240 mA
7 160 mA 260 mA
8 180 mA 280 mA
9 200 mA 300 mA
10 250 mA 350 mA
6-15 Reserved for future use
The measurement for max RMS current is done as average RMS current consumption
over a period of 100ms.
Max peak current is defined as absolute max value not to be exceeded at all.
The conditions under which the power classes are defined are:
- Maximum bus frequency
- Maximum operating voltage
- Worst case functional operation
- Worst case environmental parameters (temperature,...)
These registers define the maximum power consumption for any protocol operation
in data transfer mode, Ready state and Identification state.
CARD_TYPE
This field defines the type of the card. The only currently valid values for
this field are 0x01 and 0x03.
Bit Card Type
7-2 Reserved
1 High Speed MultiMediaCard @ 52MHz
0 High Speed MultiMediaCard @ 26MHz
CSD_STRUCTURE
This field is a continuation of the CSD_STRUCTURE field in the CSD register.
CSD_STRUCTURE CSD structure version Valid for System Specification Version
0 CSD version No. 1.0 Version 1.0 - 1.2
1 CSD version No. 1.1 Version 1.4 - 2.2
2 CSD version No. 1.2 Version 3.1-3.2-3.31-4.0-4.1-4.2
3 Reserved for future use
4-255 Reserved for future use
EXT_CSD_REV
Defines the fixed parameters. related to the EXT_CSD, according to its
revision.
EXT_CSD_REV Extended CSD Revision
0 Revision 1.0
1 Revision 1.1
2 Revision 1.2 (moviNAND)
3-255 Reserved
CMD_SET
Contains the binary code of the command set that is currently active in the
card. It is set to '0' (Standard MMC) after power up and can be changed by a
SWITCH command.
CMD_SET_REV
Contains a binary number reflecting the revision of the currently active
command set. For Standard MMC command set it is:
Code MMC Revisions
0 v4.0
1-255 Reserved
This field, though in the Modes segment of the EXT_CSD, is read only.
POWER_CLASS
This field contains the 4 bit value of the selected power class for the card.
The power classes are defined in Table. The host should be responsible of
properly writing this field with the maximum power class it allows the card to
use. The card uses this information to, internally, manage the power budget and
deliver an optimized performance.
This field is 0 after power-on or software reset.
Bits Description
7-4 Reserved
3-0 Card power class code (See Table 5-29)
HS_TIMING
This field is 0 after power-on, or software reset, thus selecting the backwards
compatibility interface timing for the card. If the host writes 1 to this
field, the card changes its timing to high speed interface timing (refer to
Chapter 5.4.8).
BUS_WIDTH
It is set to '0' (1 bit data bus) after power up and can be changed by a SWITCH
command.
Value Bus Mode
0 1 bit data bus (MMC, with old 7pin connector)
1 4 bit data bus (MMCplus, with SD-card-compatible 9pin connector)
2 8 bit data bus (MMCplus, with special 13pin connector)
3-255 Reserved
For detecting cards with 4bit/8bit data bus support: Switch the SD/MMC
controller to 4bit/8bit modes, and use BUSTEST_W and BUSTEST_R to test if the
card sends a proper response, see
https://www.mikrocontroller.net/attachment/101561/AN_MMCA050419.pdf
Note: The SD/MMC controller in the DSi supports 1bit/4bit modes only (no 8bit
mode). For the DSi's onboard eMMC it's safe to assume 4bit being supported,
however, external MMC cards do require detecting 4bit support.
The RCA was intended for connecting multiple cards to the same host, possibly
even sharing the same signal wires for multiple cards. The multi-card feature
isn't used to often though.
Most hosts are having only a single card slot. And, hosts that <do> support
multiple cards may use separate busses and even separate controllers for each
card (eg. Nintendo DSi is doing so for onboard NAND and external SD slot).
However, even single-card systems will need to obtain a "dummy" RCA, and use
that RCA value for selecting the card.
The only exception is SPI mode: SPI isn't using RCA, and doesn't support RCA
commands at all - instead, in SPI mode, the cards are selected via /CS signal
(which may include multiple /CS signals for multiple cards).
RCA register
The writable 16-bit relative card address register carries the card address
that is published by the card during the card identification. This address is
used for the addressed host-card communication after the card identification
procedure. The default value of the RCA register is 0000h. The value 0000h is
reserved to set all cards into the Stand-by State with CMD7.
In UHS-II mode, Node ID is used as RCA. Refer to SD-TRAN Section of UHS-II
Addendum for more details.
Note
Commands GET_CSD, GET_CID, APP_CMD, GO_INACTIVE_STATE, and GET_STATUS
allow/require to specify RCA in parameter field.
Other commands are either processed by all cards (broadcast commands), or
processed only be cards that have been previously selected via CMD7 (most
normal commands).
Broadcast Commands
CMD0 sd/mmc spi GO_IDLE_STATE (type=bc)
CMD2 sd/mmc ALL_GET_CID (type=bcr)
CMD3 sd GET_RELATIVE_ADDR (type=bcr)
CMD4 sd/mmc SET_DSR (type=bc)
CMD7 sd/mmc SELECT_DESELECT_CARD (type=ac) ;actually: (type=bcr)
CMD8 sd spi SET_IF_COND (type=bcr)
ACMD41 sd spi SD_SEND_OP_COND (type=bcr) ;SPI: reduced functionality
Some broadcast commands are sending responses.
SD specs are suggesting to use separate CMD lines for each card (so the host
would broadcast the same command on all CMD lines, and would receive separate
responses in parallel from each CMD line).
MMC cards are said to support open-collector CMD lines (so responses from
separate cards would be logically ORed, though, dunno what that would be good
for).
DSi SD/MMC Protocol: DSR Register (16bit Driver Stage Register) (Optional)
--------------------------------------------------------------------------
DATA_STAT_AFTER_ERASE
Defines the data status after erase, whether it is 0 or 1 (the status is card
vendor dependent).
SD_SECURITY
This field indicates CPRM Security Specification Version for each capacity
card. The definition of Protected Area is different in each capacity card.
00h No Security
01h Not Used
02h SDSC Card (CPRM Security Version 1.01)
03h SDHC Card (CPRM Security Version 2.00)
04h SDXC Card (CPRM Security Version 3.xx)
05h-07h Reserved
The basic rule of setting this field:
SDSC Card sets this field to 2 (Version 1.01).
SDHC Card sets this field to 3 (Version 2.00).
SDXC Card sets this field to 4 (Version 3.xx).
Note that it is mandatory for a regular writable SD Memory Card to support
Security Protocol. For ROM (Read Only) and OTP (One Time Programmable) types of
the SD Memory Card, the security feature is optional.
SD_BUS_WIDTHS
Describes all the DAT bus widths that are supported by this card.
Bit 3 Reserved
Bit 2 4 bit (DAT0-3)
Bit 1 Reserved
Bit 0 1 bit (DAT0)
Since the SD Memory Card shall support at least the two bus modes 1-bit or
4-bit width, then any SD Card shall set at least bits 0 and 2
(SD_BUS_WIDTH="0101").
EX_SECURITY
This field indicates Extended Security which is defined by the Part A4 Data
Protection System Specification Version 1.00 or will be defined by a later
version of the Part 3 Security Specification Version 3.00.
00h Extended Security is not supported.
01h..0Fh Extended Security is supported. SCR[44-43] is defined by the
Part A4 Data Protection System Specification. SCR[46-45] is
reserved for future extension.
CMD_SUPPORT
Support bit of new commands are defined to Bit 33-32 (uh, 35-32?) of SCR.
Bit Supported Command Command CCC Remark
35 Extension Register Multi-Block CMD58/59 11 Optional.
34 Extension Register Single Block CMD48/49 11 Optional.
33 Set Block Count CMD23 2,4 Mandatory for UHS104 card
32 Speed Class Control CMD20 2,4 Mandatory for SDXC card
If CMD58/59 is supported, then CMD48/49 shall be also supported.
DSi SD/MMC Protocol: PWD Register (128bit Password plus 8bit Password len)
--------------------------------------------------------------------------
SD/MMC State
The "state" is an important SD/MMC feature to deal with - most commands can be
send only in certain states:
For normal operation, the card should be in "tran" state (and it may then
temporarily switch to "data/rcv/prg" states during read/write/erase commands).
For initialization, the card should be first forced to "idle" state, and the
init commands should then go through "ready/ident/stby" states, until finally
reaching "tran" state.
Less important states are "dis/ina", and, on MMC only, "btst/slp/irq" and
"pre-idle".
Both SD and MMC specs are leaving state undocumented for SPI mode (meaning that
SPI specific commands like CMD58/CMD59 are supported only in "unknown" state).
XXX...
SDIO State
Command ini stb cmd trn ina
CMD3 SET_RELATIVE_ADDR stb ok --- --- ---
CMD5 IO_SEND_OP_COND ok --- --- --- ---
ocr bad ina --- --- --- ---
CMD7 SELECT_CARD --- cmd ok --- ---
DESELECT_CARD --- ok stb --- ---
CMD15 GO_INACTIVE_STATE ina ina ina --- ---
CMD52 IO_RW_DIRECT --- --- ok (cmd)---
CMD53 IO_RW_EXTENDED --- --- trn --- ---
Note: In CMD52, state "dis" can mean state "ini","stb","ina" (though,
theoretically CMD52 cannot be used in that states, so one should never see the
"dis" state at all).
The CIS used by SDIO is based directly upon the metaformat specification used
by PCMCIA and Compact Flash. For details on the metaformat, refer to:
PC Card Standard, Volume 4, Metaformat Specification
Published by: PCMCIA (Personal Computer Memory Card International Association)
Basic Format
00h CISTPL_code
01h Offset to next tuple (n) (aka size of body)
02h+(0..n-1) Body (n bytes)
Summary
00h = CISTPL_NULL Null Tuple
10h = CISTPL_CHECKSUM Checksum Control
15h = CISTPL_VERS_1 Level 1 Version/Product Information
16h = CISTPL_ALTSTR Alternate Language String
20h = CISTPL_MANFID Manufacturer ID
21h = CISTPL_FUNCID Function ID
22h = CISTPL_FUNCE Function Extensions
80h-8Fh = Vendor specific Vendor specific
91h = CISTPL_SDIO_STD Info for Standard SDIO Functions
92h = CISTPL_SDIO_EXT Reserved for future SDIO stuff
FFh = CISTPL_END End-of-chain
Tuple 22h - Function Extension, Type 02h, for Function 1-7 (Power State)
00h Tuple ID (22h)
01h Tuple Size (02h+N*2) (N=1..15, for up to 15 power states)
02h Type of extended data (02h=Type 02h)
03h Fixed value (00h)
04h..xxh Nx16bit Max consumption in Power State 1..N (0..65535mW)
01 CISTPL_DEVICE
14 CISTPL_NO_LINK
1A CISTPL_CONFIG
1B CISTPL_CFTABLE_ENTRY
DSi Files
--> DSi SD/MMC DSiware Files on Internal eMMC Storage
--> DSi SD/MMC DSiware Files on External SD Card (.bin aka Tad Files)
--> DSi SD/MMC DSiware Files from Nintendo's Server
--> DSi SD/MMC DSiware Tickets and Title metadata
--> DSi SD/MMC Firmware dev.kp and cert.sys Certificate Files
--> DSi SD/MMC Firmware Certificate/Keys (DER)
--> DSi SD/MMC Firmware Font File
--> DSi SD/MMC Firmware Log Files
--> DSi SD/MMC Firmware Misc Files
--> DSi SD/MMC Firmware Wifi Firmware
--> DSi SD/MMC Firmware System Settings Data Files
--> DSi SD/MMC Firmware Version Data File
--> DSi SD/MMC Firmware Nintendo DS Cart Whitelist File
--> DSi SD/MMC Camera Files - Overview
--> DSi SD/MMC Camera Files - JPEG's
--> DSi SD/MMC Camera Files - pit.bin
--> DSi SD/MMC Flipnote Files
--> DS File Formats
DSi SD/MMC Partition Table (aka Master Boot Record aka MBR)
-----------------------------------------------------------
More info
For more info on MBR variants (and on the Partition Type value at 1C2h+n*10h),
see:
http://en.wikipedia.org/wiki/Master_Boot_Record
http://en.wikipedia.org/wiki/Partition_type <-- rather meaningless
Root directory
The following sectors are the Root directory, again, size depends on the info
in bootsector (on FAT32 is it's a normal cluster chain with variable size).
Each entry consists of 32 bytes:
00-07 8 Filename (first byte: 00=free entry, 2E=dir, E5=deleted entry)
08-0A 3 Filename extension
0B 1 Fileattribute
bit0 read only
bit1 hidden
bit2 system
bit3 volume label
bit4 subdirectory
bit5 archive-flag
bit6 reserved
bit7 reserved
0C-0D 2 Reserved, or stuff
0E-0F 2 Reserved, or Creation Timestamp
10-11 2 Reserved, or Creation Datestamp
12-13 2 Reserved, or Last Access Datestamp
14-15 2 Reserved, or MSBs of Cluster (for FAT32)
16-17 2 Last Modify Timestamp: HHHHHMMM, MMMSSSSS
18-19 2 Last Modify Datestamp: YYYYYYYM, MMMDDDDD
1A-1B 2 Pointer to first Cluster of file
1C-1F 4 Filesize in bytes (always 0 for directories)
The 'cluster' entry points to the first used cluster of the file. The FAT entry
for that cluster points to the next used cluster (if any), the FAT entry for
that cluster points to the next cluster, and so on.
http://en.wikipedia.org/wiki/Design_of_the_FAT_file_system
The DSi uses a 256MB Samsung eMMC moviNAND(?) flash chip, which is a NAND flash
chip with a built-in controller that implements a MMC (SDIO?) interface. In
many ways, it's like an SD card (or actually: MMC card) in BGA packaging, and
some people have successfully read it with modified(why/how?) SD(/MMC?) card
readers (is there any standard software that can be used for doing that?). The
last 16MB is used for wear-leveling purposes (such as replacing bad blocks),
while the first 240MB is used for storing actual data.
Stage 2 Boot Info Blocks 1, 2, 3 (unencrypted, aside from the RSA block)
000h 20h Zerofilled
020h 4 ARM9 Bootcode NAND Offset (800h) (Info Block 3: 80400h)
024h 4 ARM9 Bootcode Size actual (26410h)
028h 4 ARM9 Bootcode RAM Address / Entry (37B8000h)
02Ch 4 ARM9 Bootcode Size rounded-up (26600h)
030h 4 ARM7 Bootcode NAND Offset (26E00h) (Info Block 3: A6A00h)
034h 4 ARM7 Bootcode Size actual (27588h)
038h 4 ARM7 Bootcode RAM Address / Entry (37B8000h)
03Ch 4 ARM7 Bootcode Size rounded-up (27600h)
040h BFh Zerofilled
0FFh 1 ARM Loadmode Flags (0Ch)
100h 80h RSA Block (B3,FF,EC,E5,..) (Boot Info Block 3: 5B,E1,7A,9F,..)
180h 14h Global MBK1..MBK5 Slot Settings
194h 0Ch Local MBK6..MBK8 Settings, WRAM Areas for ARM9
1A0h 0Ch Local MBK6..MBK8 Settings, WRAM Areas for ARM7
1ACh 4 Global MBK9 Setting, WRAM Slot Write Protect (FF000000h)
1B0h 50h Zerofilled
The ARM Loadmode Flags are (usually 0Ch):
0 ARM9 Loadmode (0=Normal to memory, 1=Special via bit3)
1 ARM7 Loadmode (0=Normal to memory, 1=Special via bit3)
2 Unused, set (usually 1)
3 Special Loadmode (0=LZSS to memory, 1=Transfer via IPC FIFO)
4-7 Unused, cleared (usually 0)
BUG: If bit3 is set, then parts of bootrom behaves as if both bit0 & bit1 are
also set. Hmmm, but bit3 is actually set, so it's default behaviour...?
The above RSA Block contains 74h bytes of information (plus 0Bh bytes padding):
Pre 0Bh Leading RSA Padding (01,FF,FF,FF,FF,FF,FF,FF,FF,FF,00)
00h 10h AES_Engine Key Y for ARM9/ARM7 Bootcode (EC,07,00,00,...)
10h 14h SHA1 on WifiFlash[00h..27h] and eMMCBootInfo[00h..FFh,180h..1FFh]
3DS: reportedly NAND/MBR[00h..27h] instead of WifiFlash[00h..27h]??
24h 14h SHA1 on decrypted ARM9 Bootcode, with the actual binary size
38h 14h SHA1 on decrypted ARM7 Bootcode, with the actual binary size
4Ch 14h Zerofilled
60h 14h SHA1 on above 60h-byte area at [00h..5Fh] (63,D2,FC,6E,...)
eMMC Encryption for Boot Sectors (AES-CTR, with fixed key; from RSA block)
The ARM9/ARM7 bootcode is encrypted via AES-CTR:
RSA_KEY = F1,F5,1A,FF,... ;-from 3DS TWL_FIRM (for RSA Block)
IV[0..3] = +size ;\
IV[4..7] = -size ; size rounded up to 200h boundary, ie.
IV[8..B] = -size-1 ; from Boot Info Block entries [02Ch,03Ch]
IV[C..F] = 00000000h ;/
KEY_X[0..F] = "Nintendo DS",... ;-same as Key X for "Tad Files"
KEY_Y[0..F] = EC,07,00,00,... ;-from RSA Block (see above)
The RSA_KEY key is stored in some non-dumpable area of the DSi BIOS, making it
impossible to obtain that key without chip decapping. However, Nintendo has
included the same RSA_KEY in the "TWL_FIRM" firmware update for 3DS.
Stages
Stage 1: Load Stage 2 from NAND Boot Sectors (via code in BIOS ROM)
Stage 2: Load Stage 3 from NAND Filesystem
Stage 3: Contains GUI and allows to boot Cartridges or NAND files
Stage 1
The first stage of the DSi's bootloader lives in ROM, presumably on the CPU
die. It loads further encrypted (and probably signed) stages from NAND flash,
starting with a (partially unencrypted) offset table in the sector at 0x200.
Not much is known about this bootloader yet, but it presumably knows how to:
Initialize the encryption hardware
Read the contents of NVRAM
Initialize both LCDs
Read blocks (but not files) from the NAND flash
Perform some variety of integrity check on all data it reads(signature,CRC,?)
Display basic hexadecimal error codes
Possibly factory-programming the NAND flash?
Might also do basic power-on self test of peripherals
When the Stage 1 bootloader (in ROM) fails, it displays a 32-bit hexadecimal
number on the top screen, known Stage 1 error codes are:
Error Code Description
0000FE00 Error communicating NAND chip (It's missing, CLK shorted, etc.)
0000FEFC Integrity error in first block of Stage 2 (address at 220h)
0000FEFD Integrity error in second block of Stage 2 (address at 230h)
0000FEFE Boot sector integrity error (Sector 200h not valid), or error
in NVRAM contents.
Stage 2
Unlike the stage1 bootloader, which must be small enough to fit in ROM
(probably several kilobytes), the stage2 bootloader has about a megabyte of
NAND flash reserved for it. The stage2 bootloader understands partitions and
filesystems, and it is capable of loading the DSi menu. It also must understand
the encryption used on filesystem blocks in the NAND, and it must understand
how to load and validate title metadata.
The Stage 2 loader was not modified by the System Menu 1.4 update. This is
still earlier in the boot process than the "Health and Safety" warning.
The first stage bootloader reads sector 0x200 in order to find a table of
offsets to the Stage 2 bootloader:
00000220 00 08 00 00 10 64 02 00 00 80 7b 03 00 66 02 00 |.....d....{..f..|
00000230 00 6e 02 00 88 75 02 00 00 80 7b 03 00 76 02 00 |.n...u....{..v..|
00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
This appears to be describing two chunks of the stage2 loader, one 0x26410
bytes in length at address 0x800, and one 0x27588 bytes at address 0x26e00.
Note that this sector (and two similar ones at 0x400 and 0x600) appear to be
the only unencrypted blocks on the NAND flash.
It is unclear why there are two pieces which are nearly but not quite the same
size. Passive traces of the boot sequence confirm that the 0x26e00 chunk is
slightly larger, and it's loaded first. The 0x800 chunk is read immediately
after the 0x26e00 chunk.
Whereas the filesystem data in NAND is encrypted using a unique key for every
DSi, the stage2 bootloader is identical on every DSi tested so far. This
probably means that it is encrypted using a fixed key included in stage1.
All Stage 2 errors show before the health and safety screen. It appears that
Stage 2 errors from a cold power-on always cause the DSi to hang at a black
screen, whereas Stage 2 errors after reset (pressing but not holding the power
button) will give an error message screen. Known Stage 2 errors:
Text Description
"Error: 1-2435-8325" Invalid signature or partition type in MBR,
invalid starting LBA.
"Error: 2-2435-8325" Error reading fat/sectors from eMMC
"Error: 3-2435-8325" DSi Menu integrity checks failed
SD Card
DSiware (including Browser and Flipnote) can be exported to SD Card (via System
Menu, Data Managment).
Camera Photos and Frames can be exported (via Nintendo DSi Camera, Options,
Copy) (Frames are some sort of gaudi-masks that can be used (and created) via
one of the Camera special effect features; the mask uses YELLOW as transparent
color). As on eMMC storage, all photos from internal camera are mirrored
horizontally.
PRIVATE <DIR> private
DS <DIR> ds
TITLE <DIR> title ;\
484E4750 BIN 9.180K 484E4750.bin (aka Nintendo DSi Browser) ; dsiware
4B475556 BIN 11.510K 4B475556.bin (aka Flipnote Studio) ; games
HNB_ LST 2K HNB_.lst (content: "VUGKPGNH") ;/
APP <DIR> app
484E494A <DIR> 484E494A (aka Nintendo DSi Camera Stuff) ;\
PIT BIN 47K pit.bin ; camera
DCIM <DIR> DCIM ; frames
100NIN02 <DIR> 100NIN02 ;
HNI_0001 JPG 45K HNI_0001.JPG ;-frame/mask ;/
4B475556 <DIR> 4B475556 (aka Flipnote Studio Stuff) ;\
RECENT10 PLS 4K recent10.pls ;
MARK0 PLS 8K mark0.pls ; flipnote
MARK1 PLS 8K mark1.pls ; stuff
MARK2 PLS 8K mark2.pls ;
MARK3 PLS 8K mark3.pls ;
001 <DIR> 001 ;
DIRMEMO2 LST 157K dirmemo2.lst ;
F08243~1 PPM 467K F08243_0E5E2296197E5_000.ppm ;/
DCIM <DIR> DCIM
101NIN02 <DIR> 101NIN02 ;<-- can be 100NIN02 thru 999NIN02
HNI_0001 JPG 43K HNI_0001.JPG ;\dsi camera photos
HNI_0002 JPG 17K HNI_0002.JPG ; (names are numbered differently
HNI_0003 JPG 39K HNI_0003.JPG ;/as on eMMC where they came from)
Reportedly, the "Nintendo DSi Sound" application can also access audio files in
AAC format, saved in any folders on SD Card.
Aside from DSi-related files, the SD Card can also contain whatever files from
other computers.
Blocks
The System Menu, Data Management feature is referring to filesizes & free space
in "Blocks" (aka 128Kbytes units, aka 1Mbit units).
File/folder names
The DSi is using weird numeric strings as file/folder names:
000000vv Title Version (lowercase hex32bit) from tmd[1E4h] as carthdr[1Eh]
4ggggggg Title ID Gamecode (hex) as carthdr[230h..233h]
000300tt Title ID Filetype (hex) as carthdr[234h..237h]
HNI_nnnn Camera photo/frame files (nnnn = 0001..0100 decimal)
nnnNIN02 Camera photo/frame folders (nnn = 100..999 decimal)
The "000300tt" can be:
00030000 ROM Cartridges (as so for ROMs, doesn't appear in SD/MMC files)
00030004 DSiware (browser, flipnote, and games) (if any installed)
00030005 System Fun Tools (camera, sound, zone, pictochat, ds download play)
0003000f System Data (non-executable, without carthdr)
00030015 System Base Tools (system settings, dsi shop, 3ds transfer tool)
00030017 System Menu (launcher)
The "4ggggggg" can be (last two digits are region(s), or "41" for all regions):
484e41gg System Menu (Launcher)
484e42gg System Settings
484e4341 Wifi Firmware (non-executable datafile) (all regions)
484e4441 DS Download Play (all regions)
484e4541 Pictochat (all regions) (no update available)
484e46gg Nintendo DSi Shop
484e47gg Nintendo DSi Browser
484e4841 Nintendo DS Cart Whitelist (non-executable datafile) (all regions)
484e49gg Nintendo DSi Camera
484e4agg Nintendo Zone (doesn't exist in Korea)
484e4bgg Nintendo DSi Sound
484e4cgg Version Data (non-executable datafile)
484e4fgg Nintendo 3DS Transfer Tool
484E494A Nintendo DSi Camera Data (uppercase) ("japan") (aka all regions)
4b44474a Dokodemo Wii no Ma (japan only)
4b4755gg Flipnote Studio (doesn't exist in Korea/China)
42383841 DS Internet settings (a new DSi tool on 3DS consoles)
4bgggggg DSiware games... (whatever games you have purchased, if any)
These files can be stored in Internal eMMC, or on external SD card, and can be
downloaded from Nintendo's server (when buying games, or updating system
files).
Filesystem Viewer
no$gba debug version is allowing to view the filesystem tree from encrypted
eMMC images (via menubar: Window, Filesystem), the filesystem viewer is also
able to export single files from eMMC and SD images (by double-clicking
separate files).
Emulation
No$gba emulates read/write-accesses to eMMC images.
Another idea for future would be using files & folders on the PC filesystem
instead of a single image file (that might be easier to deal with in some
cases, but for the reverse-engineering stage it's better to stick with original
authentic images).
SD Card Images
no$gba supports SD Card images in similar fashion as above eMMC images, but
without needing any footer since there's encryption on SD cards. The image
should contain a pre-formatted MBR and FAT (as real SD cards do).
DSi-#.sd ;SD Card for machine 1..12 (# = 1..C hex)
note: no$gba does currently support only 128MB SDSC images (the CID, CSD, OCR,
SCR, SSR registers are hardcoded for images with 125698048 byte size), there is
a .zip file with an empty pre-formatted SD image in the no$gba package (if you
want to use that image: unzip it to the no$gba folder).
DSiware games (downloaded from DSi Shop), and pre-installed System Tools are
consisting of following files:
FAT16:\shared2\launcher\wrap.bin (16Kbytes)
Contains a list of installed DSiware Title IDs (in no specific order).
0000h 14h SHA1 on entries [014h..03Fh]
0014h 14h SHA1 on entries [040h..177h]
0028h 4 ID ("APWR") (aka 'WRAP' with mis-ordered letters)
002Ch 4 Size of entries at [040h..177h] (00000138h, aka 39*8)
0030h 10h Zerofilled
0040h 138h Space for 39 Title IDs (as at cart[230h]) (8x00h=unused entry)
0178h 3E88h Unknown (looks like random/garbage, or encrypted junk)
DSi SD/MMC DSiware Files on External SD Card (.bin aka Tad Files)
-----------------------------------------------------------------
The DSi can export applications from NAND to SD (via System Settings --> Data
Managment). The ".bin" files created on SD are using the "Tad file structure",
and alongsides, there's a "HNB_.lst" file containing a list of game codes.
Much like the Wii, the DSi carries with it a private ECC key that it can use to
sign things, and a certificate signed by Nintendo that attests to the fact that
the public ECC key belongs to a genuine DSi.
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/000300tt4ggggggg/000000vv
The "000000vv" file contains the ".app" file (in encrypted form).
Server: "000000vv" (AES-CBC encrypted, raw)
eMMC: "000000vv.app" (decrypted, raw)
SD Card: "GGGGGGGG.bin" (ES-block encrypted, with extra data)
First, the encrypted Title Key must be decrypted (via AES-CBC):
KEY[00h..0Fh] = Common Key (AF,1B,F5,16,...) ;from ARM7BIOS
IV[00h..07h] = Title ID (00,03,00,tt,gg,gg,gg,gg) ;from tik/cetk[1DCh]
IV[08h..0Fh] = Zerofilled ;padding
Input: Encrypted Title Key ;from tik/cetk[1BFh]
Output: Decrypted Title Key ;for use in next step
Then, the actual executable/file can be decrypted (also via AES-CBC):
KEY[00h..0Fh] = Decrypted Title Key ;from above step
IV[00h..01h] = Usually Zero (or "Index" from tmd?) ;from tmd[1E8h+N*24h] ?
IV[02h..0Fh] = Zerofilled ;padding
Input: Encrypted file "000000vv" ;from http download
Output: Decrypted file "000000vv.app" ;saved on eMMC
The above decryption steps do require a big-endian AES-CBC software
implementation (the DSi hardware supports only little-endian, and it supports
only AES-CTR and AES-CCM, and, especially, it supports only the "encrypt" key
schedule, whilst AES-CBC would require a different "decrypt" key schedule).
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/000300tt4ggggggg/cetk
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/000300tt4ggggggg/tmd
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/000300tt4ggggggg/tmd.nn
These files do contain tickets ("cetk"), and title metadata ("tmd" for newest
version, plus "tmd.nn" for older versions; with nn=0,1,256,257,512 and the
like).
--> DSi SD/MMC DSiware Tickets and Title metadata
The "cetk" file is available only for free system updates (not for titles sold
commercially in DSi Shop).
Downloading
The files can be downloaded with normal web browsers. The homebrew "NUS
Downloader" utility is also allowing to download those files (and to decrypt
them, provided that the "cetk" is available).
For free system updates, tickets can be downloaded as "cetk" files. For titles
sold commercially in DSi ship, tickets must be purchased somehow differently.
For example, the updates for DSi System Settings (EUR) can be downloaded from:
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/00030015484e4250/tmd
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/00030015484e4250/cetk
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/00030015484e4250/00000002
http://nus.cdn.t.shop.nintendowifi.net/ccs/download/00030015484e4250/00000003
The tmd and cetk files are unencrypted. The 00000002 and 00000003 files are
encrypted executables (containing System Settings v2 and v3).
Older Versions
Nintendo is usually keeping older "000000vv" files on their server, so one
could still download those older versions.
The oldest/original version would be usually "00000000", however, in case of
system files that are pre-installed on all consoles, only later versions are
available as updates (ie. starting with "00000001", or for some reason, with
"00000002", in case of system settings).
The tmd/cetk files are available only for the newest version (meaning that some
cosmetic values like title size & title version are adjusted for the newest
version; the cetk's AES-CBC key usually doesn't change for updates, so older
versions can be still decrypted with newer cetk's).
Older versions are usually deleted on internal eMMC storage, so only the
"000000vv.app" file exists.
Below describes the "raw" ticket+tmd formats. For more info on the data being
stored/encrypted in various locations, see these chapters:
--> DSi SD/MMC DSiware Files on Internal eMMC Storage
--> DSi SD/MMC DSiware Files on External SD Card (.bin aka Tad Files)
--> DSi SD/MMC DSiware Files from Nintendo's Server
Notes
The Title Version and Content Size/SHA1 entries are reflecting the NEWEST
".app" version (but the AES-CBC key should usually/always also work for older
versions).
The homebrew NUS Downloader utility is saving TMD (520 bytes; with REMOVED
certificate) and CETK (2468 bytes; with included certificate).
0000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Console ID string
00000c0: 00 00 00 02 54 57 63 37 39 64 63 65 63 39 2d 30 ....TWc79dcec9-0
00000d0: 38 61 32 30 32 38 37 30 31 30 38 34 31 31 38 00 8a2028701084118.
00000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Data management can't be accessed when dev.kp doesn't exist since you'd have no
twcert to sign/verify tads with, like when you never connected the DSi Shop
server.
Length
The length encoding depends on bit7 of the first byte:
when bit7=0 --> bit6-0 contain length (0..127 bytes)
when bit7=1 --> bit6-0 contain number of following length bytes
The length does rarely exceed 16bits, the most common lengths are:
len = Length 0..127 bytes (with len<80h)
81h,len = Length 128..255 bytes (with len>7Fh)
82h,msb,lsb = Length 256..65535 bytes (with msb:len>00FFh)
01h,Len,Value - BOOLEAN
Allows to define a boolean flag. Len is always 1, and value must be:
value[0] = flag (00h=False, or FFh=True)
02h,Len,Value - INTEGER
Allows to define integer, including "large" values like RSA keys. Bit7 of the
first byte is treated as sign bit, when storing unsigned values one must insert
a leading 00h byte if the high bit is set.
value[0..(len-1)] = data ;(len)*8 bits (with sign bit in MSB of 1st byte)
05h,Len - NULL
Allows to define empty/zero data, Len must be 00h, and accordingly, value is
0-byte tall.
0.9.2342.19200300.100.1.* /itu-t/data/pss/ucl/pilot/pilotAttributeType/..
0.9.2342.19200300.100.1.1 ../userid ;unused
0.9.2342.19200300.100.1.25 ../domainComponent ;unused
1.2.840.113533.7.65.* /iso/member-body/us/nortelnetworks/entrust/nsn-ce/..
1.2.840.113533.7.65.0 ../0 ;dsi browser equifax_s_ca.ca
1.2.840.113549.1.1.* /iso/member-body/us/rsadsi/pkcs/pkcs-1/..
1.2.840.113549.1.1.1 ../rsaEncryption
1.2.840.113549.1.1.2 ../rsaEncryptionWithMD2 ;dsi browser rsa.ca
1.2.840.113549.1.1.3 ../rsaEncryptionWithMD4 ;unused
1.2.840.113549.1.1.4 ../rsaEncryptionWithMD5 ;dsi browser thawte.ca
1.2.840.113549.1.1.5 ../rsaEncryptionWithSHA1
1.2.840.113549.1.1.11 ../rsaEncryptionWithSHA256
1.2.840.113549.1.1.12 ../rsaEncryptionWithSHA384 ;unused
1.2.840.113549.1.1.13 ../rsaEncryptionWithSHA512 ;unused
1.2.840.113549.1.1.14 ../rsaEncryptionWithSHA224 ;unused
1.2.840.113549.1.7.* /iso/member-body/us/rsadsi/pkcs/pkcs-7/..
1.2.840.113549.1.7.1 ../data ;for nested .der? ;3ds miiverse olv applet
1.2.840.113549.1.7.6 ../encryptedData ;"inside" pkcs-7
1.2.840.113549.1.9.* /iso/member-body/us/rsadsi/pkcs/pkcs-9/..
1.2.840.113549.1.9.1 ../emailAddress
1.2.840.113549.1.9.21 ../localKeyID ;"inside" pkcs-7
1.2.840.113549.1.12.1.* /iso/member-body/us/rsadsi/pkcs/pkcs-12/PbeIds/..
1.2.840.113549.1.12.1.3 ../pbeWithSHAAnd3-KeyTripleDES-CBC ;\inside pkcs-7
1.2.840.113549.1.12.1.6 ../pbeWithSHAAnd40BitRC2-CBC ;/
1.2.840.113549.1.12.10.* /iso/member-body/us/rsadsi/pkcs/pkcs-12/Version1/.
1.2.840.113549.1.12.10.1.2 ../BagIds/ShroudedKeyBag ;-inside pkcs-7
1.3.6.1.4.1.311.* /iso/org/dod/internet/prv/enterprise/microsoft/..
1.3.6.1.4.1.311.20.2 ../20/2/? ;incomplete blurp? ;3ds browser securetrust
1.3.6.1.4.1.311.21.1 ../21.1 ;unknown blurp? ;3ds browser securetrust
1.3.6.1.5.5.7.1.* /iso/org/dod/internet/security/mechanisms/pkix/pe/..
1.3.6.1.5.5.7.1.12 ../id-pe-logotype ;3ds shared data TLS, CA_8.der
1.3.14.3.2.* /iso/org/oiw/secsig/algorithms/..
1.3.14.3.2.26 ../hashAlgorithmIdentifier ;3ds miiverse olv applet
2.5.4.* /joint/ds/attributeType/..
2.5.4.3 ../commonName
2.5.4.4 ../surname
2.5.4.5 ../serialNumber
2.5.4.6 ../countryName
2.5.4.7 ../localityName
2.5.4.8 ../stateOrProvinceName
2.5.4.9 ../streetAddress
2.5.4.10 ../organizationName
2.5.4.11 ../organizationalUnit
2.5.4.12 ../title
2.5.4.42 ../givenName
2.5.29.* /joint/ds/certificateExtension/..
2.5.29.14 ../subjectKeyIdentifier
2.5.29.15 ../keyUsage
2.5.29.16 ../privateKeyUsagePeriod ;dsi browser equifax_s_ca.ca
2.5.29.17 ../subjectAltName ;3ds browser japnese gov
2.5.29.18 ../issuerAltName ;unused
2.5.29.19 ../basicConstraints
2.5.29.20 ../cRLNumber ;unused
2.5.29.21 ../reasonCode ;unused
2.5.29.22 ../expirationDate ;unused
2.5.29.23 ../instructionCode ;unused
2.5.29.24 ../invalidityDate ;unused
2.5.29.25 ../cRLDistributionPoints ;unused
2.5.29.26 ../issuingDistributionPoint ;unused
2.5.29.27 ../deltaCRLIndicator ;unused
2.5.29.28 ../issuingDistributionPoint ;unused
2.5.29.29 ../certificateIssuer ;unused
2.5.29.30 ../nameConstraints ;unused
2.5.29.31 ../cRLDistributionPoints
2.5.29.32 ../certificatePolicies ;dsi browser swiss_g2.ca
2.5.29.33 ../policyMappings ;unused
2.5.29.34 ../policyConstraints ;unused
2.5.29.35 ../authorityKeyIdentifier
2.5.29.36 ../policyConstraints ;unused
2.5.29.37 ../extKeyUsage ;3ds browser usertrust
2.16.840.1.113730.1.* /joint/country/us/organization/netscape/cert-ext/..
2.16.840.1.113730.1.1 ../cert-type ;dsi browser tc_c2_ca.ca
2.16.840.1.113730.1.8 ../ca-policy-url ;dsi browser tc_c2_ca.ca
2.16.840.1.113730.1.13 ../comment
Notes
The blurry japanese letters aren't actually legible (especially for the smaller
font sizes). Also note that the size of small font varies for the three regions
(ie. 10x12, 12x13, or 12x12).
LZ Decompression Functions
--------------------------
LZSS, Yaz0, LZ11 - Decompression for BIOS/SWI and ZFTR Font Files
LZSS/Yaz0/LZ11 are very similar formats, with small differences in the header
and compression codes, which could be summarized as so:
10,ss,ss,Ss ;ID(10h), Size(Ssssss) ;-LZSS header
11,ss,ss,Ss ;ID(11h), Size(Ssssss) ;-LZ11 header
"Yaz0",Ss,ss,ss,ss,0,0,0,0,0,0,0,0 ;-Yaz0 header
Ff ;Flags(Ff), each 8 entries ;-Flags (bit7=first)
1N,nn,nP,pp ;Disp(Ppp)+1, Len(Nnnn)+111h ;\
0N,nP,pp ;Disp(Ppp)+1, Len(Nn)+11h ; LZ11, when flag=1
NP,pp ;Disp(Ppp)+1, Len(N)+1 ;/
0P,pp,Nn ;Disp(Ppp)+1, Len(Nn)+12h ;\Yaz0, when flag=0
NP,pp ;Disp(Ppp)+1, Len(N)+2 ;/
NP,pp ;Disp(Ppp)+1, Len(N)+3 ;-LZSS, when flag=1
Dd ;Databyte(Dd) ;-When flag other than above
Below function can decompress LZSS data (as used by BIOS SWIs), and the LZ11
variant (with 11h in the header; as used by ZFTR font files, but not being
compatible with the BIOS SWI functions on neither GBA nor NDS nor DSi).
if src has "LZ77" or "CMPR" prefix then src=src+4 ;skip prefix (if any)
typ=byte[src]
if typ=59h ;YAZ0
errif (bytes[src+0..3]<>"Yaz0") OR (bytes[src+8..15]<>0)
fin=dst+BigEndian(word[src+04h]), src=src+16
else ;LZSS/LZ11
fin=dst+(word[src]/100h), src=src+4
endif
@@collect_more:
flagbits=[src], src=src+1, numflags=8
if typ=59h then flagbits=flagbits XOR 0FFh ;-invert for YAZ0
@@decompress_lop:
if dst>=fin then goto @@decompress_done
if numflags=0 then goto @@collect_more
numflags=numflags-1, flagbits=flagbits*2
if (flagbits AND 100h)=0 then
[dst]=[src], dst=dst+1, src=src+1
else
if typ=10h ;LZ10 aka LZSS (BIOS SWI compatible)
len=3
len=len+[src]/10h, disp=001h+([src] AND 0Fh)*100h+[src+1], src=src+2
elseif typ=11h ;LZ11 (special extended format)
if [src]/10h>1 then len=001h
if [src]/10h<1 then len=011h+([src] AND 0Fh)*10h, src=src+1
if [src]/10h=1 then len=111h+([src] AND 0Fh)*1000h+[src+1]*10h, src=src+2
len=len+[src]/10h, disp=001h+([src] AND 0Fh)*100h+[src+1], src=src+2
elseif typ=59h ;YAZ0 (special extended format)
len=[src]/10h, disp=001h+([src] AND 0Fh)*100h+[src+1], src=src+2
if len=0 then len=[src]+12h, src=src+1, else len=len+02h
endif
for i=1 to len, [dst]=[dst-disp], dst=dst+1, next i
endif
goto @@decompress_lop
@@decompress_done:
ret
The LZSS variant is implemented in GBA/NDS/DSi BIOS SWI functions:
--> BIOS Decompression Functions
LZSS and LS11 are used with many NDS/DSi/3DS files. LZSS/LZ11 can be detected
by checking for 10h/11h in first byte, and additionally checking for:
Extension is ".lz", ".lz77", ".LZ", or extension is preceeded by "_LZ."
Less common extensions are ".l", ".lex", ".cmp" (and various others)
Bytes[5..10] (after header+flags) contain IDs alike "NARC",FFFEh etc.
File starts with "LZ77",10h or "CMPR",10h (both rather uncommon)
Prefix strings exist in a few LZSS files ("LZ77" in Super Mario 64 DS, or
"CMPR" in Nanostray), then followed by normal LZSS data starting with type=10h.
Yaz0 files can be detected by checking for "Yaz0" in first 4 bytes. Yaz0 is
used by a few titles only (eg. used by DSi Sound, rom:\texture.szs). Yaz0 is
widely believed to use RLE compression (don't ask why).
LZ/Huffman
Apart from the above chubby functions, there are at least two compression
schemes trying to implement real serious compression:
--> GBA Cart e-Reader VPK Decompression
--> LZ Decompression Functions ASH0
Some titles contain regular .zip files (with Stored and Deflated files):
DSi Browser (rom:\skin\std_skin.zip) -- corrupted .zip (with 0D,0A appended)
DSi Shop (rom:\skin\std_skin.zip) -- intact .zip (unlike above)
3DS Browser applet (RomFS:\browser\page\..\*.zip)
--> ZIP Decompression
Others
Arika has brewed up a obscure compression+archive+encryption format:
--> DS Encrypted Arika Archives with ALZ1 compression
ash_decompress(source,dest)
collected[0]=80000000h ;stream 0 initially empty (endflag in bit31)
collected[1]=80000000h ;stream 1 initially empty (endflag in bit31)
src[0]=source+0 ;stream 0 start
for i=0 to 3, id[i]=read_bits(0,8), next i, if id[0..3]<>'ASH0' then error
dest_end=dest+read_bits(0,32) ;size of decompressed data
src[1]=source+read_bits(0,32) ;stream 1 start
load_huffman_tree(0,9) ;load stream 0 tree (9bit len/data values)
load_huffman_tree(1,11) ;load stream 1 tree (11bit disp values)
decompress_loop:
temp=0, while temp<8000h do temp=tree[0][temp+read_bits(0,1)]
if temp<8100h then
[dest]=temp AND FFh, dest=dest+1 ;store one uncompressed data byte
else
disp=0, while disp<8000h do disp=tree[1][disp+read_bits(1,1)]
len=temp+3-8100h, disp=disp+1-8000h
for j=1 to len, [dest]=[dest-disp], dest=dest+1, next j
if dest<dest_end then decompress_loop
ret
read_bits(s,num)
data=0
for i=1 to num
shl collected[s],1 ;move next bit to carry, or set zeroflag if empty
if zeroflag
collected[s]=[src[s]]*1000000h+[src[s]+1]*10000h+[src[s]+2]*100h+[src[s]+3]
src[s]=src[s]+4 ;read data in 32bit units, in reversed byte-order
carryflag=1 ;endbit
rcl collected[s],1 ;move bit31 to carry (and endbit to bit0)
rcl data,1 ;move carry to data
next i
ret(data)
load_huffman_tree(s,width)
stacktop=sp
tree_index=0
load_lop:
if getbits(0,1)=1
push tree_index+1 ;right (bit0=right) ;\
push tree_index ;left ; memorize left/right indices
tree_index=tree_index+2 ; and load more
goto load_lop ;/
dta=getbits(0,width)+8000h ;get data (bit15=data)
resolve_lop:
pop idx ;parent index
tree[s][idx]=dta ;store data (or child_index)
if (idx AND 1)=0 then goto load_lop ;load more (if it was left node)
dta=idx-1 ;child_index (to be stored at next parent_index)
if stacktop<>sp then goto resolve_lop
ret
Note: The official max tree sizes appear to be:
tree[0] = about 200h*6 halfwords
tree[1] = about 800h*6 halfwords
ZIP Decompression
-----------------
Official specs
The official ZIP specs can be reportedly found on pkware.com (but it's unknown
which browsers are capable of viewing that webpage):
http://support.pkware.com/home/pkzip/developer-tools/appnote
Alternately, the currently latest specs can be found here:
http://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT ;July 2020
That specs include info on rarely used things (including other compression
methods, encryption, compressed directory entries, and support for 64bit
offset/size values).
Inflate/Deflate
Inflate/Deflate is a common (de-)compression algorithm, used in ZIP files since
1991. And also used by ZLIB and GZIP. In the PSX world, it's also used by the
.CDZ cdrom-image format.
--> Inflate - Core Functions
--> Inflate - Initialization & Tree Creation
--> Inflate - Headers and Checksums
Note: Very old ZIP versions from 1989/1990 did use Shrink and Implode instead
of Deflate.
tinf_uncompress(dst,src)
tinf_init() ;init constants (needed to be done only once)
tinf_align_src_to_byte_boundary()
repeat
bfinal=tinf_getbit() ;read final block flag (1 bit)
btype=tinf_read_bits(2) ;read block type (2 bits)
if btype=0 then tinf_inflate_uncompressed_block()
if btype=1 then tinf_build_fixed_trees(), tinf_inflate_compressed_block()
if btype=2 then tinf_decode_dynamic_trees(), tinf_inflate_compressed_block()
if btype=3 then ERROR ;reserved
until bfinal=1
tinf_align_src_to_byte_boundary()
ret
tinf_inflate_uncompressed_block()
tinf_align_src_to_byte_boundary()
len=LittleEndian16bit[src+0] ;get len
if LittleEndian16bit[src+2]<>(len XOR FFFFh) then ERROR ;verify inverse len
src=src+4 ;skip len values
for i=0 to len-1, [dst]=[src], dst=dst+1, src=src+1, next i ;copy block
ret
tinf_inflate_compressed_block()
repeat
sym1=tinf_decode_symbol(tinf_len_tree)
if sym1<256
[dst]=sym1, dst=dst+1
if sym1>256
len = tinf_read_bits(length_bits[sym1-257])+length_base[sym1-257]
sym2 = tinf_decode_symbol(tinf_dist_tree)
dist = tinf_read_bits(dist_bits[sym2])+dist_base[sym2]
for i=0 to len-1, [dst]=[dst-dist], dst=dst+1, next i
until sym1=256
ret
tinf_decode_symbol(tree)
sum=0, cur=0, len=0
repeat ;get more bits while code value is above sum
cur=cur*2 + tinf_getbit()
len=len+1
sum=sum+tree.table[len]
cur=cur-tree.table[len]
until cur<0
return tree.trans[sum+cur]
tinf_align_src_to_byte_boundary()
tag=01h ;empty/end-bit (discard any bits, align src to byte-boundary)
ret
tinf_init()
tinf_build_bits_base(length_bits, length_base, 4, 3)
length_bits[28]=0, length_base[28]=258
tinf_build_bits_base(dist_bits, dist_base, 2, 1)
ret
tinf_build_bits_base(bits,base,delta,base_val)
for i=0 to 29
bits[i]=min(0,i-delta)/delta
base[i]=base_val
base_val=base_val+(1 shl bits[i])
ret
tinf_build_fixed_trees()
for i=0 to 6, tinf_len_tree.table[i]=0, next i ;[0..6]=0 ;len tree...
tinf_len_tree.table[7,8,9]=24,152,112 ;[7..9]=24,152,112
for i=0 to 23, tinf_len_tree.trans[i+0] =i+256, next i ;[0..23] =256..279
for i=0 to 143, tinf_len_tree.trans[i+24] =i+0, next i ;[24..167] =0..143
for i=0 to 7, tinf_len_tree.trans[i+168]=i+280, next i ;[168..175]=280..287
for i=0 to 111, tinf_len_tree.trans[i+176]=i+144, next i ;[176..287]=144..255
for i=0 to 4, tinf_dist_tree.table[i]=0, next i ;[0..4]=0,0,0,0,0 ;\dist
tinf_dist_tree.table[5]=32 ;[5]=32 ; tree
for i=0 to 31, tinf_dist_tree.trans[i]=i, next i ;[0..31]=0..31 ;/
ret
tinf_decode_dynamic_trees()
hlit = tinf_read_bits(5)+257 ;get 5 bits HLIT (257-286)
hdist = tinf_read_bits(5)+1 ;get 5 bits HDIST (1-32)
hclen = tinf_read_bits(4)+4 ;get 4 bits HCLEN (4-19)
for i=0 to 18, lengths[i]=0, next i
for i=0 to hclen-1 ;read lengths for code length alphabet
lengths[clcidx[i]]=tinf_read_bits(3) ;get 3 bits code length (0-7)
tinf_build_tree(code_tree, lengths, 19) ;build code length tree
for num=0 to hlit+hdist-1 ;decode code lengths for dynamic trees
sym = tinf_decode_symbol(code_tree)
len=1, val=sym ;default (for sym=0..15)
if sym=16 then len=tinf_read_bits(2)+3, val=lengths[num-1] ;3..6 previous
if sym=17 then len=tinf_read_bits(3)+3, val=0 ;3..10 zeroes
if sym=18 then len=tinf_read_bits(7)+11, val=0 ;11..138 zeroes
for i=1 to len, lengths[num]=val, num=num+1, next i
tinf_build_tree(tinf_len_tree, 0, hlit) ;\build trees
tinf_build_tree(tinf_dist_tree, 0+hlit, hdist) ;/
ret
tinf_data
clcidx[0..18] = 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 ;constants
tinf_adler32(src, length)
s1=1, s2=0
while (length>0)
k=max(length,5552)
for i=0 to k-1, s1=s1+[src], s2=s2+s1, src=src+1, next i
s1=s1 mod 65521, s2=s2 mod 65521, length=length-k
return (s2*10000h+s1)
Used in Arika's DSi Dr. Mario and reportedly also in other Arika titles.
rom:\INFO.DAT - contains encrypted directory
rom:\GAME.DAT - contains ALZ1 compressed files, and some uncompressed files
FAT16:\sys\log\sysmenu.log (16Kbytes)
Contains several groups of three text lines. Each "#FFT" group begins with two
0Ah characters, and is followed by space padding for 256-byte alignment of the
next group).
Below is some example (with blank space removed, original 40-digit hash strings
abbreviated to "xxxx..xx", and some lines are replaced by "...").
#FFT 13-08-18[SUN] 12:37:10
title: HNAP
DHT_PAHSE1_FAILED (sub info): hash1 - 8dfc..59
#FFT 13-08-18[SUN] 12:37:10
title: HNAP
DHT_PAHSE1_FAILED (sub info): calc_hash - 7eca..f5
#FFT 13-08-18[SUN] 12:37:11
title: HNAP
menuRedIplManager.cpp [l.514] RED FATAL 0000000010000000 (0000000041575445)
#FFT 13-08-18[SUN] 12:37:11
title: HNAP
menuResetCallback.cpp [l.50] type 0
#FFT 13-08-18[SUN] 13:44:16
title: HNAP
DHT_PAHSE1_FAILED (sub info): hash1Addr-02799e38
#FFT 13-08-18[SUN] 13:44:16
title: HNAP
DHT_PAHSE1_FAILED (sub info): hash1 - 8dfc..59
...
...
#FFT 13-09-10[TUE] 22:07:39
title: HNAP
menuResetCallback.cpp [l.50] type 0
#FFT 13-09-14[SAT] 14:59:16
title: HNAP
SYSMi_LoadTitleThreadFunc: some error has occurred.
#FFT 13-09-14[SAT] 14:59:16
title: HNAP
SYSMi_AuthenticateTitleThreadFunc: loaded 1 times.
#FFT 13-09-14[SAT] 14:59:17
title: HNAP
menuRedIplManager.cpp [l.514] RED FATAL 0000800000002100 (0003000049524544)
#FFT 13-09-14[SAT] 14:59:17
title: HNAP
menuResetCallback.cpp [l.50] type 0
#FFT 00-01-03[MON] 20:50:18
title: HNAP
WHITELIST_NOTFOUND (sub info): no entry for phase 1/2.
#FFT 00-01-03[MON] 20:50:18
title: HNAP
WHITELIST_NOTFOUND (sub info): no entry for phase 3.
#FFT 00-01-03[MON] 20:50:18
title: HNAP
SYSMi_LoadTitleThreadFunc: some error has occurred.
#FFT 00-01-03[MON] 20:50:18
title: HNAP
SYSMi_AuthenticateTitleThreadFunc: loaded 1 times.
#FFT 00-01-03[MON] 20:50:19
title: HNAP
menuRedIplManager.cpp [l.514] RED FATAL 0000800008000100 (000000004143454b)
#FFT 00-01-03[MON] 20:50:19
title: HNAP
menuResetCallback.cpp [l.50] type 0
#FFT 00-01-05[WED] 01:03:16
title: HNAP
WHITELIST_NOTFOUND (sub info): no entry for phase 1/2.
...
...
#FFT 00-01-01[SAT] 00:02:37
title: HNAP
SYSMi_AuthenticateTitleThreadFunc: loaded 1 times.
#FFT 00-01-01[SAT] 00:02:38
title: HNAP
menuRedIplManager.cpp [l.514] RED FATAL 0002004000000100 (00000000414e5045)
#FFT 00-01-01[SAT] 00:02:38
title: HNAP
menuResetCallback.cpp [l.50] type 0
FAT16:\sys\HWINFO_N.dat (16Kbytes)
0000h 14h SHA1 on entries [088h..09Bh]
0014h 6Ch Zerofilled
0080h 4 Header, Version or so (00000001h)
0084h 4 Header, Size of entries at [0088h..009Bh] (00000014h)
0088h 4 Some per-console ID (used what for?)
008Ch 10h Some per-console ID (used in "Tad Files")
009Ch 3F64h Unused (FFh-filled)
Entries [0088h..009Bh] are copied to [2000600h..2000613h].
FAT16:\import\
FAT16:\progress\
FAT16:\tmp\es\write\
Empty folders.
The DSi stores System Settings (and Title ID of most recent System Menu index)
on eMMC in two identical files: TWLCFG0.dat and TWLCFG1.dat.
If both files are intact then the newer file is taken (as indicated by the
update counter; for some weird reason, the DSi System Menu is always updating
BOTH files, so they are usually both "newer").
For NDS compatibility, some of the data is additionally stored on Wifi FLASH:
--> DS Firmware User Settings
The TWL data and the NDS-style data are also copied to RAM:
2000400h 128h TWLCFGn.dat bytes [088h..1AFh]
2FFFC80h 70h Wifi FLASH User Settings (fmw[newest_user_settings])
2FFFDFCh 4 Pointer to 2000400h
For some reason, most DSi games are containing some initialization code for
repairing or initializing the above pointer, as so:
if [2FFFDFCh]=0 then [2FFFDFCh]=2000400h
The RAM data at 2000400h isn't actually used by too many games though (one
program that is using it is Flipnote).
Some games are attempting to adopt the System Setting's language selection as
game language, games should do that only if they do support that language (a
bad example is the german version of Magic Made Fun: Deep Psyche, which
defaults to French when using English as system language).
The Wifi Enable flag is... a surreal fake Wireless-Disable option; which does
only disable the Wifi LED, the actual Wifi transmission does still work.
DSi SD/MMC Firmware Version Data File
-------------------------------------
Photos/Frames
Photos can be taken via Nintendo DSi Camera utitilty (or alternately, directly
via hotkeys in System Menu; which will be automatically flagging the photos
with "Star" stickers, which will cause them to be shown as System Menu
background image).
Frames are masks (with transparent pixels) that can be put onto photos. The
Frames can be created via Nintendo DSi Camera utility (Camera, select Frame
(upper-right Lens option), accept that Lens, then click Create Frame; the
procedure then is to take a photo, and to rub-out pixels on touchscreen to make
them transparent).
Internal/External Storage
The Camera is storing further data on the eMMC FAT12 partition:
FAT12:\photo\DCIM\100NIN02\HNI_nnnn.JPG ;camera photos
FAT12:\photo\private\ds\app\484E494A\pit.bin ;camera info
FAT12:\photo\private\ds\app\484E494A\DCIM\100NIN02\HNI_nnnn.JPG;camera frames
Camera data can be copied to SD card (via Nintendo DSi Camera, Options, Copy):
SD:\DCIM\nnnNIN02\HNI_nnnn.JPG ;camera photos
SD:\private\ds\app\484E494A\pit.bin ;camera info
SD:\private\ds\app\484E494A\DCIM\nnnNIN02\HNI_nnnn.JPG ;camera frames
And, in internal eMMC only (not on SD), the DSi is somewhere storing Calendar
entries (some sort of bitmaps with optional handwritten comments drawn via
touchscreen).
File/Folder Numbers
The "nnnNIN02" folders are numbered "100NIN02" through "999NIN02". The first
folder is usually 100NIN02, unless another "100xxxxx" folder did already exist
(eg. if the SD card contains a "100CANON" folder, then DSi would start at
101NIN02 or higher).
The trailing "02" of the "nnnNIN02" folders appears to be fixed for DSi photos
(folder name "nnnNIN01" is reserved for Wii screenshots).
The "HNI_nnnn.JPG" filenames are numbered "HNI_0001.JPG" through
"HNI_0100.JPG", thereafter, the DSi will switch to next higher folder number,
and wrap to using "HNI_0001.JPG" as first filename in that folder.
The weird "484E494A" folder name is based on the japanese Nintendo DSi Camera's
gamecode (HNIJ) converted to an 8-digit uppercase HEX string (this appears to
be always the japanese gamecode, even on european DSi consoles).
Stickers
Photos with "Star" sticker are shown as background picture in System Menu; this
works only for images stored in internal eMMC memory (images on SD Card can
have stickers, too, but they are ignored by System Menu).
FAT16:\title\00030004\4b4755gg\data\public.sav
This .sav file contains a FAT12 filesystem with following files:
Flipnote(public.sav):\eula.txt ;128 Kbytes, 20000h - zerofilled
Flipnote(public.sav):\option.bin ;256 bytes, 100h - options
Flipnote(public.sav):\mark0.pls ;8000 bytes, 1F40h - Heart sticker
Flipnote(public.sav):\mark1.pls ;8000 bytes, 1F40h - Crown sticker
Flipnote(public.sav):\mark2.pls ;8000 bytes, 1F40h - Music sticker
Flipnote(public.sav):\mark3.pls ;8000 bytes, 1F40h - Skull sticker
Flipnote(public.sav):\recent10.pls ;4000 bytes, FA0h - Recently saved
Flipnote(public.sav):\friend.pls ;28800 bytes, 7080h - F7,A0,CD,zeroes..
Flipnote(public.sav):\remind.pls ;10240 bytes, 2800h - F7,A0,CD,zeroes..
Flipnote(public.sav):\latest1.pls ;256 bytes, 100h - xxxxxxxx,zeroes..
Flipnote(public.sav):\nand.pls ;160000 bytes, 27100h - All files
Flipnote(public.sav):\ugo\0NN\XNNNNN_NNNNNNNNNNNNN_NNN.ppm - flipnotes
SD:\private\ds\app\4B4755GG\gif\XNNNNN_NNNNNNNNNNNNN_NNN.gif
Flipnotes exported to GIF format. Supported are animated GIFs, and separate
GIFs for each frame. There appears to be no way to view GIFs, or to convert
them back to PPM format.
SD:\private\ds\app\4B4755GG\001\XNNNNN_NNNNNNNNNNNNN_NNN.ppm ;normal
SD:\private\ds\app\4B4755GG\YYYYMMDD\NNN\XNNNNN_NNNNNNNNNNNNN_NNN.ppm ;backup
Flipnotes animation files.
0000h 4 File ID ("PARA")
0004h 4 Size of Animation Data (vid)
0008h 4 Size of Audio Data (aud) (0=none)
000Ch 2 Number of Frames minus 1 (NF-1)
000Eh 2 Unknown (always 24h,00h)
0010h 2 Lock Flag (0=Open, 1=Locked, prevent editing)
0012h 2 Preview frame number
0014h 22 Nickname of Original Author (UCS-2) ;\max 10 characters
002Ah 22 Nickname of Last Editor (UCS-2) ; (plus ending zero)
0040h 22 Nickname of User (?) (UCS-2) ;/
0056h 8 User ID of Original Author (Flipnote Studio ID)
005Eh 8 User ID of Last Editor (Flipnote Studio ID)
0066h 18 Filename of Original File (3xHEX, 13xASCII, 2xVER)
0078h 18 Filename of Current File (3xHEX, 13xASCII, 2xVER)
008Ah 8 User ID of Previous Editor (Flipnote Studio ID)
0092h 8 Filename Fragment (3xHEX, 5xHEX)
009Ah 4 Time/Date (seconds since 1st Jan 2000)
009Eh 2 Zerofilled
00A0h 600h Preview Bitmap (8x6 tiles, aka 64x48 pixels, 4bpp)
06A0h 2 Size of Animation Table (4*NF)
06A2h 4 Zerofilled
06A6h 2 Flags (bit0=Can be set?, bit1=Loop/Repeat, bit6=Set?)
06A8h 4*NF Animation Table (offsets in Animation Data for each frame)
... (vid) Animation Data Frame(s)
... 1*NF Audio Flags for each Frame (bit0-2: Effect 1-3, bit3-7: Zero)
... .. Padding (0..3 bytes zerofilled, for alignment of next entry)
... 4 Size of Background music in bytes (0=not used/empty)
... 4 Size of Sound effect #1 in bytes (0=not used/empty, max 2000h)
... 4 Size of Sound effect #2 in bytes (0=not used/empty, max 2000h)
... 4 Size of Sound effect #3 in bytes (0=not used/empty, max 2000h)
... 1 Framespeed for playback (1..8) aka "8 minus N"
... 1 Framespeed when BGM was recorded (1..8) aka "8-decimal"
... 14 Zerofilled
... (aud) Audio Data (BGM, followed by Effects 1, 2, 3) (if any)
... 80h RSA-OpenPGP-SHA1 across all preceeding bytes
... 10h Zerofilled
The RSA signature is in OpenPGP SHA1 format (as used by SWI 23h, however
Flipnote is using it's own RSA functions instead of the BIOS SWIs). The RSA
public/private keys are contained in the Flipnote executable (in the modcrypted
area).
Audio Data
First comes the BGM (if used)
Then comes sound effect #1 (if used)
Then comes sound effect #2 (if used)
Then comes sound effect #3 (if used)
The sound data seems to be a variant of VOX ADPCM at around 8KHz.
Briefly
0:00000 11 00 02 02 00 00 00 82 17 00 10 00 00 00 00 00 ;\
0:00010 00 00 03 00 00 00 00 ;
0:00017..000FF unused (zerofilled) ;/
0:00100 00 00 00 00 00 00 00 00 00 00 11 00 00 00 00 00 ;\
0:00110 80 00 ;
0:00112..00FFF unused (zerofilled) ;/
0:01000 01 03 D9 01 FF ;\
0:01005 20 04 71 02 00 02 ;hif.h: 271h ;
0:0100B 21 02 0C 00 ;
0:0100F 22 04 00 00 08 32 ;
0:01015 1A 05 01 01 00 02 07 ;\ ;
0:0101C 1B 08 C1 41 30 30 FF FF 32 00 ; PROM? ;
0:01026 14 00 ; RAM? ;
0:01028..01044 FF-filled (1Dh bytes) uh? ;/ ;
0:01045..010FF 00-filled ;/
0:01100 20 04 71 02 00 02 ;\
0:01106 21 02 0C 00 ;
0:0110A 22 2A 01 01 11 00 00 00 00 00 00 00 00 00 00 08 00 00
0:0111C FF 80 00 00 00 00 01 0A 00 00 00 00 00 00 00 00
0:0112C 00 00 00 01 00 01 00 01 00 01
0:01136 80 01 06 ;
0:01139 81 01 07 ;
0:0113C 82 01 DF ;
0:0113F FF 01 00 ;
0:01142..011FF 00-filled ;/
0:01200..02FFF mirrors of 01000..011FF (common cis and function 1 cis) ?
0:03000.. 00-filled
Differences between hw2 versus hw4/hw6 (hw4 and hw6 are exactly same):
added several new "GMBOX" registers (hw4/hw6)
added new CPU_DBG registers (hw4/hw6)
added three new "UART_HCI_FRAMER_xxx" error bits (hw4/hw6)
renamed "DRAGON_INT" (hw2) to "INT" (hw4/hw6)
renamed "SPI_xxx" (hw2) to "HOST_CTRL_SPI_xxx" (hw4/hw6)
1:00474h..00477h - WINDOW_DATA
0-31 DATA
Used to access the internal Xtensa memory space. The actual memory access
occurs when writing the WINDOW_xxx_ADDR registers (see below).
BPTWL
Apart from SDIO bus, some wifi functions are also controlled by the BPTWL chip
(accessed via I2C bus). The wifi related BPTWL signals are:
ATH_TX_H ;\maybe some/all of these do just indicate traffic
WL_RXPE ; (for blinking the wifi LED, if it is enabled)
WL_TXPE ;/
/WIFI_RST ;-Reset or so
That signals seem to be used with BPTWL register 30h, which is allowing to
disable the Wifi LED, and might also allow to do things like restting the Wifi
hardware, and/or switching between NDS and DSi wifi-modes.
HTC Services/Handshake
After BMI, and before WMI, there is a "HTC_SERVICES" handshake with following
values:
RSVD_SERVICE_GROUP = 0
WMI_SERVICE_GROUP = 1
HTC_TEST_GROUP = 254
HTC_SERVICE_GROUP_LAST = 255
MAKE_SERVICE_ID(group,index) = group*100h + index
NOTE: service ID of 0000h is reserved and should never be used
HTC_CTRL_RSVD_SVC = MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1)
WMI_CONTROL_SVC = MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0) ;control
WMI_DATA_BE_SVC = MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1) ;best effort
WMI_DATA_BK_SVC = MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2) ;background
WMI_DATA_VI_SVC = MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3) ;video
WMI_DATA_VO_SVC = MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4) ;voice
WMI_MAX_SERVICES = 5
raw stream service (i.e. flash, tcmd, calibration apps):
HTC_RAW_STREAMS_SVC = MAKE_SERVICE_ID(HTC_TEST_GROUP,0)
Obscure note: The above services are also known as ACs or ENDPOINTs (whatever
that means).
WMI Events/Responses
Events/Responses with same ID as corresponding command
000Eh WMI_GET_CHANNEL_LIST_CMD
001Ch WMI_GET_TX_PWR_CMD
0035h WMI_GET_FIXRATES_CMD
003Eh WMI_GET_KEEPALIVE_CMD
F001h WMI_GET_BITRATE_CMD
Events/Responses that could/should exist (but aren't documented)
? WMI_GET_APPIE_CMD ;aka GET_APP_IE ;\not implemented in DSi
? WMI_AP_MODE_STAT_CMD ;has reply? ;/
Events/Responses that have REPLY structs defined (but CMDs don't send reply?)
? WMI_CRE_PRIORITY_STREAM_REPLY ;\
? WMI_DEL_PRIORITY_STREAM_REPLY ; not implemented in DSi
? WMI_FRAME_RATES_REPLY ;/
Events/Responses with special IDs
1001h WMI_READY_EVENT
1002h WMI_CONNECT_EVENT
1003h WMI_DISCONNECT_EVENT
1004h WMI_BSSINFO_EVENT ;aka WMI_BSS_INFO
1005h WMI_CMDERROR_EVENT ;aka WMI_CMD_ERROR_EVENT ;for CMD 01h,11h,16h,26h
1006h WMI_REGDOMAIN_EVENT ;aka WMI_REG_DOMAIN_EVENT
1007h WMI_PSTREAM_TIMEOUT_EVENT
1008h WMI_NEIGHBOR_REPORT_EVENT
1009h WMI_TKIP_MICERR_EVENT
100Ah WMI_SCAN_COMPLETE_EVENT
100Bh WMI_REPORT_STATISTICS_EVENT ;related to CMD 0010h ?
100Ch WMI_RSSI_THRESHOLD_EVENT
100Dh WMI_ERROR_REPORT_EVENT ;aka WMI_TARGET_ERROR_REPORT_EVENT
100Eh WMI_OPT_RX_FRAME_EVENT ;aka WMI_OPT_RX_INFO
100Fh WMI_REPORT_ROAM_TBL_EVENT ;related to CMD 002Ah ?
1010h WMI_EXTENSION_EVENT ;prefix for WMIX events...
1010h:3001h WMIX_DSETOPENREQ_EVENT ;request 2001h ;\
1010h:3002h WMIX_DSETCLOSE_EVENT ;request close ; not implemented in DSi
1010h:3003h WMIX_DSETDATAREQ_EVENT ;request 2002h ;/
1010h:3004h WMIX_GPIO_INTR_EVENT ;used (interrupt)
1010h:3005h WMIX_GPIO_DATA_EVENT ;used (reply to 2004h and 2006h)
1010h:3006h WMIX_GPIO_ACK_EVENT ;used (reply to 2003h and 2005h)
1010h:3007h WMIX_HB_CHALLENGE_RESP_EVENT ;used (reply to 2008h)
1010h:3008h WMIX_DBGLOG_EVENT ;used (probably related to 2009h)
1010h:3009h WMIX_PROF_COUNT_EVENT ;-not implemented in DSi
1011h WMI_CAC_EVENT
1012h WMI_SNR_THRESHOLD_EVENT
1013h WMI_LQ_THRESHOLD_EVENT
1014h WMI_TX_RETRY_ERR_EVENT
1015h WMI_REPORT_ROAM_DATA_EVENT ;related to 002Bh? ;\not implemented in DSi
1016h WMI_TEST_EVENT ;/
1017h WMI_APLIST_EVENT
1018h WMI_GET_WOW_LIST_EVENT ;reply to CMD 0044h
1019h WMI_GET_PMKID_LIST_EVENT ;reply to CMD F006h
Below not in AR6kSDK.build_sw.18, however, "101Ah" is USED on DSi...
101Ah WMI_CHANNEL_CHANGE_EVENT ;<-- used on DSi
Below some are spotted on 3DS (possibly inofficial stuff?)
(type4=3ds/internet?, macfilter=3ds/localmultiplay?)
101Dh type4, len=0
101Fh type4, len=N*4
1020h type4, len=8
1021h macfilter, len=10h+? ;"succes"
1022h type4, len=0 ;reply to cmd 0057h ?
1023h macfilter, len=4+? ;reply to cmd 0068h
1024h type4, len=0Eh
1025h type4, len=1 ;thrown by 3DS type4 variant (works when ignored)
1026h macfilter, len=0Ch ;reply to cmd 006Dh
1027h macfilter, len=2+? ;reply to cmd 0073h
Below (101Bh..9004h) not implemented in DSi...
101Bh WMI_PEER_NODE_EVENT
101Ch WMI_PSPOLL_EVENT ;aka WMI_PS_POLL_EVENT ;AP mode related?
101Dh WMI_DTIMEXPIRY_EVENT
101Eh WMI_WLAN_VERSION_EVENT
101Fh WMI_SET_PARAMS_REPLY_EVENT ;reply to CMD F018h (reply to "SET" cmd!)
1020h WMI_ADDBA_REQ_EVENT
1021h WMI_ADDBA_RESP_EVENT
1022h WMI_DELBA_REQ_EVENT aka WMI_DELBA_EVENT
1023h WMI_TX_COMPLETE_EVENT
1024h WMI_HCI_EVENT_EVENT aka WMI_HCI_EVENT
1025h WMI_ACL_DATA_EVENT
1026h WMI_REPORT_SLEEP_STATE_EVENT ;formerly N/A
1027h WMI_WAPI_REKEY_EVENT ;formerly N/A, or 1026h if WAPI_ENABLE
1028h WMI_REPORT_BTCOEX_STATS_EVENT ;formerly 1026h/1027h ;reply to F032h
1029h WMI_REPORT_BTCOEX_CONFIG_EVENT ;formerly 1027h/1028h ;reply to F033h
102Ah WMI_GET_PMK_EVENT aka WMI_GET_PMK_REPLY
102Bh WMI_DFS_HOST_ATTACH_EVENT ;\
102Ch WMI_DFS_HOST_INIT_EVENT ;
102Dh WMI_DFS_RESET_DELAYLINES_EVENT ;
102Eh WMI_DFS_RESET_RADARQ_EVENT ;
102Fh WMI_DFS_RESET_AR_EVENT ; DFS Events
1030h WMI_DFS_RESET_ARQ_EVENT ;
1031h WMI_DFS_SET_DUR_MULTIPLIER_EVENT ;
1032h WMI_DFS_SET_BANGRADAR_EVENT ;
1033h WMI_DFS_SET_DEBUGLEVEL_EVENT ;
1034h WMI_DFS_PHYERR_EVENT ;/
1035h WMI_CCX_RM_STATUS_EVENT ;-CCX Evants ;uh, EvAntS?
1036h WMI_P2P_GO_NEG_RESULT_EVENT ;-P2P Events ;uh, EventS?
1037h WMI_WAC_SCAN_DONE_EVENT ;\
1038h WMI_WAC_REPORT_BSS_EVENT ; WAC
1039h WMI_WAC_START_WPS_EVENT ;
103Ah WMI_WAC_CTRL_REQ_REPLY_EVENT ;/
103Bh WMI_RFKILL_STATE_CHANGE_EVENT ;\RFKILL Events
103Ch WMI_RFKILL_GET_MODE_CMD_EVENT ;/
103Dh WMI_P2P_GO_NEG_REQ_EVENT ;\
103Eh WMI_P2P_INVITE_REQ_EVENT ;
103Fh WMI_P2P_INVITE_RCVD_RESULT_EVENT ;
1040h WMI_P2P_INVITE_SENT_RESULT_EVENT ; More P2P Events
1041h WMI_P2P_PROV_DISC_RESP_EVENT ;
1042h WMI_P2P_PROV_DISC_REQ_EVENT ;
1043h WMI_P2P_START_SDPD_EVENT ;
1044h WMI_P2P_SDPD_RX_EVENT ;/
1045h WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT ;-avoid AR6003 crash
8000h WMI_THIN_EVENTID_RESERVED_START ;\
8001h WMI_THIN_GET_MIB_EVENT ; THIN events (wmi_thin.h)
8002h WMI_THIN_JOIN_EVENT ;
8FFFh WMI_THIN_EVENTID_RESERVED_END ;/
9000h WMI_SET_CHANNEL_EVENT ;\
9001h WMI_ASSOC_REQ_EVENT aka WMI_ASSOCREQ_EVENT ; More events,
9002h WMI_ACS_EVENT ;generic ACS event ; somehow located
9003h WMI_REPORT_WMM_PARAMS_EVENT ; after THIN area
9004h WMI_STORERECALL_STORE_EVENT ;/
code from 2012 has WMI_WAPI_REKEY_EVENT re-removed again, the two RFKILL Events
moved around (placed into the P2P event area), and WMI_REPORT_WMM_PARAMS_EVENT
moved to 10xxh, a new WMI_WAC_REJECT_WPS_EVENT at 10xxh, and
WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT removed, and
WMI_STORERECALL_STORE_EVENT moved to 9003h, and adds more NEW stuff at
9004h-900Dh:
10xxh WMI_REPORT_WMM_PARAMS_EVENT ;-moved to 10xxh or so
10xxh WMI_WAC_REJECT_WPS_EVENT ;-NEW
9003h WMI_STORERECALL_STORE_EVENT ;-move to HERE
9004h WMI_WOW_EXT_WAKE_EVENT ;\
9005h WMI_GTK_OFFLOAD_STATUS_EVENT ;
9006h WMI_NETWORK_LIST_OFFLOAD_EVENT ;
9007h WMI_REMAIN_ON_CHNL_EVENT ; NEW
9008h WMI_CANCEL_REMAIN_ON_CHNL_EVENT ;
9009h WMI_TX_STATUS_EVENT ;
900Ah WMI_RX_PROBE_REQ_EVENT ;
900Bh WMI_P2P_CAPABILITIES_EVENT ;
900Ch WMI_RX_ACTION_EVENT ;
900Dh WMI_P2P_INFO_EVENT ;/
targaddr[10h] - hi_option_flag
0 HI_OPTION_TIMER_WAR ;Enable timer workaround
1 HI_OPTION_BMI_CRED_LIMIT ;Limit BMI command credits
2 HI_OPTION_RELAY_DOT11_HDR ;Relay Dot11 hdr to/from host
3 HI_OPTION_MAC_ADDR_METHOD ;MAC addr method 0=locally administred
; 1=globally unique addrs
4 HI_OPTION_ENABLE_RFKILL ;RF Kill Enable Feature
5 HI_OPTION_ENABLE_PROFILE ;Enable CPU profiling
6 HI_OPTION_DISABLE_DBGLOG ;Disable debug logging
7 HI_OPTION_SKIP_ERA_TRACKING ;Skip Era Tracking
8 HI_OPTION_PAPRD_DISABLE ;Disable PAPRD (debug)
9-11 HI_OPTION_NUM_DEV ;num dev (3bit)
12-27 HI_OPTION_DEV_MODE ;dev mode (16bit) (aka 4xMODE, 4xSUBMODE?)
28 HI_OPTION_NO_LFT_STBL ;Disable LowFreq LF Timer Stabilization
29 HI_OPTION_SKIP_REG_SCAN ;Skip regulatory scan
30 HI_OPTION_INIT_REG_SCAN ;Do regulatory scan during init before
; sending WMI ready event to host
31 HI_OPTION_FW_BRIDGE ;Firmware bridging
Two bits of hi_option_flag are used to represent 3 (three?) modes
HI_OPTION_FW_MODE_IBSS = 00h ;IBSS Mode
HI_OPTION_FW_MODE_BSS_STA = 01h ;STA Mode
HI_OPTION_FW_MODE_AP = 02h ;AP Mode
HI_OPTION_FW_MODE_BT30AMP = 03h ;BT30 AMP Mode
Two bits of hi_option flag are used to represent 4 submodes (aka DEV_MODE?)
HI_OPTION_FW_SUBMODE_NONE = 00h ;Normal mode
HI_OPTION_FW_SUBMODE_P2PDEV = 01h ;p2p device mode
HI_OPTION_FW_SUBMODE_P2PCLIENT = 02h ;p2p client mode
HI_OPTION_FW_SUBMODE_P2PGO = 03h ;p2p go mode
Fw Mode/SubMode Mask
.--------.-------.-------.-------.-------.-------.-------.-------.
| SUB | SUB | SUB | SUB | | | | |
|MODE[3] |MODE[2]|MODE[1]|MODE[0]|MODE[3]|MODE[2]|MODE[1]|MODE[0]|
| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) |
'--------'-------'-------'-------'-------'-------'-------'-------'
HI_OPTION_FW_MODE_BITS 0x2 ;\
HI_OPTION_FW_MODE_MASK 0x3 ; MODE
HI_OPTION_FW_MODE_SHIFT 0xC ;bit12-13 (2bit) per device? ;
HI_OPTION_ALL_FW_MODE_MASK 0xFF ;bit12-19 (8bit) per 4 devices? ;/
HI_OPTION_FW_SUBMODE_BITS 0x2 ;\
HI_OPTION_FW_SUBMODE_MASK 0x3 ; SUB-
HI_OPTION_FW_SUBMODE_SHIFT 0x14 ;bit20-21 (2bit) per device? ; MODE
HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 ;bit20-27 (8bit) per 4 devices? ;
HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 ;/
targaddr[CCh] - hi_option_flag2
0 HI_OPTION_OFFLOAD_AMSDU ;aka OFFLAOD
1 HI_OPTION_DFS_SUPPORT ;-only in newer code from 2011 or so
2 HI_OPTION_ENABLE_RFKILL ;\
3 HI_OPTION_RADIO_RETENTION_DISABLE ;
4 HI_OPTION_EARLY_CFG_DONE ; only in newer code from 2015 or so
5 HI_OPTION_DISABLE_CDC_MAX_PERF_WAR ;
6 HI_OPTION_USE_EXT_LDO ;
7 HI_OPTION_DBUART_SUPPORT ;
8 Reserved? ;
9 HT_OPTION_GPIO_WAKEUP_SUPPORT ;HT? ;/
10-31 Reserved
targaddr[C0h] - hi_acs_flags
0 HI_ACS_FLAGS_ENABLED ;ACS is enabled
1 HI_ACS_FLAGS_USE_WWAN ;Use physical WWAN device
2 HI_ACS_FLAGS_TEST_VAP ;Use test VAP
3-31 Reserved
targaddr[C4h] - hi_console_flags
0-2 HI_CONSOLE_FLAGS_UART ;UART ID (0=Default)
3 HI_CONSOLE_FLAGS_BAUD_SELECT ;Baud Select (0=9600, 1=115200)
4-30 Reserved
31 HI_CONSOLE_FLAGS_ENABLE ;Enable Console
Override REV2 ROM's app start address (whatever crap, doesn't apply to DSi)
AR6002_REV2_APP_START_OVERRIDE 0x911A00 ;\
AR6002_REV2_DATASET_PATCH_ADDRESS 0x52D8B0 ; AR6002
AR6002_REV2_APP_LOAD_ADDRESS 0x502070 ;/
AR6003_REV2_APP_START_OVERRIDE 0x944C00 ;\
AR6003_REV2_APP_LOAD_ADDRESS 0x543180 ;
AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 ; AR6003 REV2
AR6003_REV2_DATASET_PATCH_ADDRESS 0x57E884 ;
AR6003_REV2_RAM_RESERVE_SIZE 6912 ;/
AR6003_REV3_APP_START_OVERRIDE 0x945D20 ;\
AR6003_REV3_APP_LOAD_ADDRESS 0x545000 ;
AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 ; AR6003 REV3
AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FEC8 ;
AR6003_REV3_RAM_RESERVE_SIZE 512 ;
AR6003_REV3_RAM_RESERVE_SIZE_TCMD 4352 ;/
The BMI commands are used to upload the Wifi Firmware to RAM. Doing that is
required because the ROM functions themselves aren't fully functional, and the
chip can process only BMI commands or WMI commands (not both at once):
BMI Commands --> After RESET
WMI Commands --> After uploading and sending BMI_DONE
The AR6002 ROM contains about 40-50% of the program code needed to operate the
chip (and most of that ROM code is left unused, until it is getting initialized
by the firmware; so the firmware isn't just an "update", it's absolutely
required to get the chip working).
BMI Transfer
Before each BMI command, wait for LOCAL_COUNT[4] to become nonzero. Then, write
the command and parameters to MBOX0. Then read the response (if any) from MBOX0
(ideally with checking MBOX empty flag before reading response bytes; DSi code
doesn't seem to do that though - maybe the SDIO controller is automatically
waiting while MBOX empty?).
Segmented Write
The Segmented Write feature is implemented only in newer ROMs (not in DSi with
AR6002). It is invoked via BMI_CMD(03h) with destination address set to special
value 00001234h.
Send 32bit Command (00000003h) <-- same as Write Memory command
Send 32bit Address (00001234h) <-- special value for Segmented Write
Send 32bit Length (should be max 1F4h due to MBOX size)
Send LEN bytes, as described below...
The transferred data should contain a file header:
00h 4 File ID (544D4753h) ("SGMT")
04h 4 File Flags (0=Raw, 1=BMI_SGMTFILE_FLAG_COMPRESS)
Followed by one or more segments:
00h 4 Destination Address (the actual address, no special value here)
04h 4 Segment Length (N) (or special value FFFFFFFxh)
08h N Data (N bytes) (no data when N=FFFFFFFxh)
Special values for "Segment Length" (all with bit31=1):
FFFFFFFFh ;End of segmented data file (should occur as last segment)
FFFFFFFEh ;Board Data (write "hi_board_data+Address", instead raw "Address")
FFFFFFFDh ;Set App Start=Addresss; like BMI_CMD(05h)
FFFFFFFCh ;Call Address; like BMI_CMD(04h), but without param/return value
Compressed Segmented data is said to work in two ways (?):
1) Use BMI_LZ_STREAM_START with Addr=00001234h, followed by BMI_LZ_DATA, or
2) Use BMI_WRITE_MEMORY with Addr=00001234h and file header Flags=1.
Atheros has invented that weird feature for "backwards compatibility & darn
convenience", which is both sad and funny because Atheros is definitely unable
to <maintain> backwards compatibility (such as keeping the same WMI
command/event numbering in firmware revisions), but as it seems, Atheros is
believing that "backwards compatibility" is something that can be <invented> by
adding obscure features.
MBOX transfers include a small header for distinguishing between Data Packets
and Commands/Events, and for indicating the actual length (as opposed to the
MBOX transfer length, which is usually garbage-padded to 80h-byte boundary).
The exception are BMI Bootloader commands/responses (which don't have such
headers or padding).
Types
There are four data packet types (BE/BK/VI/VO), most packets are using type=2
(Best Effort), however, some weird access points are sending other types (eg.
Asus RT-AX56U has type=4 (video) in WPA2/EAPOL handshakes). Basically, one can
ignore that, and simply all types in range 2,3,4,5 as data packets.
Notes
Data Packet Type is usually 02h=BE (best effort),
The send/receive DATA headers are apparently containing incomplete wifi "Frame
Headers":
without 3rd address field
without WEP entries (those are apparently automatically inserted)
without Frame Control, Duration/ID, Sequence Control
there seem to be only Data Frames (no Managment/Control Frames)
That, unless some of the missing info would be encoded in the <Unknown> header
entries.
WMIcmd(0004h) - WMI_SYNCHRONIZE_CMD
Parameters (01h bytes):
00h A_UINT8 1 dataSyncMap ;00h, 01h, or 09h used?
WMIcmd(000Ah) - WMI_SET_PROBED_SSID_CMD
Parameters (23h bytes):
00h A_UINT8 1 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX
01h A_UINT8 1 flag; /* WMI_SSID_FLG
02h A_UINT8 1 ssidLength;
03h A_UINT8 32 ssid[32];
#define MAX_PROBED_SSID_INDEX = 15
WMI_SSID_FLAG values:
DISABLE_SSID_FLAG = 00h /* disables entry
SPECIFIC_SSID_FLAG = 01h /* probes specified ssid
ANY_SSID_FLAG = 02h /* probes for any ssid
WMIcmd(000Bh) - WMI_SET_LISTEN_INT_CMD
Parameters (04h bytes):
00h A_UINT16 2 listenInterval;
02h A_UINT16 2 numBeacons;
The Listen interval is between 15 and 3000 TUs
MIN_LISTEN_INTERVAL = 15 ;min = 15
MAX_LISTEN_INTERVAL = 5000 ;max = 5000 or 3000, uh?
MIN_LISTEN_BEACONS = 1
MAX_LISTEN_BEACONS = 500
WMIcmd(000Ch) - WMI_SET_BMISS_TIME_CMD
Parameters (04h bytes):
00h A_UINT16 2 bmissTime;
02h A_UINT16 2 numBeacons;
Valid values are between 1000 and 5000 TUs
MIN_BMISS_TIME = 1000
MAX_BMISS_TIME = 5000
MIN_BMISS_BEACONS = 1
MAX_BMISS_BEACONS = 50
WMIcmd(000Fh) - WMI_SET_BEACON_INT_CMD
Parameters (02h bytes):
00h A_UINT16 2 beaconInterval;
WMIcmd(001Ah) - WMI_SET_PMKID_CMD
Parameters:
00h A_UINT8 6 bssid[ATH_MAC_LEN];
06h A_UINT8 1 enable; /* PMKID_ENABLE_FLG
07h A_UINT8 16 pmkid[WMI_PMKID_LEN];
#define WMI_PMKID_LEN = 16
PMKID_ENABLE_FLG values:
PMKID_DISABLE = 0
PMKID_ENABLE = 1
WMIcmd(001Dh) - WMI_SET_ASSOC_INFO_CMD
Parameters:
00h A_UINT8 1 ieType
01h A_UINT8 1 bufferSize
02h A_UINT8 N*1 assocInfo[1] ;up to WMI_MAX_ASSOC_INFO_LEN
A maximum of 2 private IEs can be sent in the [Re]Assoc request.
A 3rd one, the CCX version IE can also be set from the host.
WMI_MAX_ASSOC_INFO_TYPE = 2
WMI_CCX_VER_IE = 2 /* ieType to set CCX Version IE
WMI_MAX_ASSOC_INFO_LEN = 240
WMIcmd(001Eh) - WMI_ADD_BAD_AP_CMD
Parameters (07h bytes):
00h A_UINT8 1 badApIndex ;0 to WMI_MAX_BAD_AP_INDEX
01h A_UINT8 6 bssid[ATH_MAC_LEN]
WMI_MAX_BAD_AP_INDEX = 1
WMIcmd(001Fh) - WMI_DELETE_BAD_AP_CMD
Parameters (01h bytes):
00h A_UINT8 1 badApIndex ;0 to WMI_MAX_BAD_AP_INDEX
WMIcmd(0023h) - WMI_SET_ACCESS_PARAMS_CMD
Parameters:
00h A_UINT16 2 txop ;in units of 32 usec
02h A_UINT8 1 eCWmin
03h A_UINT8 1 eCWmax
04h A_UINT8 1 aifsn
05h A_UINT8 1 ac
WMI_DEFAULT_TXOP_ACPARAM = 0 /* implies one MSDU
WMI_DEFAULT_ECWMIN_ACPARAM = 4 /* corresponds to CWmin of 15
WMI_DEFAULT_ECWMAX_ACPARAM = 10 /* corresponds to CWmax of 1023
WMI_MAX_CW_ACPARAM = 15 /* maximum eCWmin or eCWmax
WMI_DEFAULT_AIFSN_ACPARAM = 2
WMI_MAX_AIFSN_ACPARAM = 15
WMIcmd(0025h) - WMI_SET_OPT_MODE_CMD
Parameters (01h bytes on DSi?, but parameter structure is undocumented):
00h A_UINT8 optMode (documented in code from 2008 only)
OPT_MODE_TYPE values:
SPECIAL_OFF = unknown (maybe 0 or 1 or so) ;\
SPECIAL_ON = SPECIAL_OFF+1 ; code from 2008 only
PYXIS_ADHOC_ON = SPECIAL_OFF+2 ; (removed/undoc in 2010)
PYXIS_ADHOC_OFF = SPECIAL_OFF+3 ;/
WMIcmd(0026h) - WMI_OPT_TX_FRAME_CMD
Unknown/undocumented purpose. Unknown if/how this is implemented in DSi. The
DSi does redirect cmd 0026h to a function handler, but that handler does just
trigger a misalign exception. However, the DSi does also have a function for
handling the command (with "opt_tx_frame_cmd" string in AR6013/AR6014), but
that function doesn't seem to be called upon command number 0026h. Maybe the
CMD is triggered upon special flags in the SDIO transfer block header, rather
than by the command number?
Parameters (11h bytes on DSi)
Unknown (11h bytes, but parameter structure is undocumented)
See also: WMI_OPT_RX_FRAME_EVENT (counterpart in opposite direction), and
WMI_SET_OPT_MODE_CMD.
WMIcmd(0027h) - WMI_SET_VOICE_PKT_SIZE_CMD
Parameters (02h bytes):
00h A_UINT16 2 voicePktSize
WMIcmd(0028h) - WMI_SET_MAX_SP_LEN_CMD
Parameters (01h bytes):
00h A_UINT8 1 maxSPLen
APSD_SP_LEN_TYPE values:
DELIVER_ALL_PKT = 00h
DELIVER_2_PKT = 01h
DELIVER_4_PKT = 02h
DELIVER_6_PKT = 03h
WMIcmd(0031h) - WMI_SET_LPREAMBLE_CMD
Parameters (01h bytes on DSi?, but other sources claim 02h bytes):
01h 02h <---- total size (on DSi it's 01h, ie. left column)
00h 00h A_UINT8 1 status
-- 01h A_UINT8 1 preamblePolicy
WMI_LPREAMBLE_STATUS values:
WMI_LPREAMBLE_DISABLED = 0
WMI_LPREAMBLE_ENABLED = 1
WMI_PREAMBLE_POLICY values:
WMI_IGNORE_BARKER_IN_ERP = 0
WMI_DONOT_IGNORE_BARKER_IN_ERP = 1
WMIcmd(0032h) - WMI_SET_RTS_CMD
Parameters (02h bytes):
00h A_UINT16 2 threshold
WMIcmd(0038h) - WMI_SET_WMM_CMD
Parameters (01h bytes):
00h A_UINT8 1 status
WMI_WMM_STATUS values:
WMI_WMM_DISABLED = 0
WMI_WMM_ENABLED = 1
WMM stands for Wi-Fi Multimedia (WMM) aka Wireless Multimedia Extensions (WME)
aka some QOS related stuff?
"WMM prioritizes traffic according to four Access Categories (AC): voice
(AC_VO), video (AC_VI), best effort (AC_BE), and background (AC_BK)."
WMIcmd(0039h) - WMI_SET_WMM_TXOP_CMD
Parameters (01h bytes):
00h A_UINT8 1 txopEnable
WMI_TXOP_CFG values:
WMI_TXOP_DISABLED = 0
WMI_TXOP_ENABLED = 1
WMIcmd(003Dh) - WMI_SET_KEEPALIVE_CMD
Parameters (01h bytes):
00h A_UINT8 1 keepaliveInterval ;MAYBE in seconds? usually 00h=what?
...Developer commands...
WMIevent(000Eh) - WMI_GET_CHANNEL_LIST_CMD
WMIevent(001Ch) - WMI_GET_TX_PWR_CMD
WMIevent(0035h) - WMI_GET_FIXRATES_CMD
WMIevent(003Eh) - WMI_GET_KEEPALIVE_CMD
WMIevent(F001h) - WMI_GET_BITRATE_CMD
Events/Responses with same ID as corresponding command.
See corresponding commands for description of reply data.
WMIevent(1001h) - WMI_READY_EVENT
This event exists with numerous (incorrect) definitions, claiming the event
data to be 07h, 0Bh, 0Ch, 0Fh, or 10h bytes in length:
Event Data (0Ch bytes on DSi, as returned by DSi firmware):
00h A_UINT8 6 macaddr[ATH_MAC_LEN] ;MAC addr of DSi console
06h A_UINT8 1 phyCapability (=02h aka "11G") ;WMI_PHY_CAPABILITY
07h A_UINT8 1 unused/padding
08h A_UINT32 4 version (=2100007Bh/2300006Ch) (firmware version)
Event Data (07h bytes, exists in AR6002 ROM, but overridden by DSi firmware):
00h A_UINT8 6 macaddr[ATH_MAC_LEN]
06h A_UINT8 1 phyCapability ;WMI_PHY_CAPABILITY
Event Data (0Bh bytes, accidently claimed to be so in source code from 2008):
00h A_UINT32 4 version
04h A_UINT8 6 macaddr[ATH_MAC_LEN]
0Ah A_UINT8 1 phyCapability ;WMI_PHY_CAPABILITY
Event Data (0Fh bytes, accidently claimed to be so in source code from 2010):
00h A_UINT32 4 sw_version
04h A_UINT32 4 abi_version
08h A_UINT8 6 macaddr[ATH_MAC_LEN]
0Eh A_UINT8 1 phyCapability ;WMI_PHY_CAPABILITY
Event Data (10h bytes, as done by 3DS function in wifi firmware RAM):
00h A_UINT8 6 macaddr[ATH_MAC_LEN] ;MAC addr of DSi console
06h A_UINT8 1 phyCapability (=02h aka "11G") ;WMI_PHY_CAPABILITY
07h A_UINT8 1 unused/padding
08h A_UINT32 4 version (230000B3h) (firmware version)
0Ch A_UINT16 2 whus ;=[004134h] ;some I/O register ???
0Eh A_UINT16 2 what ;=[520088h] ;hi_hci_uart_baud ???
WMI_PHY_CAPABILITY values (maybe the "11" is related to "IEEE 802.11"?):
WMI_11A_CAPABILITY = 1
WMI_11G_CAPABILITY = 2
WMI_11AG_CAPABILITY = 3
WMI_11NA_CAPABILITY = 4
WMI_11NG_CAPABILITY = 5
WMI_11NAG_CAPABILITY = 6
WMIevent(1008h) - WMI_NEIGHBOR_REPORT_EVENT
Event Data:
typedef PREPACK struct {
00h A_INT8 1 numberOfAps;
01h WMI_NEIGHBOR_INFO N*7 neighbor[1];
WMI_NEIGHBOR_INFO structure:
A_UINT8 6 bssid[ATH_MAC_LEN];
A_UINT8 1 bssFlags; /* see WMI_BSS_FLAGS
WMI_BSS_FLAGS values:
WMI_DEFAULT_BSS_FLAGS = 00h
WMI_PREAUTH_CAPABLE_BSS = 01h
WMI_PMKID_VALID_BSS = 02h
The WMI_NEIGHBOR_REPORT Event is generated by the target to inform the host of
BSS's it has found that matches the current profile.
It can be used by the host to cache PMKs and/to initiate pre-authentication if
the BSS supports it. The first bssid is always the current associated BSS.
The bssid and bssFlags information repeats according to the number or APs
reported.
WMIevent(1011h) - WMI_CAC_EVENT
Supposedly related to Call Admission Control (CAC), eg. for VoIP.
Event Data (42h bytes):
00h A_UINT8 1 ac;
01h A_UINT8 1 cac_indication;
02h A_UINT8 1 statusCode;
03h A_UINT8 3Fh tspecSuggestion[WMM_TSPEC_IE_LEN];
CAC_INDICATION values:
CAC_INDICATION_ADMISSION = 00h
CAC_INDICATION_ADMISSION_RESP = 01h
CAC_INDICATION_DELETE = 02h
CAC_INDICATION_NO_RESP = 03h
#define WMM_TSPEC_IE_LEN = 63
WMIevent(1017h) - WMI_APLIST_EVENT
Event Data:
00h A_UINT8 1 apListVer;
01h A_UINT8 1 numAP;
02h WMI_AP_INFO N*8 apList[1];
APLIST_VER values (only one defined):
APLIST_VER1 = 1,
WMI_AP_INFO structure:
typedef PREPACK union {
WMI_AP_INFO_V1 8 apInfoV1;
} POSTPACK WMI_AP_INFO;
WMI_AP_INFO_V1 structure:
A_UINT8 6 bssid[ATH_MAC_LEN];
A_UINT16 2 channel;
WMIcmd(0001h) - WMI_CONNECT_CMD
Parameters (34h bytes):
00h A_UINT8 1 networkType ;somewhat NETWORK_TYPE related ? (1)
01h A_UINT8 1 dot11AuthMode ;aka DOT11_AUTH_MODE ? (1=Open, 2=WEP)
02h A_UINT8 1 authMode ;aka AUTH_MODE ? (1)
03h A_UINT8 1 pairwiseCryptoType ;aka CRYPTO_TYPE (1=Open, 2=WEP)
04h A_UINT8 1 pairwiseCryptoLen (0)
05h A_UINT8 1 groupCryptoType ;aka CRYPTO_TYPE (1=Open, 2=WEP)
06h A_UINT8 1 groupCryptoLen (0)
07h A_UINT8 1 ssidLength
08h A_UCHAR 32 ssid[WMI_MAX_SSID_LEN]
28h A_UINT16 2 channel ;in MHz
2Ah A_UINT8 6 bssid[ATH_MAC_LEN]
30h A_UINT32 4 ctrl_flags (0)
Returns WMI_CONNECT_EVENT (or WMI_DISCONNECT_EVENT, eg. upon bad WEP password).
NETWORK_TYPE values:
INFRA_NETWORK = 01h ;DSi uses 01h for Open/WEP/WPA/WPA2
ADHOC_NETWORK = 02h
ADHOC_CREATOR = 04h
AP_NETWORK = 10h
NETWORK_SUBTYPE values (unknown purpose, and unknown if they start at 0 or 1 or
so):
SUBTYPE_NONE = unknown (maybe 0 or 1 or so?)
SUBTYPE_BT = SUBTYPE_NONE+1
SUBTYPE_P2PDEV = SUBTYPE_NONE+2
SUBTYPE_P2PCLIENT = SUBTYPE_NONE+3
SUBTYPE_P2PGO = SUBTYPE_NONE+4
DOT11_AUTH_MODE values:
OPEN_AUTH = 01h ;DSi uses 01h for Open/WPA/WPA2
SHARED_AUTH = 02h ;DSi uses 02h for WEP
LEAP_AUTH = 04h /* different from IEEE_AUTH_MODE definitions
AUTH_MODE values:
WMI_NONE_AUTH = 01h ;DSi uses 01h for Open/WEP
WMI_WPA_AUTH = 02h ;\whatever maybe for RADIUS?
WMI_WPA2_AUTH = 04h ;/
WMI_WPA_PSK_AUTH = 08h ;DSi uses 03h (not 08h) for WPA-PSK
WMI_WPA2_PSK_AUTH = 10h ;DSi uses 05h (not 10h) for WPA2-PSK
WMI_WPA_AUTH_CCKM = 20h ;\whatever for "Cisco Centralized Key Management"?
WMI_WPA2_AUTH_CCKM = 40h ;/
CRYPTO_TYPE values:
NONE_CRYPT = 01h ;DSi uses 01h for Open
WEP_CRYPT = 02h ;DSi uses 02h for WEP
TKIP_CRYPT = 04h ;DSi uses 03h (not 04h) for WPA
AES_CRYPT = 08h ;DSi uses 04h (not 08h) for WPA2
WAPI_CRYPT = 10h ;only if WAPI_ENABLE
connect "ctrl_flags":
0 CONNECT_ASSOC_POLICY_USER = 0001h
1 CONNECT_SEND_REASSOC = 0002h
2 CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0004h
3 CONNECT_PROFILE_MATCH_DONE = 0008h
4 CONNECT_IGNORE_AAC_BEACON = 0010h
5 CONNECT_CSA_FOLLOW_BSS = 0020h
6 CONNECT_PYXIS_REMOTE = 0040h ;-old code from 2008
6 CONNECT_DO_WPA_OFFLOAD = 0040h ;\
7 CONNECT_DO_NOT_DEAUTH = 0080h ; new code from 2010
8 CONNECT_WPS_FLAG = 0100h ;
9 CONNECT_IGNORE_BSSID_HINT = 0200h ;
16 AP_NO_DISASSOC_UPON_DEAUTH = 10000h ;/ <--AP configuration flags
DEFAULT_CONNECT_CTRL_FLAGS = (CONNECT_CSA_FOLLOW_BSS)
WMIcmd(0002h) - WMI_RECONNECT_CMD
Parameters (optional...?... 08h bytes):
00h A_UINT16 2 channel ;hint
02h A_UINT8 6 bssid[ATH_MAC_LEN] ;mandatory if set
WMIcmd(0003h) - WMI_DISCONNECT_CMD
Parameters:
Unknown (none?)
Returns WMI_DISCONNECT_EVENT. Uhm, or seems to crash on AR6013...?
WMIevent(1002h) - WMI_CONNECT_EVENT
First 10h bytes of response can be "infra_ibss_bss" or "ap_sta" or "ap_bss"
(unclear which selects/indicates which it is, maybe the parameters from
preceeding WMI_CONNECT_CMD, or from WMI_BSSINFO_EVENT's frame body?)
Upon error, DISCONNECT_EVENT is sent instead of WMI_CONNECT_EVENT (eg. when
using WMI_CONNECT with wrong WEP password).
Event Data:
When "infra_ibss_bss": ;<-- occurs for my WPA2 connect
00h A_UINT16 2 channel ;in MHz
02h A_UINT8 6 bssid[ATH_MAC_LEN] ;
08h A_UINT16 2 listenInterval ;0064h
0Ah A_UINT16 2 beaconInterval ;0064h
0Ch A_UINT32 4 networkType ;00000001h
When "ap_sta":
00h A_UINT8 1 phymode
01h A_UINT8 1 aid
02h A_UINT8 6 mac_addr[ATH_MAC_LEN]
08h A_UINT8 1 auth
09h A_UINT8 1 keymgmt
0Ah A_UINT16 2 cipher
0Ch A_UINT8 1 apsd_info
0Dh A_UINT8 3 unused[3]
When "ap_bss":
00h A_UINT16 2 channel
02h A_UINT8 6 bssid[ATH_MAC_LEN]
08h A_UINT8 8 unused[8]
And, in all three cases:
10h A_UINT8 1 beaconIeLen ;16h
11h A_UINT8 1 assocReqLen ;2Fh
12h A_UINT8 1 assocRespLen ;16h
13h A_UINT8 .. assocInfo[1] ;whatever 100 bytes?
In STA mode networkType comes along with connected phy mode.
To get networkType, WMI_NETWORK_TYPE (networkType).
To get connected phymode, WMI_CONNECTED_PHYMODE(networkType) will give the
phymode value.
WMIevent(1003h) - WMI_DISCONNECT_EVENT
This event can occur when using WMI_CONNECT with wrong WEP password (instead of
WMI_CONNECT_EVENT), or when failing to respond to WPA/WPA2 handshake messages,
or when using WMI_DISCONNECT.
Event Data (0Ah+N bytes):
00h A_UINT16 2 protocolReasonStatus ;reason code, see 802.11 spec.
02h A_UINT8 6 bssid[ATH_MAC_LEN] ;set if known
08h A_UINT8 1 disconnectReason ;see WMI_DISCONNECT_REASON
09h A_UINT8 1 assocRespLen (00h=none)
0Ah A_UINT8 N*1 assocInfo[1]
WMI_DISCONNECT_REASON values:
NO_NETWORK_AVAIL = 01h ;-occurs on wrong WEP key
LOST_LINK = 02h ;-bmiss
DISCONNECT_CMD = 03h ;-requested via disconnect command
BSS_DISCONNECTED = 04h ;-occurs after some minutes of inactivity?
AUTH_FAILED = 05h ;-reportedly occurs if AP was already connected?
ASSOC_FAILED = 06h
NO_RESOURCES_AVAIL = 07h
CSERV_DISCONNECT = 08h
INVALID_PROFILE = 0Ah
DOT11H_CHANNEL_SWITCH = 0Bh
PROFILE_MISMATCH = 0Ch
PYXIS_VIRT_ADHOC_DISC = 0Dh ;-old code from 2008
CONNECTION_EVICTED = 0Dh ;\
IBSS_MERGE = 0Eh ; new code from 2010
EXCESS_TX_RETRY = 0Fh ;/ <--TX frames failed after excessive retries
WMIcmd(0016h) - WMI_ADD_CIPHER_KEY_CMD
Parameters (2Dh bytes on DSi?, but other sources claim 2Ch or 33h bytes):
2Ch 2Dh 33h <---- total size (on DSi it's 2Dh, ie. middle column)
00h 00h 00h A_UINT8 1 keyIndex ;aka WMI_MAX_KEY_INDEX ?
01h 01h 01h A_UINT8 1 keyType ;aka CRYPTO_TYPE
02h 02h 02h A_UINT8 1 keyUsage ;KEY_USAGE
03h 03h 03h A_UINT8 1 keyLength
04h 04h 04h A_UINT8 8 keyRSC[8] ;key replay sequence counter
0Ch 0Ch 0Ch A_UINT8 32 key[WMI_MAX_KEY_LEN] ;aka password
-- 2Ch 2Ch A_UINT8 1 key_op_ctrl ;Additional Key Control information
-- -- 2Dh A_UINT8 6 key_macaddr[ATH_MAC_LEN]
KEY_USAGE values:
PAIRWISE_USAGE = 00h ;<-- DSi browser uses THIS for WPA/WPA2 key 0
GROUP_USAGE = 01h ;<-- DSi browser uses THIS for WEP/WPA/WPA2 key 1..3
TX_USAGE = 02h ;<-- reportedly "default Tx Key - Static WEP only"
Undoc (or 01h+02h) = 03h ;<-- DSi browser uses THIS for WEP key 0
Bit Flag. (aka key_op_ctrl values?):
Bit 0 - Initialise TSC - default is Initialize
KEY_OP_INIT_TSC = 01h
KEY_OP_INIT_RSC = 02h
KEY_OP_INIT_WAPIPN = 10h (only if "WAPI_ENABLE")
KEY_OP_INIT_VAL = 03h ;<-- Default Initialise the TSC & RSC ;used by DSi
KEY_OP_VALID_MASK = 03h
More constants:
WMI_MIN_KEY_INDEX = 0
WMI_MAX_KEY_INDEX = 3 ;<-- when not "WAPI_ENABLE"
WMI_MAX_KEY_INDEX = 7 ;<-- when "WAPI_ENABLE" (wapi grpKey 0-3, prwKey 4-7)
WMI_MAX_KEY_LEN = 32
WEP Cipher Keys
All four keys (with KeyIndex=0..3) must be set before WMI_CONNECT_CMD. The
NDS/DSi user interface allows to define only one WEP key 0, but one must add
dummy keys for key 1..3, else connect will fail.
WPA/WPA2 Cipher Keys
For WPA/WPA2, WMI_CONNECT_CMD isn't working fully automated: After
WMI_CONNECT_EVENT, one must manually receive & reply EAPOL handshake messages,
and then add the cipher keys based on the message contents. The used keys are
key 0 (for pairwise cipher), and key 1 or 2 (for the current group cipher key).
--> DS Wifi WPA/WPA2 Handshake Messages (EAPOL)
--> DS Wifi WPA/WPA2 Keys and MICs
--> DS Wifi WPA/WPA2 Encryption
--> DS Firmware Wifi Calibration Data
--> DS Firmware Wifi Internet Access Points
Moreover, the access point may throw further EAPOL messages for assigning new
group keys every once and then, and one must also manually apply that new key
via ADD_CIPHER (the group key index switches between 1 and 2 on each update).
KeyIndex=0, key=PTK[20h..2Fh]+PTK[38h..3Fh]+PTK[30h..37h], RSC=0
KeyIndex=1/2, key=GTK[00h..0Fh]+PTK[18h..1Fh]+PTK[10h..17h], RSC=EAPOL RSC
WAPI Cipher Keys
Some atheros firmwares have "WAPI_ENABLE" with eight key indices (grpKey=0..3,
prwKey=4..7). The DSi firmware probably doesn't have that WAPI stuff.
WMIcmd(0020h) - WMI_SET_TKIP_COUNTERMEASURES_CMD
Parameters (01h bytes):
00h A_UINT8 1 cm_en ;WMI_TKIP_CM_CONTROL
WMI_TKIP_CM_CONTROL values:
WMI_TKIP_CM_DISABLE = 00h
WMI_TKIP_CM_ENABLE = 01h
Note: There are also "CM_CONNECT_TYPE" values in "cnxmgmt.h", is THAT related?
WMIevent(1009h) - WMI_TKIP_MICERR_EVENT
Event Data (02h bytes):
00h A_UINT8 1 keyid
01h A_UINT8 1 ismcast
TKIP MIC Error Event
WMIcmd(0007h) - WMI_START_SCAN_CMD
Parameters (theoretically 12h+N*2 bytes, but 14h bytes when N=0 ?):
00h A_BOOL 4 forceFgScan
04h A_BOOL 4 isLegacy For Legacy Cisco AP compatibility
08h A_UINT32 4 homeDwellTime Max duration in the home channel (msec)
0Ch A_UINT32 4 forceScanInterval Time interval between scans (msec)
10h A_UINT8 1 scanType WMI_SCAN_TYPE
11h A_UINT8 1 numChannels how many channels follow
12h A_UINT16 N*2 channelList[1] channels in MHz
WMI_SCAN_TYPE values:
WMI_LONG_SCAN = 0
WMI_SHORT_SCAN = 1
Old code from 2008 did (additionally) use value 0 and 1 as so:
WMI_PYXIS_PAS_DSCVR = 0
WMI_PYXIS_ACT_DSCVR = 1
The DSi Browser receives one or more WMI_BSSINFO_EVENT's (if there are any
beacons on the current channel), and, once when the DwellTime (mul5?) has
ellapsed, finally receives WMI_SCAN_COMPLETE_EVENT.
WMIcmd(0008h) - WMI_SET_SCAN_PARAMS_CMD
Parameters (14h bytes):
00h A_UINT16 2 fg_start_period ;seconds
02h A_UINT16 2 fg_end_period ;seconds
04h A_UINT16 2 bg_period ;seconds
06h A_UINT16 2 maxact_chdwell_time ;msec
08h A_UINT16 2 pas_chdwell_time ;msec
0Ah A_UINT8 1 shortScanRatio ;how many shorts scan for one long
0Bh A_UINT8 1 scanCtrlFlags
0Ch A_UINT16 2 minact_chdwell_time ;msec
0Eh A_UINT16 2 maxact_scan_per_ssid ;max active scans per ssid
10h A_UINT32 4 max_dfsch_act_time ;msec
#define WMI_SHORTSCANRATIO_DEFAULT = 3
Warning: ScanCtrlFlag value of FFh is used to disable all flags in
WMI_SCAN_PARAMS_CMD
Do not add any more flags to WMI_SCAN_CTRL_FLAG_BITS
WMI_SCAN_CTRL_FLAGS_BITS:
CONNECT_SCAN_CTRL_FLAGS = 01h ;set if can scan in the Connect cmd
SCAN_CONNECTED_CTRL_FLAGS = 02h ;set if scan for the SSID it is
; already connected to
ACTIVE_SCAN_CTRL_FLAGS = 04h ;set if enable active scan
ROAM_SCAN_CTRL_FLAGS = 08h ;set if enable roam scan when bmiss
; and lowrssi
REPORT_BSSINFO_CTRL_FLAGS = 10h ;set if follows customer BSSINFO
; reporting rule
ENABLE_AUTO_CTRL_FLAGS = 20h ;if disabled, target doesn't
; scan after a disconnect event
ENABLE_SCAN_ABORT_EVENT = 40h ;Scan complete event with canceled status
; will be generated when a scan is
; prempted before it gets completed
#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS)
#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS)
#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS)
#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS)
#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS)
#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS)
#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT)
WMIevent(100Ah) - WMI_SCAN_COMPLETE_EVENT
Event Data (old: None, or new: status, 04h bytes):
00h A_INT32 4 status; ;aka "staus"
(whatever, usually/always zero)
(can be 10h... when already connected maybe?)
WMI_BIT_RATE values
Mbit/s = Index Mbit/s = Mask
RATE_AUTO = -1 - = -
RATE_1Mb = 0 FIX_RATE_1Mb = 1h
RATE_2Mb = 1 FIX_RATE_2Mb = 2h
RATE_5_5Mb = 2 FIX_RATE_5_5Mb = 4h
RATE_11Mb = 3 FIX_RATE_11Mb = 8h
RATE_6Mb = 4 FIX_RATE_6Mb = 10h
RATE_9Mb = 5 FIX_RATE_9Mb = 20h
RATE_12Mb = 6 FIX_RATE_12Mb = 40h
RATE_18Mb = 7 FIX_RATE_18Mb = 80h
RATE_24Mb = 8 FIX_RATE_24Mb = 100h
RATE_36Mb = 9 FIX_RATE_36Mb = 200h
RATE_48Mb = 10 FIX_RATE_48Mb = 400h
RATE_54Mb = 11 FIX_RATE_54Mb = 800h
Below only for newer (non-DSi) revisions (with 32bit RATE_MASK values):
RATE_MCS_0_20 = 12 FIX_RATE_MCS_0_20 = 1000h
RATE_MCS_1_20 = 13 FIX_RATE_MCS_1_20 = 2000h
RATE_MCS_2_20 = 14 FIX_RATE_MCS_2_20 = 4000h
RATE_MCS_3_20 = 15 FIX_RATE_MCS_3_20 = 8000h
RATE_MCS_4_20 = 16 FIX_RATE_MCS_4_20 = 10000h
RATE_MCS_5_20 = 17 FIX_RATE_MCS_5_20 = 20000h
RATE_MCS_6_20 = 18 FIX_RATE_MCS_6_20 = 40000h
RATE_MCS_7_20 = 19 FIX_RATE_MCS_7_20 = 80000h
RATE_MCS_0_40 = 20 FIX_RATE_MCS_0_40 = 100000h
RATE_MCS_1_40 = 21 FIX_RATE_MCS_1_40 = 200000h
RATE_MCS_2_40 = 22 FIX_RATE_MCS_2_40 = 400000h
RATE_MCS_3_40 = 23 FIX_RATE_MCS_3_40 = 800000h
RATE_MCS_4_40 = 24 FIX_RATE_MCS_4_40 = 1000000h
RATE_MCS_5_40 = 25 FIX_RATE_MCS_5_40 = 2000000h
RATE_MCS_6_40 = 26 FIX_RATE_MCS_6_40 = 4000000h
RATE_MCS_7_40 = 27 FIX_RATE_MCS_7_40 = 8000000h
Get bit rate cmd uses same definition as set bit rate cmd
WMIcmd(0021h) - WMI_RSSI_THRESHOLD_PARAMS_CMD
Parameters (20h bytes):
00h A_UINT32 4 pollTime ;Polling time as a factor of LI
04h A_INT16 2 thresholdAbove1_Val ;lowest of upper
06h A_INT16 2 thresholdAbove2_Val
08h A_INT16 2 thresholdAbove3_Val
0Ah A_INT16 2 thresholdAbove4_Val
0Ch A_INT16 2 thresholdAbove5_Val
0Eh A_INT16 2 thresholdAbove6_Val ;highest of upper
10h A_INT16 2 thresholdBelow1_Val ;lowest of bellow
12h A_INT16 2 thresholdBelow2_Val
14h A_INT16 2 thresholdBelow3_Val
16h A_INT16 2 thresholdBelow4_Val
18h A_INT16 2 thresholdBelow5_Val
1Ah A_INT16 2 thresholdBelow6_Val ;highest of bellow
1Ch A_UINT8 1 weight ;"alpha"
1Dh A_UINT8 3 reserved[3]
Setting the polltime to 0 would disable polling.
Threshold values are in the ascending order, and should agree to:
(lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal
< highThreshold_upperVal)
See also: WMI_RSSI_THRESHOLD_EVENT
WMIcmd(002Fh) - WMI_SNR_THRESHOLD_PARAMS_CMD
Parameters (10h bytes):
00h A_UINT32 4 pollTime ;Polling time as a factor of LI
04h A_UINT8 1 weight ;"alpha"
05h A_UINT8 1 thresholdAbove1_Val ;lowest of uppper ;uh, ppper?
06h A_UINT8 1 thresholdAbove2_Val
07h A_UINT8 1 thresholdAbove3_Val
08h A_UINT8 1 thresholdAbove4_Val ;highest of upper
09h A_UINT8 1 thresholdBelow1_Val ;lowest of bellow ;uh bell?
0Ah A_UINT8 1 thresholdBelow2_Val
0Bh A_UINT8 1 thresholdBelow3_Val
0Ch A_UINT8 1 thresholdBelow4_Val ;highest of bellow ;uh bell?
0Dh A_UINT8 3 reserved[3]
Setting the polltime to 0 would disable polling.
See also: WMI_SNR_THRESHOLD_EVENT
WMIcmd(0030h) - WMI_LQ_THRESHOLD_PARAMS_CMD
Parameters (0Ch bytes):
00h A_UINT8 1 enable ;<-- enable (unlike SNR command)
01h A_UINT8 1 thresholdAbove1_Val ;\these parameters seem to be same as
02h A_UINT8 1 thresholdAbove2_Val ; for WMI_SNR_THRESHOLD_PARAMS_CMD
03h A_UINT8 1 thresholdAbove3_Val ;
04h A_UINT8 1 thresholdAbove4_Val ;
05h A_UINT8 1 thresholdBelow1_Val ;
06h A_UINT8 1 thresholdBelow2_Val ;
07h A_UINT8 1 thresholdBelow3_Val ;
08h A_UINT8 1 thresholdBelow4_Val ;
09h A_UINT8 3 reserved[3] ;/
See also: WMI_LQ_THRESHOLD_EVENT
WMIcmd(0033h) - WMI_CLR_RSSI_SNR_CMD
Parameters:
Unknown (none?)
Probably somehow related to RSSI_THRESHOLD and SNR_THRESHOLD.
WMIevent(100Ch) - WMI_RSSI_THRESHOLD_EVENT
Event Data (03h bytes):
00h A_INT16 2 rssi
02h A_UINT8 1 range
WMI_RSSI_THRESHOLD_VAL values (which are probably meant to occurr in one of
above fields, unclear which one though):
WMI_RSSI_THRESHOLD1_ABOVE = 0
WMI_RSSI_THRESHOLD2_ABOVE = 1
WMI_RSSI_THRESHOLD3_ABOVE = 2
WMI_RSSI_THRESHOLD4_ABOVE = 3
WMI_RSSI_THRESHOLD5_ABOVE = 4
WMI_RSSI_THRESHOLD6_ABOVE = 5
WMI_RSSI_THRESHOLD1_BELOW = 6
WMI_RSSI_THRESHOLD2_BELOW = 7
WMI_RSSI_THRESHOLD3_BELOW = 8
WMI_RSSI_THRESHOLD4_BELOW = 9
WMI_RSSI_THRESHOLD5_BELOW = 10
WMI_RSSI_THRESHOLD6_BELOW = 11
Indicate the RSSI events to host. Events are indicated when we breach a
thresold value. (uh, how old do we breach?)
WMIevent(1012h) - WMI_SNR_THRESHOLD_EVENT
Event Data (02h bytes):
00h A_UINT8 1 range ;WMI_SNR_THRESHOLD_VAL
01h A_UINT8 1 snr
WMI_SNR_THRESHOLD_VAL values:
WMI_SNR_THRESHOLD1_ABOVE = 1
WMI_SNR_THRESHOLD1_BELOW = 2
WMI_SNR_THRESHOLD2_ABOVE = 3
WMI_SNR_THRESHOLD2_BELOW = 4
WMI_SNR_THRESHOLD3_ABOVE = 5
WMI_SNR_THRESHOLD3_BELOW = 6
WMI_SNR_THRESHOLD4_ABOVE = 7
WMI_SNR_THRESHOLD4_BELOW = 8
WMIevent(1013h) - WMI_LQ_THRESHOLD_EVENT
Event Data (05h bytes):
00h A_INT32 4 lq
04h A_UINT8 1 range ;WMI_LQ_THRESHOLD_VAL
WMI_LQ_THRESHOLD_VAL values:
WMI_LQ_THRESHOLD1_ABOVE = 1
WMI_LQ_THRESHOLD1_BELOW = 2
WMI_LQ_THRESHOLD2_ABOVE = 3
WMI_LQ_THRESHOLD2_BELOW = 4
WMI_LQ_THRESHOLD3_ABOVE = 5
WMI_LQ_THRESHOLD3_BELOW = 6
WMI_LQ_THRESHOLD4_ABOVE = 7
WMI_LQ_THRESHOLD4_BELOW = 8
WMIcmd(0024h) - WMI_SET_RETRY_LIMITS_CMD
Parameters:
00h A_UINT8 1 frameType ;WMI_FRAMETYPE
01h A_UINT8 1 trafficClass ;applies only to DATA_FRAMETYPE
02h A_UINT8 1 maxRetries
03h A_UINT8 1 enableNotify
This command is used to customize the number of retries the wlan device will
perform on a given frame.
WMI_MIN_RETRIES = 2
WMI_MAX_RETRIES = 13
WMI_FRAMETYPE values:
MGMT_FRAMETYPE = 0
CONTROL_FRAMETYPE = 1
DATA_FRAMETYPE = 2
WMIcmd(0022h) - WMI_TARGET_ERROR_REPORT_BITMASK_CMD
Parameters (04h bytes):
00h A_UINT32 4 bitmask ;... probably "WMI_TARGET_ERROR_VAL" ?
Sets the error reporting event bitmask in target. Target clears it upon an
error. Subsequent errors are counted, but not reported via event, unless the
bitmask is set again.
See also: WMI_TARGET_ERROR_REPORT_EVENT
WMIevent(1014h) - WMI_TX_RETRY_ERR_EVENT
Event Data (01h bytes):
00h A_UINT8 1 retrys
WMIcmd(002Eh:2009h) - WMIX_DBGLOG_CFG_MODULE_CMD
Parameters (08h bytes):
00h A_UINT32 4 cfgvalid ;change mask (0=no change, 1=change)
04h A_UINT32 4 dbglog_config ;new state (0=clear, 1=set)
The cfgvalid mask and dbglog_config bits are:
Bit0-15 DBGLOG_MODULE_LOG_ENABLE ;logging enable flags for module 0-15
Bit16 DBGLOG_REPORTING_ENABLED ;reporting enable flag (1=enable)
Bit17-19 DBGLOG_TIMESTAMP_RESOLUTION ;timestamp resolution (default=1 ms)
Bit20-29 DBGLOG_REPORT_SIZE ;report size in number of messages
Bit30-31 Reserved ;reserved
Using parameters FFFFFFFFh,00000000h or 0001FFFFh,00000000h does disable
WMIX_DBGLOG_EVENT.
WMIevent(1007h) - WMI_PSTREAM_TIMEOUT_EVENT
Event Data (04h bytes):
00h A_UINT8 1 txQueueNumber
01h A_UINT8 1 rxQueueNumber
02h A_UINT8 1 trafficDirection
03h A_UINT8 1 trafficClass
WMIcmd(0029h) - WMI_SET_ROAM_CTRL_CMD
Parameters (09h bytes on DSi?, but would be greater if "numBss>1"):
PREPACK union {
.. A_UINT8 bssid[ATH_MAC_LEN] ;WMI_FORCE_ROAM
.. A_UINT8 roamMode ;WMI_SET_ROAM_MODE
.. WMI_BSS_BIAS_INFO bssBiasInfo ;WMI_SET_HOST_BIAS
.. WMI_LOWRSSI_SCAN_PARAMS lrScanParams
} POSTPACK info
.. A_UINT8 roamCtrlType
This command is used to influence the Roaming behaviour.
Set the host biases of the BSSs before setting the roam mode as bias based.
WMI_ROAM_CTRL_TYPE, Different types of Roam Control:
WMI_FORCE_ROAM = 1 ;Roam to the specified BSSID
WMI_SET_ROAM_MODE = 2 ;default, progd bias, no roam
WMI_SET_HOST_BIAS = 3 ;Set the Host Bias
WMI_SET_LOWRSSI_SCAN_PARAMS = 4 ;Set lowrssi Scan parameters
WMI_ROAM_MODE, aka ROAM MODES:
WMI_DEFAULT_ROAM_MODE = 1 ;RSSI based ROAM
WMI_HOST_BIAS_ROAM_MODE = 2 ;HOST BIAS based ROAM
WMI_LOCK_BSS_MODE = 3 ;Lock to the Current BSS - no Roam
BSS HOST BIAS INFO structures:
WMI_BSS_BIAS typedef PREPACK struct:
6 A_UINT8 bssid[ATH_MAC_LEN]
1 A_INT8 bias
WMI_BSS_BIAS_INFO typedef PREPACK struct:
00h 1 A_UINT8 numBss
01h 7*N WMI_BSS_BIAS bssBias[1]
WMI_LOWRSSI_SCAN_PARAMS typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS:
00h 2 A_UINT16 lowrssi_scan_period
02h 2 A_INT16 lowrssi_scan_threshold
04h 2 A_INT16 lowrssi_roam_threshold
06h 1 A_UINT8 roam_rssi_floor
07h 1 A_UINT8 reserved[1] ;for alignment
WMIcmd(001Bh) - WMI_SET_TX_PWR_CMD
Parameters:
00h A_UINT8 1 dbM ;in dbM units
WMIcmd(0047h) - WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD
This seems to be a nintendo-specific command with 4-byte parameter (official
atheros source code contains a 5-byte WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD
structure, but doesn't have any CMD number assigned to it).
Parameters (04h or 05h bytes):
04h 05h <---- total size (on DSi it's 04h, ie. left column)
00h - A_UINT32 4 timeout ;in seconds, used: 00000002h ;(or 0=Disable)
- 00h A_UINT32 4 frequency ;\whatever, not really used because there's
- 04h A_UINT8 1 threshold ;/no WMIcmd(xxxxh) value assigned
BUG: The function uses a bizarre timeout*1000/1000 mechanism. Values in range
timeout=21h..83h (aka timeout*1000=8000h..1FFFFh) won't work on AR6002 (which
tries to add a 17bit fractional part to such values; this is bugfixed in
AR6013/AR6014 by using only 15bit fractions). And, on all chips, there will be
an overflow on very large values (when timeout*1000/1000 plus 15bit/17bit
fraction exceeds 32bit).
On DSi, AR6002 does handle command 003Ch and 003Ch, but AR6013/AR6014 do merely
redirect them to dummy handlers; despite of also having (unused) actual
handlers for those commands.
WMIcmd(0042h) - WMI_SET_HOST_SLEEP_MODE_CMD
Parameters (08h bytes on DSi?, so, a BOOL must be 4 bytes?):
00h A_BOOL 4 awake;
04h A_BOOL 4 asleep;
See also: WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT
WMIcmd(0043h) - WMI_SET_WOW_MODE_CMD
Event Data (04h bytes on DSi?, but other sources claim MORE bytes?):
04h ??h <---- total size (on DSi it's 04h, ie. left column)
00h 00h A_BOOL 4 enable_wow
-- 04h WMI_WOW_FILTER .. filter ;UINTx or so? with "WMI_WOW_FILTER" value?
-- .. A_UINT16 2 hostReqDelay
WMI_WOW_FILTER values (only one defined):
WOW_FILTER_SSID = 01h
WMIcmd(0045h) - WMI_ADD_WOW_PATTERN_CMD
Parameters:
00h A_UINT8 1 filter_list_id;
01h A_UINT8 1 filter_size;
02h A_UINT8 1 filter_offset;
03h A_UINT8 .. filter[1];
WMIcmd(0046h) - WMI_DEL_WOW_PATTERN_CMD
Parameters (04h bytes):
00h A_UINT16 2 filter_list_id;
02h A_UINT16 2 filter_id;
WMIcmd(002Eh:2007h) - WMIX_GPIO_INTR_ACK_CMD
Parameters:
A_UINT32 ack_mask; /* interrupts to acknowledge
Host acknowledges and re-arms GPIO interrupts. A single message should be used
to acknowledge all interrupts that were delivered in an earlier
WMIX_GPIO_INTR_EVENT message.
GPIO Constants
AR6001_GPIO_PIN_COUNT = 18
AR6002_GPIO_PIN_COUNT = 18 ;aka hw2.0
AR6003_GPIO_PIN_COUNT = 28 ;aka hw4.0 ;XXX shouldn't that be 26 ?
MCKINLEY_GPIO_PIN_COUNT = 57 ;aka hw6.0
Values of gpioreg_id in the WMIX_GPIO_REGISTER_SET_CMDID and
WMIX_GPIO_REGISTER_GET_CMDID commands come in two flavors. If the upper bit of
gpioreg_id is CLEAR, then the remainder is interpreted as one of these values.
This provides platform-independent access to GPIO registers. If the upper bit
(GPIO_ID_OFFSET_FLAG) of gpioreg_id is SET, then the remainder is interpreted
as a platform-specific GPIO register offset.
GPIO_ID_OUT = 00000000h
GPIO_ID_OUT_W1TS = 00000001h
GPIO_ID_OUT_W1TC = 00000002h
GPIO_ID_ENABLE = 00000003h
GPIO_ID_ENABLE_W1TS = 00000004h
GPIO_ID_ENABLE_W1TC = 00000005h
GPIO_ID_IN = 00000006h
GPIO_ID_STATUS = 00000007h
GPIO_ID_STATUS_W1TS = 00000008h
GPIO_ID_STATUS_W1TC = 00000009h
GPIO_ID_PIN0 = 0000000Ah
GPIO_ID_PIN(n) = (GPIO_ID_PIN0+(n)) ;=0000000Ah and up
GPIO_ID_NONE = FFFFFFFFh
GPIO_ID_OFFSET_FLAG = 80000000h
GPIO_ID_REG_MASK = 7fffffffh
GPIO_ID_IS_OFFSET(reg_id) = (((reg_id) & GPIO_ID_OFFSET_FLAG) != 0)
WMIevent(1015h) - WMI_REPORT_ROAM_DATA_EVENT
;-not implemented in DSi ;related to 002Bh?
Event Data:
PREPACK union {
00h WMI_TARGET_ROAM_TIME roamTime;
} POSTPACK u;
14h A_UINT8 roamDataType ;
ROAM_DATA_TYPE values (only one defined)
ROAM_DATA_TIME = 1 /* Get The Roam Time Data
WMI_TARGET_ROAM_TIME structure:
00h A_UINT32 4 disassoc_time
04h A_UINT32 4 no_txrx_time
08h A_UINT32 4 assoc_time
0Ch A_UINT32 4 allow_txrx_time
10h A_UINT8 6 disassoc_bssid[ATH_MAC_LEN]
16h A_INT8 1 disassoc_bss_rssi
17h A_UINT8 6 assoc_bssid[ATH_MAC_LEN] ;UNALIGNED!!!
1Dh A_INT8 1 assoc_bss_rssi
Names: WMI_GET_ROAM_DATA aka WMI_REPORT_ROAM_DATA aka WMI_TARGET_ROAM_DATA
WMIcmd(002Eh:200Ah) - WMIX_PROF_CFG_CMD
WMIcmd(002Eh:200Bh) - WMIX_PROF_ADDR_SET_CMD
WMIcmd(002Eh:200Ch) - WMIX_PROF_START_CMD
WMIcmd(002Eh:200Dh) - WMIX_PROF_STOP_CMD
WMIcmd(002Eh:200Eh) - WMIX_PROF_COUNT_GET_CMD ;reply 3009h
Not implemented in DSi. Said to be "Target Profiling support".
Parameter structures are defined only for WMIX_PROF_CFG_CMD and
WMIX_PROF_ADDR_SET_CMD.
Parameters for WMIX_PROF_CFG_CMD:
00h A_UINT32 4 period; /* Time (in 30.5us ticks) between samples
04h A_UINT32 4 nbins;
Parameters for WMIX_PROF_ADDR_SET_CMD:
00h A_UINT32 4 addr;
Maybe the other three WMIX_PROF_xxx_CMD's don't have any parameters.
See also: WMIX_PROF_COUNT_EVENT
WMIcmd(F01Bh) - WMI_ALLOW_AGGR_CMD
Parameters:
00h A_UINT16 2 tx_allow_aggr (16bit mask to allow tx/uplink ADDBA
negotiation - bit position indicates tid)
02h A_UINT16 2 rx_allow_aggr (16bit mask to allow rx/donwlink ADDBA
negotiation - bit position indicates tid)
Configures tid's to allow ADDBA negotiations on each tid, in each direction.
uh, donwlink?
WMIcmd(F01Ch) - WMI_ADDBA_REQ_CMD
Parameters:
00h A_UINT8 1 tid
"f/w starts performing ADDBA negotiations with peer on the given tid"
"f/w" means FirmWare? ForWard? Fail/Wrong? or What?
WMIcmd(F01Dh) - WMI_DELBA_REQ_CMD
Parameters:
00h A_UINT8 1 tid
01h A_UINT8 1 is_sender_initiator
"f/w would teardown BA with peer." - uh, "f/w"?
"is_send_initiator indicates if it's or tx or rx side" - uh, "it's or"?
WMIevent(1020h) - WMI_ADDBA_REQ_EVENT
Event Data:
00h A_UINT8 1 tid
01h A_UINT8 1 win_sz
02h A_UINT16 2 st_seq_no
04h A_UINT8 1 status "f/w response for ADDBA Req; OK(0) or failure(!=0)"
WMIevent(1021h) - WMI_ADDBA_RESP_EVENT
Event Data:
00h A_UINT8 1 tid
01h A_UINT8 1 status /* OK(0), failure (!=0)
02h A_UINT16 2 amsdu_sz /* Three values: Not supported(0), 3839, 8k
Uhm, does "8k" mean 8192 or 8000 or so?
WMIcmd(F01Eh) - WMI_SET_HT_CAP_CMD
Parameters:
00h A_UINT8 1 band (specifies which band to apply these values)
01h A_UINT8 1 enable (allows 11n to be disabled on a per band basis)
02h A_UINT8 1 chan_width_40M_supported
03h A_UINT8 1 short_GI_20MHz
04h A_UINT8 1 short_GI_40MHz
05h A_UINT8 1 intolerance_40MHz
06h A_UINT8 1 max_ampdu_len_exp
WMIcmd(F01Fh) - WMI_SET_HT_OP_CMD
Parameters:
00h A_UINT8 1 sta_chan_width;
WMIcmd(F020h) - WMI_SET_TX_SELECT_RATES_CMD
Parameters:
00h A_UINT32 4*8*2 rateMasks[WMI_MODE_MAX * WMI_MAX_RATE_MASK];
WMIcmd(F021h) - WMI_SET_TX_SGI_PARAM_CMD
Parameters:
00h A_UINT32 4*2 sgiMask[WMI_MAX_RATE_MASK];
08h A_UINT8 1 sgiPERThreshold;
DEFAULT_SGI_MASK_L32 = 08080000h
DEFAULT_SGI_MASK_U32 = 00000000h
DEFAULT_SGI_PER = 10
WMIcmd(F022h) - WMI_SET_RATE_POLICY_CMD
Parameters:
00h A_UINT32 4*2 rateField[WMI_MAX_RATE_MASK]
(rateField: "1 bit per rate corresponding to index")
08h A_UINT8 1 id ;range 1..5 (aka 1..WMI_RATE_POLICY_ID_MAX)
09h A_UINT8 1 shortTrys
0Ah A_UINT8 1 longTrys
0Bh A_UINT8 1 reserved ;padding
WMI_RATE_POLICY_ID_MAX = 5
WMIcmd(F024h) - WMI_RX_FRAME_FORMAT_CMD
Parameters:
00h A_UINT8 1 metaVersion ;version of meta data for rx packets
;(0-7=valid, 0=default)
01h A_UINT8 1 dot11Hdr ;1=leave .11 header intact,
;0=default/replace .11 header with .3
02h A_UINT8 1 defragOnHost ;1=defragmentation is performed by host,
;0=performed by target <default>
03h A_UINT8 1 reserved[1] ;alignment
WMIcmd(F025h) - WMI_SET_THIN_MODE_CMD
Parameters:
00h A_UINT8 1 enable ;0=default/normal mode, 1=operate in thin mode
01h A_UINT8 3 reserved[3]
WMIcmd(F026h) - WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMD
Parameters:
00h A_UINT8 1 precedence;
BT_WLAN_CONN_PRECEDENCE values:
BT_WLAN_CONN_PRECDENCE_WLAN = 0 ;default
BT_WLAN_CONN_PRECDENCE_PAL = 1
Unknown purpose. Maybe related to BT=Bluetooth? CONN=Connect? PAL=What?
WMIcmd(F03Fh) - WMI_CONFIG_TX_MAC_RULES_CMD
Parameters:
00h A_UINT32 4 rules ;combination of WMI_WRT_xxx values (see "wmi_thin.h")
WMIcmd(F040h) - WMI_SET_PROMISCUOUS_MODE_CMD
Parameters:
00h A_UINT8 1 enable (0=default/normal mode, 1=promiscuous mode)
WMIcmd(F041h) - WMI_RX_FRAME_FILTER_CMD
Parameters:
00h A_UINT16 2 filtermask(0) ;WMI_FILTERMASK_MGMT
02h A_UINT16 2 filtermask(1) ;WMI_FILTERMASK_CTRL
04h A_UINT16 2 filtermask(2) ;WMI_FILTERMASK_DATA
06h A_UINT16 2 reserved ;alignment
WMIcmd(F042h) - WMI_SET_CHANNEL_CMD
Parameters:
00h A_UINT16 2 channel ;frequency in MHz
-- //A_UINT8 - mode ;outcommented (HT20 or HT40 flag?)
-- //A_UINT8 - secondary ;outcommented (HT40 2nd channel above/below flag?)
See also: WMI_SET_CHANNEL_EVENT
WMIevent(9000h) - WMI_SET_CHANNEL_EVENT
Event Data:
00h A_UINT8 1 result ;WMI_SET_CHANNEL_RES (or WMI_THIN_JOIN_RESULT??)
01h A_UINT8 3 reserved[3] ;alignment
WMI_SET_CHANNEL_RES values:
WMI_SET_CHANNEL_RES_SUCCESS = 0
WMI_SET_CHANNEL_RES_FAIL = 1
This is probably the reply to WMI_SET_CHANNEL_CMD (although official comments
claim it to be WMI_THIN_JOIN related; probably because of copying/pasting the
WMI_THIN_JOIN parameter structure without adjusting the comments).
WMIcmd(F028h) - WMI_SET_PMK_CMD
Parameters:
00h A_UINT8 20h pmk[WMI_PMK_LEN];
WMI_PMK_LEN = 32
WMIcmd(F048h) - WMI_SET_PASSPHRASE_CMD
Parameters:
00h A_UCHAR 20h ssid[WMI_MAX_SSID_LEN];
20h A_UINT8 40h passphrase[WMI_PASSPHRASE_LEN];
60h A_UINT8 1 ssid_len;
61h A_UINT8 1 passphrase_len;
WMI_PASSPHRASE_LEN = 64
WMIevent(101Bh) - WMI_PEER_NODE_EVENT
Event Data:
00h A_UINT8 1 eventCode;
01h A_UINT8 6 peerMacAddr[ATH_MAC_LEN];
Below PEER values are probably meant to be the "eventCode" values(?):
PEER_NODE_JOIN_EVENT = 00h
PEER_NODE_LEAVE_EVENT = 01h
PEER_FIRST_NODE_JOIN_EVENT = 10h
PEER_LAST_NODE_LEAVE_EVENT = 11h
WMIevent(101Dh) - WMI_DTIMEXPIRY_EVENT
Event Data:
Unknown (if any)
WMIevent(101Eh) - WMI_WLAN_VERSION_EVENT
Event Data:
00h A_UINT32 4 version;
Whatever event with whatever version?
WMIevent(1023h) - WMI_TX_COMPLETE_EVENT
Event Data:
00h A_UINT8 1 numMessages ;number of tx comp msgs following
01h A_UINT8 1 msgLen ;length in bytes for each individual msg following
02h A_UINT8 1 msgType ;version of tx complete msg data following
03h A_UINT8 1 reserved
When msgType=01h=WMI_TXCOMPLETE_VERSION_1
04h ... .. individual message(s) (see TX_COMPLETE_MSG_V1 structure)
When msgType=Other
04h ... .. reserved for other MSG types (none such defined yet)
TX_COMPLETE_MSG_V1 structure:
00h A_UINT8 1 status /* one of TX_COMPLETE_STATUS_xxx values
01h A_UINT8 1 pktID /* packet ID to identify parent packet
02h A_UINT8 1 rateIdx /* rate index on successful transmission
03h A_UINT8 1 ackFailures /* number of ACK failures in tx attempt
#if 0 ;optional "host delivery time" params currently ommitted...
-- A_UINT32 queueDelay /* usec delay measured Tx Start time
-- A_UINT32 mediaDelay /* usec delay measured ACK rx time
#endif
TX_COMPLETE_STATUS_xxx values:
TX_COMPLETE_STATUS_SUCCESS = 0
TX_COMPLETE_STATUS_RETRIES = 1
TX_COMPLETE_STATUS_NOLINK = 2
TX_COMPLETE_STATUS_TIMEOUT = 3
TX_COMPLETE_STATUS_OTHER = 4
Transmit complete event.
WMIevent(1025h) - WMI_ACL_DATA_EVENT
Event Data:
Unknown (what?)
ACL is what? Is that somehow related to "ACLCOEX"?
WMIevent(1045h) - WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT
Event Data:
Unknown (if any?)
This event exists ONLY in source code from 2010, not in older code, and it's
removed in newer code from 2012.
Special event used to notify host that AR6003 has processed sleep command (aka
WMI_SET_HOST_SLEEP_MODE_CMD?) (needed to prevent a late incoming credit report
from crashing the system).
WMIevent(9003h) - WMI_REPORT_WMM_PARAMS_EVENT
Event Data:
00h wmm_params 6*4 wmm_params[4];
"wmm_params" structure:
00h A_UINT8 1 acm; /* ACM parameter
01h A_UINT8 1 aifsn; /* AIFSN parameters
02h A_UINT8 1 logcwmin; /* cwmin in exponential form
03h A_UINT8 1 logcwmax; /* cwmax in exponential form
04h A_UINT16 2 txopLimit; /* txopLimit
WMIcmd(?) - WMI_SET_ADHOC_BSSID_CMD
Parameters:
00h A_UINT8 6 bssid[ATH_MAC_LEN];
The above parameter structure is defined in "wmi.h", but there's no
WMIcmd(xxxxh) command ID for it. Maybe the command did exist only in older
versions (from dates before 2006)?
BT_PARAMS_SCO_PSPOLL_LATENCY values:
BT_PARAM_SCO_PSPOLL_LATENCY_ONE_FOURTH = 1 ;aka 25%
BT_PARAM_SCO_PSPOLL_LATENCY_HALF = 2 ;aka 50%
BT_PARAM_SCO_PSPOLL_LATENCY_THREE_FOURTH = 3 ;aka 75%
BT_PARAMS_SCO_STOMP_RULES values:
BT_PARAMS_SCO_STOMP_SCO_NEVER = 1
BT_PARAMS_SCO_STOMP_SCO_ALWAYS = 2
BT_PARAMS_SCO_STOMP_SCO_IN_LOWRSSI = 3
BT_ANT_FRONTEND_CONFIG values:
BT_ANT_TYPE_UNDEF = 0 ;aka "Disabled (default)"
BT_ANT_TYPE_DUAL = 1
BT_ANT_TYPE_SPLITTER = 2
BT_ANT_TYPE_SWITCH = 3
BT_ANT_TYPE_HIGH_ISO_DUAL = 4 ;<-- not in "code aurora"
BT_COLOCATED_DEV_TYPE values:
BT_COLOCATED_DEV_BTS4020 = 0
BT_COLCATED_DEV_CSR = 1
BT_COLOCATED_DEV_VALKYRIE = 2 ;aka BT_COLOCATED_DEV_VALKYRIe
WMIcmd(F02Ah) - WMI_SET_BTCOEX_FE_ANT_CMD
Parameters:
00h A_UINT8 1 btcoexFeAntType
1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end
(for isolations less 35dB, for higher isolation there
is not need to pass this command).
(not implemented)
WMI_BTCOEX_FE_ANT_TYPE values:
WMI_BTCOEX_NOT_ENABLED = 0
WMI_BTCOEX_FE_ANT_SINGLE = 1
WMI_BTCOEX_FE_ANT_DUAL = 2
WMI_BTCOEX_FE_ANT_DUAL_HIGH_ISO = 3
WMI_BTCOEX_FE_ANT_BYPASS_MODE = 4
WMI_BTCOEX_FE_ANT_COMBINE_MODE = 5
Indicates front end antenna configuration. This command needs to be issued
right after initialization and after WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD.
AR6003 enables coexistence and antenna switching based on the configuration.
WMIcmd(F02Bh) - WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD
Parameters:
00h A_UINT8 1 btcoexCoLocatedBTdev; 1 - Qcom BT (3 -wire PTA)
2 - CSR BT (3 wire PTA)
3 - Atheros 3001 BT (3 wire PTA)
4 - STE bluetooth (4-wire ePTA)
5 - Atheros 3002 BT (4-wire MCI)
default=3 (Atheros 3001 BT )
Indicate the bluetooth chip to the firmware. Firmware can have different
algorithm based bluetooth chip type. Based on bluetooth device, different
coexistence protocol would be used.
WMIcmd(F02Ch) - WMI_SET_BTCOEX_SCO_CONFIG_CMD
Parameters:
--------------- BTCOEX_SCO_CONFIG scoConfig;
00h A_UINT32 4 scoSlots (Number of SCO Tx/Rx slots: HVx,EV3,2EV3 = 2)
04h A_UINT32 4 scoIdleSlots (Number of Bluetooth idle slots between
consecutive SCO Tx/Rx slots: HVx,EV3 = 4, 2EV3 = 10)
08h A_UINT32 4 scoFlags; SCO Options Flags:
Bit0 Allow Close Range Optimization
Bit1 Is EDR capable or Not
Bit2 IS Co-located Bt role Master
Bit3 Firmware determines the periodicity of SCO
0Ch A_UINT32 4 linkId (applicable to STE-BT - not used)
--------------- BTCOEX_PSPOLLMODE_SCO_CONFIG scoPspollConfig;
10h A_UINT32 4 scoCyclesForceTrigger (Number SCO cycles after which
force a pspoll, default=10)
14h A_UINT32 4 scoDataResponseTimeout (Timeout Waiting for Downlink pkt
in response for ps-poll, default=20 ms)
18h A_UINT32 4 scoStompDutyCyleVal (not implemented)
1Ch A_UINT32 4 scoStompDutyCyleMaxVal (not implemented)
20h A_UINT32 4 scoPsPollLatencyFraction (Fraction of idle period, within
which additional ps-polls can be queued
1 - 1/4 of idle duration
2 - 1/2 of idle duration
3 - 3/4 of idle duration
default=2 (1/2)
--------------- BTCOEX_OPTMODE_SCO_CONFIG scoOptModeConfig;
24h A_UINT32 4 scoStompCntIn100ms (max number of SCO stomp in 100ms
allowed in opt mode. If exceeds the configured value,
switch to ps-poll mode, default=3)
28h A_UINT32 4 scoContStompMax (max number of continous stomp allowed in
opt mode. if excedded switch to pspoll mode, default=3)
2Ch A_UINT32 4 scoMinlowRateMbps (Low rate threshold)
WMIcmd(F02Eh) - WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD
Parameters:
--------------- BTCOEX_ACLCOEX_CONFIG aclCoexConfig;
00h A_UINT32 4 aclWlanMediumDur (Wlan usage time during Acl (non-a2dp)
coexistence, default=30 ms)
04h A_UINT32 4 aclBtMediumDur (Bt usage time during acl coexistence,
default=30 ms)
08h A_UINT32 4 aclDetectTimeout (BT activity observation time limit.
In this time duration, number of bt pkts are counted.
If the Cnt reaches "aclPktCntLowerLimit" value for
"aclIterToEnableCoex" iteration continuously, firmware gets
into ACL coexistence mode. Similarly, if bt traffic count
during ACL coexistence has not reached "aclPktCntLowerLimit"
continuously for "aclIterToEnableCoex", then ACL coexistence
is disabled, default=100 ms)
0Ch A_UINT32 4 aclPktCntLowerLimit (Acl Pkt Cnt to be received in duration
of "aclDetectTimeout" for "aclIterForEnDis" times to
enabling ACL coex. Similar logic is used to disable acl
coexistence. (If "aclPktCntLowerLimit" cnt of acl pkts
are not seen by the for "aclIterForEnDis" then acl
coexistence is disabled), default=10)
10h A_UINT32 4 aclIterForEnDis (number of Iteration of
"aclPktCntLowerLimit" for Enabling and Disabling Acl
Coexistence, default=3)
14h A_UINT32 4 aclPktCntUpperLimit (This is upperBound limit, if there is
more than "aclPktCntUpperLimit" seen in "aclDetectTimeout",
ACL coexistence is enabled right away, default=15)
18h A_UINT32 4 aclCoexFlags A2DP Option flags:
Bit0 Allow Close Range Optimization
Bit1 disable Firmware detection
(Currently supported configuration is aclCoexFlags=0)
1Ch A_UINT32 4 linkId; ;Applicable only for STE-BT - not used
--------------- BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG aclCoexPspollConfig;
20h A_UINT32 4 aclDataRespTimeout (Max duration firmware waits for downlink
by stomping on bluetooth after ps-poll is acknowledged,
default=20 ms)
--------------- BTCOEX_OPTMODE_ACLCOEX_CONFIG aclCoexOptConfig;
24h A_UINT32 4 aclCoexMinlowRateMbps ;\
28h A_UINT32 4 aclCoexLowRateCnt ;
2Ch A_UINT32 4 aclCoexHighPktRatio ; Not implemented yet
30h A_UINT32 4 aclCoexMaxAggrSize ;
34h A_UINT32 4 aclPktStompCnt ;/
Configure non-A2dp ACL profile parameters.The starts of ACL profile can either
be indicated via WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD or enabled via firmware
detection which is configured via "aclCoexFlags".
Configration of BTCOEX_ACLCOEX_CONFIG data structure are common configuration
and applies ps-poll mode and opt mode.
Ps-poll Mode - Station is in power-save and retrieves downlink data during wlan
medium.
Opt Mode - station is in power save during bluetooth medium time and awake
during wlan duration.
(Not implemented yet) (uh, what?)
BTCOEX_PSPOLLMODE_ACLCOEX_CONFIG - Configuration applied only during ps-poll
mode.
BTCOEX_OPTMODE_ACLCOEX_CONFIG - Configuration applied only during opt mode.
Aliases for "aclCoexFlags":
#define WMI_ACLCOEX_FLAGS_ALLOW_OPTIMIZATION (1 << 0)
#define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1)
WMIcmd(F02Fh) - WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD
Parameters:
00h A_UINT32 4 btInquiryDataFetchFrequency (The frequency of querying the
AP for data (via pspoll) is configured by this parameter,
default=10 ms)
04h A_UINT32 4 protectBmissDurPostBtInquiry (The firmware will continue to
be in inquiry state for configured duration, after inquiry
completion. This is to ensure other bluetooth transactions
(RDP, SDP profiles, link key exchange, etc.) goes through
smoothly without wifi stomping, default=10 secs)
08h A_UINT32 4 maxpageStomp (Applicable only for STE-BT interface.
Currently not used)
0Ch A_UINT32 4 btInquiryPageFlag (Not used)
Configuration parameters during bluetooth inquiry and page. Page configuration
is applicable only on interfaces which can distinguish page (applicable only
for ePTA - STE bluetooth).
Bluetooth inquiry start and end is indicated via
WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD. During this the station will be
power-save mode.
WMIcmd(F030h) - WMI_SET_BTCOEX_DEBUG_CMD
Parameters:
00h A_UINT32 4 btcoexDbgParam1 ;\
04h A_UINT32 4 btcoexDbgParam2 ; Used for firmware development
08h A_UINT32 4 btcoexDbgParam3 ; and debugging
0Ch A_UINT32 4 btcoexDbgParam4 ;
10h A_UINT32 4 btcoexDbgParam5 ;/
WMIcmd(F031h) - WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD
Parameters:
00h A_UINT32 4 btProfileType (1=SCO, 2=A2DP, 3=INQUIRY_PAGE, 4=ACLCOEX)
04h A_UINT32 4 btOperatingStatus ;aka BT_STREAM_STATUS on AR6002 ?
08h A_UINT32 4 btLinkId
WMI_BTCOEX_BT_PROFILE values:
WMI_BTCOEX_BT_PROFILE_SCO = 1
WMI_BTCOEX_BT_PROFILE_A2DP = 2
WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE = 3
WMI_BTCOEX_BT_PROFILE_ACLCOEX = 4
This command is probably equivalent to WMI_SET_BT_STATUS_CMD on AR6002.
The "DataSet" feature allows the firmware to read external data from host
memory for whatever purpose (maybe intended for cases where the wifi board
doesn't contain an EEPROM, or for cases where Xtensa RAM/ROM is too small to
hold the whole firmware, or just to make it easier to modify data for
testing/debugging).
For the "DataSet" stuff, the normal Command/Response flow is reversed: the
firmware does send an EVENT to request data, and the host must respond by a
REPLY_CMD (except for the CLOSE_EVENT, which requires no reply).
WMIevent(1010h:3001h) - WMIX_DSETOPENREQ_EVENT
00h A_UINT32 4 dset_id ;-ID of requested DataSet (see "dsetid.h")
04h A_UINT32 4 targ_dset_handle ;\to be echo'ed in REPLY_CMD
08h A_UINT32 4 targ_reply_fn ; (host doesn't need to deal with this)
0Ch A_UINT32 4 targ_reply_arg ;/
DataSet Open Request Event. The host should open the DataSet and send a
WMIX_DSETOPEN_REPLY_CMD.
WMIevent(1010h:3003h) - WMIX_DSETDATAREQ_EVENT
00h A_UINT32 4 access_cookie ;-some kind of "filehandle" on host side
04h A_UINT32 4 offset ;\source offset & length of requested data
08h A_UINT32 4 length ;/
0Ch A_UINT32 4 targ_buf ;\to be echo'ed in REPLY_CMD
10h A_UINT32 4 targ_reply_fn ; (host doesn't need to deal with this)
14h A_UINT32 4 targ_reply_arg ;/
DataSet Data Request Event. The host should send the requested data via
WMIX_DSETDATA_REPLY_CMD.
WMIevent(1010h:3002h) - WMIX_DSETCLOSE_EVENT
00h A_UINT32 4 access_cookie ;-some kind of "filehandle" on host
side
DataSet Close Event. The host should close the DataSet (and doesn't need to
send any REPLY_CMD).
WMIcmd(002Eh:2001h) - WMIX_DSETOPEN_REPLY_CMD
00h A_UINT32 4 status ;-what status ?
04h A_UINT32 4 targ_dset_handle ;\
08h A_UINT32 4 targ_reply_fn ; to be echo'ed from open EVENT
0Ch A_UINT32 4 targ_reply_arg ;/
10h A_UINT32 4 access_cookie ;-some kind of "filehandle" on host side
14h A_UINT32 4 size ;-what size ?
18h A_UINT32 4 version ;-what version ?
This REPLY_CMD should be send in response to WMIX_DSETOPENREQ_EVENTs.
WMIcmd(002Eh:2002h) - WMIX_DSETDATA_REPLY_CMD
00h A_UINT32 4 status ;-what status ?
04h A_UINT32 4 targ_buf ;\
08h A_UINT32 4 targ_reply_fn ; to be echo'ed from data EVENT
0Ch A_UINT32 4 targ_reply_arg ;/
10h A_UINT32 4 length ;\requested data
14h A_UINT8 LEN buf[length] ;/
This REPLY_CMD should be send in response to WMIX_DSETDATAREQ_EVENTs.
AP Mode
Whatever that is... probably something where the AR600x acts as Access Point
(AP) for other Stations (STA).
The DSi doesn't support AP Mode stuff, however, 3DS firmware type4 does support
most of them (but with F00Ah..F013h renumbered to 004Ah..0052h).
AP Mode definitions
Changing the following values needs compilation of both driver and firmware.
AP_MAX_NUM_STA = 4 ;for old AR6002_REV2 version
AP_MAX_NUM_STA = 10 ;for newer versions
NUM_DEV = 3 ;Maximum no. of virtual interface supported
NUM_CONN = (AP_MAX_NUM_STA + NUM_DEV)
AP_ACL_SIZE = 10
IEEE80211_MAX_IE = 256
MCAST_AID = 0FFh ;Spl. AID used to set DTIM flag in the beacons
DEF_AP_COUNTRY_CODE = "US "
DEF_AP_WMODE_G = WMI_11G_MODE
DEF_AP_WMODE_AG = WMI_11AG_MODE
DEF_AP_DTIM = 5
DEF_BEACON_INTERVAL = 100
AP_DISCONNECT_STA_LEFT = 101 ;\
AP_DISCONNECT_FROM_HOST = 102 ;
AP_DISCONNECT_COMM_TIMEOUT = 103 ; AP mode disconnect reasons
AP_DISCONNECT_MAX_STA = 104 ; (101..107 decimal):
AP_DISCONNECT_ACL = 105 ;
AP_DISCONNECT_STA_ROAM = 106 ;
AP_DISCONNECT_DFS_CHANNEL = 107 ;/
WMIcmd(F015h) - WMI_AP_SET_DTIM_CMD
Parameters:
00h A_UINT8 1 dtim; ;wake up each N beacon interval units
DTIM interval used to check for multicast packets.
WMIevent(102Bh) - WMI_DFS_HOST_ATTACH_EVENT
Event Data:
00h A_UINT64 8 ext_chan_busy_ts;
08h A_UINT8 1 enable_ar;
09h A_UINT8 1 enable_radar;
WMIevent(102Ch) - WMI_DFS_HOST_INIT_EVENT
Event Data:
00h A_UINT32 4 dfs_domain;
WMIevent(102Dh) - WMI_DFS_RESET_DELAYLINES_EVENT
WMIevent(102Eh) - WMI_DFS_RESET_RADARQ_EVENT
WMIevent(102Fh) - WMI_DFS_RESET_AR_EVENT
WMIevent(1030h) - WMI_DFS_RESET_ARQ_EVENT
WMIevent(1031h) - WMI_DFS_SET_DUR_MULTIPLIER_EVENT
WMIevent(1032h) - WMI_DFS_SET_BANGRADAR_EVENT
WMIevent(1033h) - WMI_DFS_SET_DEBUGLEVEL_EVENT
Event Data:
Unknown (if any) (not defined in file "dfs_common.h")
WMIevent(1034h) - WMI_DFS_PHYERR_EVENT
Event Data:
00h A_UINT8 1 num_events;
01h dfs_event_info .. ev_info[WMI_DFS_EVENT_MAX_BUFFER_SIZE];
WMI_DFS_EVENT_MAX_BUFFER_SIZE = ((255)/sizeof(struct dfs_event_info))
Format of the above "dfs_event_info" structure:
00h A_UINT64 8 full_ts; /* 64-bit full timestamp from interrupt time
08h A_UINT32 4 ts; /* Original 15 bit recv timestamp
0Ch A_UINT32 4 ext_chan_busy; /* Ext chan busy %
10h A_UINT8 1 rssi; /* rssi of radar event
11h A_UINT8 1 dur; /* duration of radar pulse
12h A_UINT8 1 chanindex; /* Channel of event
13h A_UINT8 1 flags;
Values for "flags":
PRIMARY_CH = 0 ;\flags.bit0
EXT_CH = 1 ;/
AR_EVENT = 0 ;\flags.bit1
DFS_EVENT = 2 ;/
Some more DFS related constants (unknown purpose):
DFS_UNINIT_DOMAIN = 0 ;Uninitialized dfs domain
DFS_FCC_DOMAIN = 1 ;FCC3 dfs domain
DFS_ETSI_DOMAIN = 2 ;ETSI dfs domain
DFS_MKK4_DOMAIN = 3 ;Japan dfs domain
MAX_BIN5_DUR = 131 ;rounded from 131.25=(105*1.25) ;DFS related
TRAFFIC_DETECTED = 1 ;whatever ;DFS related
ATH_DEBUG_DFS = 00000100h ;Minimal DFS debug ;\
ATH_DEBUG_DFS1 = 00000200h ;Normal DFS debug ; should match the
ATH_DEBUG_DFS2 = 00000400h ;Maximal DFS debug ; table from if_ath.c
ATH_DEBUG_DFS3 = 00000800h ;matched filterID display ;/
P2P_SSID structure:
00h A_UINT8 1 ssidLength;
01h A_UINT8 20h ssid[WMI_MAX_SSID_LEN];
WMIcmd(F038h) - WMI_P2P_SET_CONFIG_CMD
Parameters:
00h A_UINT8 1 go_intent;
01h A_UINT8 3 country[3];
04h A_UINT8 1 reg_class;
05h A_UINT8 1 listen_channel;
06h A_UINT8 1 op_reg_class;
07h A_UINT8 1 op_channel;
09h A_UINT16 2 config_methods;
WMIcmd(F03Bh) - WMI_P2P_FIND_CMD
Parameters:
typedef PREPACK struct {
00h A_UINT32 4 timeout;
04h A_ENUM .. type; ;A_UINTx or so? ;aka WMI_P2P_DISC_TYPE
WMI_P2P_DISC_TYPE values:
WMI_P2P_FIND_START_WITH_FULL = Unknown (0 or 1 or so)
WMI_P2P_FIND_ONLY_SOCIAL = WMI_P2P_FIND_START_WITH_FULL+1
WMI_P2P_FIND_PROGRESSIVE = WMI_P2P_FIND_START_WITH_FULL+2
WMIcmd(F03Ch) - WMI_P2P_STOP_FIND_CMD
Parameters:
Unknown (none?)
WMIcmd(F03Dh) - WMI_P2P_GO_NEG_START_CMD
Parameters:
00h A_UINT16 2 listen_freq;
02h A_UINT16 2 force_freq;
04h A_UINT16 2 go_oper_freq;
06h A_UINT8 1 dialog_token;
07h A_UINT8 6 peer_addr[ATH_MAC_LEN];
0Dh A_UINT8 6 own_interface_addr[ATH_MAC_LEN];
13h A_UINT8 6 member_in_go_dev[ATH_MAC_LEN];
19h A_UINT8 1 go_dev_dialog_token;
1Ah P2P_SSID 21h peer_go_ssid;
3Bh A_UINT8 1 wps_method;
3Ch A_UINT8 1 dev_capab;
3Dh A_INT8 1 go_intent;
3Eh A_UINT8 1 persistent_grp;
WMIcmd(F03Eh) - WMI_P2P_LISTEN_CMD
Parameters:
00h A_UINT32 4 timeout;
...P2P Events...
WMIevent(1036h) - WMI_P2P_GO_NEG_RESULT_EVENT
Event Data:
00h A_UINT16 2 freq;
02h A_INT8 1 status;
03h A_UINT8 1 role_go;
04h A_UINT8 20h ssid[WMI_MAX_SSID_LEN];
24h A_UINT8 1 ssid_len;
25h A_CHAR 9 pass_phrase[WMI_MAX_PASSPHRASE_LEN];
2Eh A_UINT8 6 peer_device_addr[ATH_MAC_LEN];
34h A_UINT8 6 peer_interface_addr[ATH_MAC_LEN];
3Ah A_UINT8 1 wps_method;
3Bh A_UINT8 1 persistent_grp;
WMI_MAX_PASSPHRASE_LEN = 9
WMIevent(103Dh) - WMI_P2P_GO_NEG_REQ_EVENT
Event Data:
000h A_UINT8 6 sa[ATH_MAC_LEN];
006h A_UINT8 200h wps_buf[512];
206h A_UINT16 2 wps_buflen;
208h A_UINT8 200h p2p_buf[512];
408h A_UINT16 2 p2p_buflen;
40Ah A_UINT8 1 dialog_token;
WMIevent(103Eh) - WMI_P2P_INVITE_REQ_EVENT
Event Data:
000h A_UINT8 200h p2p_buf[512];
200h A_UINT16 2 p2p_buflen;
202h A_UINT8 6 sa[ATH_MAC_LEN];
208h A_UINT8 6 bssid[ATH_MAC_LEN];
20Eh A_UINT8 6 go_dev_addr[ATH_MAC_LEN];
214h P2P_SSID 21h ssid;
235h A_UINT8 1 is_persistent;
236h A_UINT8 1 dialog_token;
WMIevent(103Fh) - WMI_P2P_INVITE_RCVD_RESULT_EVENT
Event Data:
00h A_UINT16 2 oper_freq;
02h A_UINT8 6 sa[ATH_MAC_LEN];
08h A_UINT8 6 bssid[ATH_MAC_LEN];
0Eh A_UINT8 1 is_bssid_valid;
0Fh A_UINT8 6 go_dev_addr[ATH_MAC_LEN];
15h P2P_SSID 21h ssid;
36h A_UINT8 1 status;
WMIevent(1040h) - WMI_P2P_INVITE_SENT_RESULT_EVENT
Event Data:
00h A_UINT8 1 status;
01h A_UINT8 6 bssid[ATH_MAC_LEN];
07h A_UINT8 1 is_bssid_valid;
WMIevent(1041h) - WMI_P2P_PROV_DISC_RESP_EVENT
Event Data:
00h A_UINT8 6 peer[ATH_MAC_LEN];
06h A_UINT16 2 config_methods;
WMIevent(1042h) - WMI_P2P_PROV_DISC_REQ_EVENT
Event Data:
00h A_UINT8 6 sa[ATH_MAC_LEN];
06h A_UINT16 2 wps_config_method;
08h A_UINT8 6 dev_addr[ATH_MAC_LEN];
0Eh A_UINT8 8 pri_dev_type[WPS_DEV_TYPE_LEN];
16h A_UINT8 20h device_name[WPS_MAX_DEVNAME_LEN];
36h A_UINT8 1 dev_name_len;
37h A_UINT16 2 dev_config_methods;
39h A_UINT8 1 device_capab;
3Ah A_UINT8 1 group_capab;
WPS_DEV_TYPE_LEN = 8
WMIevent(1043h) - WMI_P2P_START_SDPD_EVENT
Event Data:
Unknown (none?)
WMIevent(1044h) - WMI_P2P_SDPD_RX_EVENT
Event Data:
00h A_UINT8 1 type;
01h A_UINT8 1 transaction_status;
02h A_UINT8 1 dialog_token;
03h A_UINT8 1 frag_id;
04h A_UINT8 6 peer_addr[ATH_MAC_LEN];
0Ah A_UINT16 2 freq;
0Ch A_UINT16 2 status_code;
0Eh A_UINT16 2 comeback_delay;
10h A_UINT16 2 tlv_length;
12h A_UINT16 2 update_indic;
14h VAR .. Variable length TLV will be placed after the event
DSi Atheros Wifi - Unimplemented WMI WAC Functions
--------------------------------------------------
WMIcmd(F044h) - WMI_WAC_SCAN_REPLY_CMD
Parameters:
00h A_ENUM .. cmdid ;A_UINTx or so? (WAC_SUBCMD)
WAC_SUBCMD values:
WAC_MORE_SCAN = -1
WAC_SEND_PROBE_IDX = 0
WMIcmd(F045h) - WMI_WAC_CTRL_REQ_CMD
Parameters:
00h A_UINT8 1 req; ;aka WAC_REQUEST_TYPE
01h A_UINT8 1 cmd; ;aka WAC_COMMAND
02h A_UINT8 1 frame; ;aka WAC_FRAME_TYPE
03h A_UINT8 11h ie[17];
14h A_INT32 4 status; ;aka WAC_STATUS
WAC related constants (from wac_defs.h):
WAC_REQUEST_TYPE values:
WAC_SET = Unknown (0 or 1 or so)
WAC_GET = WAC_SET+1
WAC_COMMAND values:
WAC_ADD = Unknown (0 or 1 or so)
WAC_DEL = WAC_ADD+1
WAC_GET_STATUS = WAC_ADD+2
WAC_GET_IE = WAC_ADD+3
WAC_FRAME_TYPE values:
PRBREQ = Unknown (0 or 1 or so)
PRBRSP = PRBREQ+1
BEACON = PRBREQ+2
WAC_STATUS values:
WAC_FAILED_NO_WAC_AP = -4
WAC_FAILED_LOW_RSSI = -3
WAC_FAILED_INVALID_PARAM = -2
WAC_FAILED_REJECTED = -1
WAC_SUCCESS = 0
WAC_DISABLED = 1
WAC_PROCEED_FIRST_PHASE = 2
WAC_PROCEED_SECOND_PHASE = 3
WMIevent(1037h) - WMI_WAC_SCAN_DONE_EVENT
WMIevent(1038h) - WMI_WAC_REPORT_BSS_EVENT
WMIevent(1039h) - WMI_WAC_START_WPS_EVENT
WMIevent(103Ah) - WMI_WAC_CTRL_REQ_REPLY_EVENT
Event Data:
Unknown (if any?)
WAC Events. Event data format is unknown, maybe related to below two structs:
WMI_GET_WAC_INFO structure (UNION):
When some case:
00h A_UINT8 11h ie[17];
When some other case:
00h A_INT32 4 wac_status;
WMI_WPS_PIN_INFO structure: ;"WPS" might be WAC_START_WPS related?
00h A_UINT8 6 bssid[ATH_MAC_LEN];
06h A_UINT8 8 pin[8]; ;aka "wps_pin[8]" presumably?
WMIevent(103Bh) - WMI_RFKILL_STATE_CHANGE_EVENT
Event Data:
Unknown (if any?)
WMIevent(103Ch) - WMI_RFKILL_GET_MODE_CMD_EVENT
Event Data:
Unknown (maybe some format as in "SET_RFKILL" command parameters?)
WMIevent(9004h) - WMI_STORERECALL_STORE_EVENT
Event Data:
00h A_UINT32 4 msec_sleep; ;time between power off/on
04h A_UINT32 4 length; ;length of following data
08h A_UINT8 .. data[1]; ;start of "STORE" data
Ultra low power store/recall feature. Maybe this requests to memorize the
"STORE" data in host memory?
WMIcmd(8000h) - WMI_THIN_RESERVED_START
WMIcmd(8FFFh) - WMI_THIN_RESERVED_END
Area for Thin commands. These command IDs can be found in "wmi_thin.h".
WMIcmd(8000h) - WMI_THIN_CONFIG_CMD
Parameters:
00h A_UINT32 4 cfgField ;combination of WMI_THIN_CFG_...
04h A_UINT16 2 length ;length in bytes of appended sub-command(s)
06h A_UINT8 2 reserved[2] ;align padding
08h ... .. structure(s) selected in "cfgField"...
When cfgField.Bit0 set: append WMI_THIN_CONFIG_TXCOMPLETE struct:
Used to configure the params and content for TX Complete messages the will come
from the Target. these messages are disabled by default but can be enabled
using this structure and the WMI_THIN_CONFIG_CMDID.
+00h A_UINT8 1 version (the versioned type of messages to use, 0=disable)
+01h A_UINT8 1 countThreshold (msg count threshold triggering a tx
complete message)
+02h A_UINT16 2 timeThreshold (timeout interval in MSEC triggering a
tx complete message)
When cfgField.Bit1 set: append WMI_THIN_CONFIG_DECRYPT_ERR struct:
Used to configure behavior for received frames that have decryption errors. The
default behavior is to discard the frame without notification. Alternately, the
MAC Header is forwarded to the host with the failed status.
+00h A_UINT8 1 enable (1=send decrypt errors to the host, 0=don't)
+01h A_UINT8 3 reserved[3] (align padding)
When cfgField.Bit2 set: Unused --- NEW VERSION
Unused.
When cfgField.Bit2 set: append WMI_THIN_CONFIG_TX_MAC_RULES --- OLD VERSION
Used to configure behavior for transmitted frames that require partial MAC
header construction. These rules are used by the target to indicate which
fields need to be written.
+00h A_UINT32 4 rules (combination of WMI_WRT_... values)
When cfgField.Bit3 set: append WMI_THIN_CONFIG_RX_FILTER_RULES struct:
Used to configure behavior for received frames as to which frames should get
forwarded to the host and which should get processed internally.
+00h A_UINT32 4 rules (combination of WMI_FILT_... values)
When cfgField.Bit4 set: append WMI_THIN_CONFIG_CIPHER_ENCAP struct:
Used to configure behavior for both TX and RX frames regarding security cipher
encapsulation. The host may specify whether or not the firmware is responsible
for cipher encapsulation. If the firmware is responsible it will add the
security header and trailer for TX frames and remove the header and trailer for
Rx frames. Also, the firmware will examine the resource counter if any and
behave appropriately when a bad value is detected. If the host indicates
responsibility for encapsulation then it is responsible for all aspects of
encapsulation, however the device will still perform the encryption and
decryption of the frame payload if a key has been provided.
+00h A_UINT8 1 enable (enables/disables firmware cipher encapsulation)
+01h A_UINT8 3 reserved[3] (align padding)
Summary of values for "cfgField":
WMI_THIN_CFG_TXCOMP = 00000001h
WMI_THIN_CFG_DECRYPT = 00000002h
WMI_THIN_CFG_MAC_RULES = 00000004h ;old version (or planned for future?)
WMI_THIN_UNUSED1 = 00000004h ;current version
WMI_THIN_CFG_FILTER_RULES = 00000008h
WMI_THIN_CFG_CIPHER_ENCAP = 00000010h
WMIcmd(8001h) - WMI_THIN_SET_MIB_CMD
Parameters:
00h A_UINT16 2 length; /* the length in bytes of the appended MIB data
02h A_UINT8 1 mibID; /* the ID of the MIB element being set
03h A_UINT8 1 reserved; /* align padding
WMIevent(8000h) - WMI_THIN_EVENTID_RESERVED_START
WMIevent(8FFFh) - WMI_THIN_EVENTID_RESERVED_END
Events/Responses with special IDs for THIN stuff (wmi_thin.h)
WMIevent(8001h) - WMI_THIN_GET_MIB_EVENT
Event Data:
Unknown (maybe same/similar format as for "SET_MIB" command parameters?)
WMIevent(8002h) - WMI_THIN_JOIN_EVENT
Event Data:
00h A_UINT8 1 result (the result of the join command)
01h A_UINT8 3 reserved[3]; /* alignment
WMI_THIN_JOIN_RESULT values (aka above "result" value):
WMI_THIN_JOIN_RES_SUCCESS = 0 ;device has joined the network
WMI_THIN_JOIN_RES_FAIL = 1 ;failed for unspecified reason
WMI_THIN_JOIN_RES_TIMEOUT = 2 ;failed due to no beacon rx in time limit
WMI_THIN_JOIN_RES_BAD_PARAM = 3 ;failed due to bad cmd param
WMI_THIN_JOIN_RES_IBSS_START = 4 ;device started new IBSS network
The presence of the I2C EEPROM appears to be some mis-conception. It might make
sense to store the wifi calibration data on the daughterboard (rather than in
eMMC storage on mainboard), however, it could be as well stored in the SPI
FLASH chip, but Nintendo apparently didn't knew how to do that.
Below describes the internal Atheros hardware. The hardware registers can be
accessed via WINDOW_DATA, or by uploading custom code to the Xtensa CPU via BMI
Bootloader commands.
Anyways, normally, the Wifi unit should be accessed via WMI commands, so one
won't need to deal with internal hardware (except cases like reading the
CHIP_ID, or for better understanding of the inner workings of the hardware).
Pseudo Opcodes
MOV ar,as Macro (=OR ar,as,as)
NOP Alias for "OR An,An,An" (alternate, instead of 0020F0h)
J.L adr,as Macro (J or LiteralLoad+JX)
BBCI.L as,b,adr Macro Branch Bit Clear Imm5 LE
BBSI.L as,b,adr Macro Branch Bit Set Imm5 LE
SRLI ar,at,imm5 Alias for "SRLI ar,at,imm4" or EXTUI (when imm5>=16)
More (inofficial) pseudos...
mov br,bs or br,bs,bs
mov br,0 and br,bs,not bs
mov br,1 or br,bs,not bs
sub at,as,imm add at,as,-imm
mov sfr_xxx mov special[imm8]
alu ax,... alu ax,ax,...
Boolean Option
Opcode Native Nocash
008st0h ANY4 bt,bs or bt,bs..bs+3 Any 4 Booleans True
009st0h ALL4 bt,bs and bt,bs..bs+3 All 4 Booleans True
00Ast0h ANY8 bt,bs or bt,bs..bs+7 Any 8 Booleans True
00Bst0h ALL8 bt,bs and bt,bs..bs+7 All 8 Booleans True
02rst0h ANDB br,bs,bt and br,bs,bt BooleanAnd
12rst0h ANDBC br,bs,bt and br,bs,not bt BooleanAndComplement(t)
22rst0h ORB br,bs,bt or br,bs,bt BooleanOr
32rst0h ORBC br,bs,bt or br,bs,not bt BooleanOrComplement(t)
42rst0h XORB br,bs,bt xor br,bs,bt Boolean Xor
C3rst0h MOVF ar,as,bt movz bt,ar,as Move if False
D3rst0h MOVT ar,as,bt movnz bt,ar,as Move if True
ii0s76h BF bs,adr jz bs,rel8 Branch if False
ii1s76h BT bs,adr jnz bs,rel8 Branch if True
Misc Option
40Est0h NSA at,as nsa at,as Normaliz.ShiftAmount
40Fst0h NSAU at,as nsau at,as Norma.ShiftAmUnsigned
23rsi0h SEXT ar,as,imm sext ar,as,imm4+7 Sign Extend 7..22
33rsi0h CLAMPS ar,as,imm clamps ar,as,imm4+7 Signed Clamp minmax
43rst0h MIN ar,as,at min ar,as,at Minimum Value Signed
53rst0h MAX ar,as,at max ar,as,at Maximum Value Signed
63rst0h MINU ar,as,at minu ar,as,at Minimum Value Unsigned
73rst0h MAXU ar,as,at maxu ar,as,at Maximum Value Unsigned
Loop Option
ii8s76h LOOP as,adr loop as,rel8abs Loop
ii9s76h LOOPNEZ as,adr loopnz as,rel8abs Loop if NotEqual zero
iiAs76h LOOPGTZ as,adr loopgtz as,rel8abs Loop if Greater zero
Mul16 Option
C1rst0h MUL16U ar,as,at umul16 ar,as,at Multiply16bitUnsigned
D1rst0h MUL16S ar,as,at smul16 ar,as,at Multiply16bitSigned
Mul32 Option
82rst0h MULL ar,as,at mul ar,as,at Multiply Low
A2rst0h MULUH ar,as,at umulhi ar,as,at MultiplyUnsignedHigh
B2rst0h MULSH ar,as,at smulhi ar,as,at MultiplySignedHigh
Div32 Option
C2rst0h QUOU ar,as,at udiv ar,as,at Quotient Unsigned
D2rst0h QUOS ar,as,at sdiv ar,as,at Quotient Signed
E2rst0h REMU ar,as,at udivrem ar,as,at Remainder Unsigned
F2rst0h REMS ar,as,at sdivrem ar,as,at Remainder Signed
Exception Option
000000h ILL ill Illegal Instruction
002080h EXCW xceptwait Exception Wait
003000h RFE ret_e RetFromException
003100h RFUE ret_ue RetFromUserModeExcept
003200h RFDE ret_de RetFromDoubleExcept
005000h SYSCALL syscall System Call
Debug Option
004xy0h BREAK imm4,imm4 break imm8 Breakpoint
F1E000h RFDO ret_do RetFromDebugOperat.
F1Es10h RFDD ;s=??? rer_dd imm1 RetFromDebugDispatch
MemECC/Parity Option
003020h RFME ret_me RetFromMemError
No Option
E3rii0h RUR ar,imm8 mov ar,user[imm8] Read User Register
F3iit0h WUR at,imm8 mov user[imm8],at WriteUserRegister
Region/MMU Option
503st0h RITLB0 at,as mov at,itlb0[as] Read InstTLB Virtual
507st0h RITLB1 at,as mov at,itlb1[as] Read InstTLB Translat
50Bst0h RDTLB0 at,as mov at,dtlb0[as] Read DataTLB Virtual
50Fst0h RDTLB1 at,as mov at,dtlb1[as] Read DataTLB Translat
504s00h IITLB as inv itlb[as] Invalidate InstTLB
50Cs00h IDTLB as inv dtlb[as] Invalidate DataTLB
505st0h PITLB at,as probe at,itlb[as] Probe InstTLB
50Dst0h PDTLB at,as probe at,dtlb[as] Probe DataTLB
506st0h WITLB at,as mov itlb[as],at Write InstTLB Entry
50Est0h WDTLB at,as mov dtlb[as],at Write DataTLB Entry
Multiprocessor Option
iiBst2h L32AI at,as,i*4 mov_m at,[as+imm8*4] Load 32bit Acquire
iiFst2h S32RI at,as,imm*4 mov_m [as+imm8*4],at Store 32bit Release
Unknown
71xxx0h ACCER ... accer ... Unknown/Unspecified
Simcall Option
005100h SIMCALL simcall Non-HW Simulator-Call
Float Option
08rst0h LSX fr,as,at f_mov fr,[as+at] LoadSingleIndexed
ii0st3h LSI ft,as,imm*4 f_mov ft,[as+imm8*4] LoadSingleImmediate
48rst0h SSX fr,as,at f_mov [as+at],fr Store Single Indexed
ii4st3h SSI ft,as,imm*4 f_mov [as+imm8*4],ft Store Single Immedia.
18rst0h LSXU fr,as,at f_movupd fr,[as+at] LoadSingleIndexed+Upd
ii8st3h LSIU ft,as,imm*4 f_movupd ft,[as+imm8*4] LoadSingleImm+Update
58rst0h SSXU fr,as,at f_movupd [as+at],fr Store Single Indx+Upd
iiCst3h SSIU ft,as,imm*4 f_movupd [as+imm8*4],ft Store Single Imm+Upd.
0Arst0h ADD.S fr,fs,ft f_add fr,fs,ft Add Single
1Arst0h SUB.S fr,fs,ft f_sub fr,fs,ft Subtract Single
2Arst0h MUL.S fr,fs,ft f_mul fr,fs,ft Multipy Single
4Arst0h MADD.S fr,fs,ft f_muladd fr,fs,ft Multiply+Add Single
5Arst0h MSUB.S fr,fs,ft f_mulsub fr,fs,ft Multiply+Sub Single
8Arsi0h ROUND.S ar,fs,imm4 f_round ar,fs,pow4 Round Single to Fixed
9Arsi0h TRUNC.S ar,fs,imm4 f_trunc ar,fs,pow4 TruncateSingleToFixed
EArsi0h UTRUNC.S ar,fs,imm4 f_utrunc ar,fs,pow4 UnsignedTruncatetoFix
AArsi0h FLOOR.S ar,fs,imm4 f_floor ar,fs,pow4 FloorSingleToFixed
BArsi0h CEIL.S ar,fs,imm4 f_ceil ar,fs,pow4 Ceiling SingleToFixed
CArsi0h FLOAT.S fr,as,imm4 f_float fr,as,frac4 ConvertFixedToSingle
DArsi0h UFLOAT.S fr,as,imm4 f_ufloat fr,as,frac4 UnsignedFixedToSingle
FArs00h MOV.S fr,fs f_mov fr,fs Move Single
FArs10h ABS.S fr,fs f_abs fr,fs Absolute Value Single
FArs40h RFR ar,fs f_mov ar,fs Move FR to AR
FArs50h WFR fr,as f_mov fr,as Move AR to FR
FArs60h NEG.S fr,fs f_neg fr,fs Negate Single
1Brst0h UN.S br,fs,ft f_cmp_un br,fs,ft CompareSingle Unord
2Brst0h OEQ.S br,fs,ft f_cmp_oeq br,fs,ft CompareSingle Equal
3Brst0h UEQ.S br,fs,ft f_cmp_ueq br,fs,ft CompareSingle UnordEq
4Brst0h OLT.S br,fs,ft f_cmp_olt br,fs,ft CompareSingle OrdLt
5Brst0h ULT.S br,fs,ft f_cmp_ult br,fs,ft CompareSingle UnorLt
6Brst0h OLE.S br,fs,ft f_cmp_ole br,fs,ft CompareSingle OrdLt/Eq
7Brst0h ULE.S br,fs,ft f_cmp_ule br,fs,ft CompareSingle UnorLtEq
8Brst0h MOVEQZ.S fr,fs,at f_movz at,fr,fs Move Single if at=0
9Brst0h MOVNEZ.S fr,fs,at f_movnz at,fr,fs Move Single if at<>0
ABrst0h MOVLTZ.S fr,fs,at f_movs at,fr,fs Move Single if at<0
BBrst0h MOVGEZ.S fr,fs,at f_movns at,fr,fs Move Single if at>=0
CBrst0h MOVF.S fr,fs,bt f_movz bt,fr,fs Move Single if bt=0
DBrst0h MOVT.S fr,fs,bt f_movnz bt,fr,fs Move Single if bt=1
pow4: (imm: opcode.bit7..4 = 0..15 aka (1 shl 0..15) aka 1..8000h)
frac4: (imm: opcode.bit7..4 = 0..15 aka (1 shr 0..15) aka 1..1/8000h)
MAC16 Option
mw = m0..m3
mx = m0..m1
my = m2..m3
as,at = a0..a15
acc = special register acchi(8bit):acclo(32bit)
700st4h UMUL.AA.LL as,at umul acc,as_l,at_l ;\
710st4h UMUL.AA.HL as,at umul acc,as_h,at_l ; Unsigned Mul
720st4h UMUL.AA.LH as,at umul acc,as_l,at_h ; acc=as*at
730st4h UMUL.AA.HH as,at umul acc,as_h,at_h ;/
24x0y4h MUL.DD.LL mx,my smul acc,mx_l,my_l ;\
25x0y4h MUL.DD.HL mx,my smul acc,mx_h,my_l ; Signed Mul
26x0y4h MUL.DD.LH mx,my smul acc,mx_l,my_h ; acc=mx*my
27x0y4h MUL.DD.HH mx,my smul acc,mx_h,my_h ;/
340sy4h MUL.AD.LL as,my smul acc,as_l,my_l ;\
350sy4h MUL.AD.HL as,my smul acc,as_h,my_l ; Signed Mul
360sy4h MUL.AD.LH as,my smul acc,as_l,my_h ; acc=as*my
370sy4h MUL.AD.HH as,my smul acc,as_h,my_h ;/
64x0t4h MUL.DA.LL mx,at smul acc,mx_l,at_l ;\
65x0t4h MUL.DA.HL mx,at smul acc,mx_h,at_l ; Signed Mul
66x0t4h MUL.DA.LH mx,at smul acc,mx_l,at_h ; acc=mx*at
67x0t4h MUL.DA.HH mx,at smul acc,mx_h,at_h ;/
740st4h MUL.AA.LL as,at smul acc,as_l,at_l ;\
750st4h MUL.AA.HL as,at smul acc,as_h,at_l ; Signed Mul
760st4h MUL.AA.LH as,at smul acc,as_l,at_h ; acc=as*at
770st4h MUL.AA.HH as,at smul acc,as_h,at_h ;/
28x0y4h MULA.DD.LL mx,my smuladd acc,mx_l,my_l ;\
29x0y4h MULA.DD.HL mx,my smuladd acc,mx_h,my_l ; Signed MulAdd
2Ax0y4h MULA.DD.LH mx,my smuladd acc,mx_l,my_h ; acc=acc+mx*my
2Bx0y4h MULA.DD.HH mx,my smuladd acc,mx_h,my_h ;/
380sy4h MULA.AD.LL as,my smuladd acc,as_l,my_l ;\
390sy4h MULA.AD.HL as,my smuladd acc,as_h,my_l ; Signed MulAdd
3A0sy4h MULA.AD.LH as,my smuladd acc,as_l,my_h ; acc=acc+as*my
3B0sy4h MULA.AD.HH as,my smuladd acc,as_h,my_h ;/
68x0t4h MULA.DA.LL mx,at smuladd acc,mx_l,at_l ;\
69x0t4h MULA.DA.HL mx,at smuladd acc,mx_h,at_l ; Signed MulAdd
6Ax0t4h MULA.DA.LH mx,at smuladd acc,mx_l,at_h ; acc=acc+mx*at
6Bx0t4h MULA.DA.HH mx,at smuladd acc,mx_h,at_h ;/
780st4h MULA.AA.LL as,at smuladd acc,as_l,at_l ;\
790st4h MULA.AA.HL as,at smuladd acc,as_h,at_l ; Signed MulAdd
7A0st4h MULA.AA.LH as,at smuladd acc,as_l,at_h ; acc=acc+as*at
7B0st4h MULA.AA.HH as,at smuladd acc,as_h,at_h ;/
2Cx0y4h MULS.DD.LL mx,my smulsub acc,mx_l,my_l ;\
2Dx0y4h MULS.DD.HL mx,my smulsub acc,mx_h,my_l ; Signed MulSub
2Ex0y4h MULS.DD.LH mx,my smulsub acc,mx_l,my_h ; acc=acc-mx*my
2Fx0y4h MULS.DD.HH mx,my smulsub acc,mx_h,my_h ;/
3C0sy4h MULS.AD.LL as,my smulsub acc,as_l,my_l ;\
3D0sy4h MULS.AD.HL as,my smulsub acc,as_h,my_l ; Signed MulSub
3E0sy4h MULS.AD.LH as,my smulsub acc,as_l,my_h ; acc=acc-as*my
3F0sy4h MULS.AD.HH as,my smulsub acc,as_h,my_h ;/
6Cx0t4h MULS.DA.LL mx,at smulsub acc,mx_l,at_l ;\
6Dx0t4h MULS.DA.HL mx,at smulsub acc,mx_h,at_l ; Signed MulSub
6Ex0t4h MULS.DA.LH mx,at smulsub acc,mx_l,at_h ; acc=acc-mx*at
6Fx0t4h MULS.DA.HH mx,at smulsub acc,mx_h,at_h ;/
7C0st4h MULS.AA.LL as,at smulsub acc,as_l,at_l ;\
7D0st4h MULS.AA.HL as,at smulsub acc,as_h,at_l ; Signed MulSub
7E0st4h MULS.AA.LH as,at smulsub acc,as_l,at_h ; acc=acc-as*at
7F0st4h MULS.AA.HH as,at smulsub acc,as_h,at_h ;/
80ws04h LDINC mw,as movupd mw,[as+4] ;Load+AutoInc
90ws04h LDDEC mw,as movupd mw,[as-4] ;Load+AutoDec
Below opcodes are doing two separate things:
1. acc=acc+x*y ;Signed MulAdd
2. as=as+/-4, mw=[as] ;Load mw from memory (for use by NEXT opcode)
08wsy4h MULA.DD.LL.LDINC mw,as,mx,my smuladd_movupd acc,mx_l,my_l,mw,[as+4]
09wsy4h MULA.DD.HL.LDINC mw,as,mx,my smuladd_movupd acc,mx_h,my_l,mw,[as+4]
0Awsy4h MULA.DD.LH.LDINC mw,as,mx,my smuladd_movupd acc,mx_l,my_h,mw,[as+4]
0Bwsy4h MULA.DD.HH.LDINC mw,as,mx,my smuladd_movupd acc,mx_h,my_h,mw,[as+4]
18wsy4h MULA.DD.LL.LDDEC mw,as,mx,my smuladd_movupd acc,mx_l,my_l,mw,[as-4]
19wsy4h MULA.DD.HL.LDDEC mw,as,mx,my smuladd_movupd acc,mx_h,my_l,mw,[as-4]
1Awsy4h MULA.DD.LH.LDDEC mw,as,mx,my smuladd_movupd acc,mx_l,my_h,mw,[as-4]
1Bwsy4h MULA.DD.HH.LDDEC mw,as,mx,my smuladd_movupd acc,mx_h,my_h,mw,[as-4]
48wst4h MULA.DA.LL.LDINC mw,as,mx,at smuladd_movupd acc,mx_l,at_l,mw,[as+4]
49wst4h MULA.DA.HL.LDINC mw,as,mx,at smuladd_movupd acc,mx_h,at_l,mw,[as+4]
4Awst4h MULA.DA.LH.LDINC mw,as,mx,at smuladd_movupd acc,mx_l,at_h,mw,[as+4]
4Bwst4h MULA.DA.HH.LDINC mw,as,mx,at smuladd_movupd acc,mx_h,at_h,mw,[as+4]
58wst4h MULA.DA.LL.LDDEC mw,as,mx,at smuladd_movupd acc,mx_l,at_l,mw,[as-4]
59wst4h MULA.DA.HL.LDDEC mw,as,mx,at smuladd_movupd acc,mx_h,at_l,mw,[as-4]
5Awst4h MULA.DA.LH.LDDEC mw,as,mx,at smuladd_movupd acc,mx_l,at_h,mw,[as-4]
5Bwst4h MULA.DA.HH.LDDEC mw,as,mx,at smuladd_movupd acc,mx_h,at_h,mw,[as-4]
Xtensa Opcodes
Xtensa opcodes are 24bit wide (or 16bit for "narrow" opcodes), the opcodes
consist of several 4bit fields (or 2bit, 8bit, 12bit, 16bit, 18bit fields in
some cases):
23-20 19-16 15-12 11-8 7-4 3-0 Type
op2 op1 r s t op0 RRR
imm4 op1 r s t op0 RRI4
imm8--------> r s t op0 RRI8
imm16-------------------> t op0 RRI16
op2 op1 rs--------> t op0 RSR
offset----------------------> n op0 CALL
op2 op1 r s m n op0 CALLX
imm8--------> r s m n op0 BRI8
imm12-------------> s m n op0 BRI8
r s t op0 RRRN
imm.l s imm.h op0 RI7 (bit7="i")
imm.l s imm.h op0 RI6 (bit7="i", bit6="z")
rtc_wlan_reg.h (hw4.0)
004000h 4 WLAN_RESET_CONTROL
004004h 4 WLAN_XTAL_CONTROL
004008h 4 WLAN_TCXO_DETECT
00400Ch 4 WLAN_XTAL_TEST
004010h 4 WLAN_QUADRATURE
004014h 4 WLAN_PLL_CONTROL
004018h 4 WLAN_PLL_SETTLE
00401Ch 4 WLAN_XTAL_SETTLE
004020h 4 WLAN_CPU_CLOCK
004024h 4 WLAN_CLOCK_OUT
004028h 4 WLAN_CLOCK_CONTROL
00402Ch 4 WLAN_BIAS_OVERRIDE
004030h 4 WLAN_WDT_CONTROL ;\
004034h 4 WLAN_WDT_STATUS ;
004038h 4 WLAN_WDT ; Watchdog Timer
00403Ch 4 WLAN_WDT_COUNT ;
004040h 4 WLAN_WDT_RESET ;/
004044h 4 WLAN_INT_STATUS ;-Interrupt Status
004048h 4 WLAN_LF_TIMER0 ;\
00404Ch 4 WLAN_LF_TIMER_COUNT0 ; Low-Freq Timer 0
004050h 4 WLAN_LF_TIMER_CONTROL0 ;
004054h 4 WLAN_LF_TIMER_STATUS0 ;/
004058h 4 WLAN_LF_TIMER1 ;\
00405Ch 4 WLAN_LF_TIMER_COUNT1 ; Low-Freq Timer 1
004060h 4 WLAN_LF_TIMER_CONTROL1 ;
004064h 4 WLAN_LF_TIMER_STATUS1 ;/
004068h 4 WLAN_LF_TIMER2 ;\
00406Ch 4 WLAN_LF_TIMER_COUNT2 ; Low-Freq Timer 2
004070h 4 WLAN_LF_TIMER_CONTROL2 ;
004074h 4 WLAN_LF_TIMER_STATUS2 ;/
004078h 4 WLAN_LF_TIMER3 ;\
00407Ch 4 WLAN_LF_TIMER_COUNT3 ; Low-Freq Timer 3
004080h 4 WLAN_LF_TIMER_CONTROL3 ;
004084h 4 WLAN_LF_TIMER_STATUS3 ;/
004088h 4 WLAN_HF_TIMER ;\
00408Ch 4 WLAN_HF_TIMER_COUNT ; High-Freq Timer
004090h 4 WLAN_HF_LF_COUNT ;<-- ;
004094h 4 WLAN_HF_TIMER_CONTROL ;
004098h 4 WLAN_HF_TIMER_STATUS ;/
00409Ch 4 WLAN_RTC_CONTROL ;\
0040A0h 4 WLAN_RTC_TIME ;
0040A4h 4 WLAN_RTC_DATE ;
0040A8h 4 WLAN_RTC_SET_TIME ; Real-Time Clock
0040ACh 4 WLAN_RTC_SET_DATE ;
0040B0h 4 WLAN_RTC_SET_ALARM ;
0040B4h 4 WLAN_RTC_CONFIG ;
0040B8h 4 WLAN_RTC_ALARM_STATUS ;/
0040BCh 4 WLAN_UART_WAKEUP
0040C0h 4 WLAN_RESET_CAUSE
0040C4h 4 WLAN_SYSTEM_SLEEP
0040C8h 4 WLAN_SDIO_WRAPPER
0040CCh 4 WLAN_MAC_SLEEP_CONTROL
0040D0h 4 WLAN_KEEP_AWAKE
0040D4h 4 WLAN_LPO_CAL_TIME ;\
0040D8h 4 WLAN_LPO_INIT_DIVIDEND_INT ;
0040DCh 4 WLAN_LPO_INIT_DIVIDEND_FRACTION ; LPO
0040E0h 4 WLAN_LPO_CAL ;
0040E4h 4 WLAN_LPO_CAL_TEST_CONTROL ;
0040E8h 4 WLAN_LPO_CAL_TEST_STATUS ;/
0040ECh 4 WLAN_CHIP_ID ;-Chip ID
0040F0h 4 WLAN_DERIVED_RTC_CLK
0040F4h 4 MAC_PCU_SLP32_MODE ;\
0040F8h 4 MAC_PCU_SLP32_WAKE ;
0040FCh 4 MAC_PCU_SLP32_INC ;
004100h 4 MAC_PCU_SLP_MIB1 ;
004104h 4 MAC_PCU_SLP_MIB2 ;
004108h 4 MAC_PCU_SLP_MIB3 ;/
00410Ch 4 WLAN_POWER_REG ;\located here in hw4.0
004110h 4 WLAN_CORE_CLK_CTRL ; (other address as in hw2.0)
004114h 4 WLAN_GPIO_WAKEUP_CONTROL ;/
(below 4118h..42E8h is new in hw4.0, didn't exist in hw2.0)
004118h 4 (WLAN_)HT
00411Ch 4 MAC_PCU_TSF_L32
004120h 4 MAC_PCU_TSF_U32
004124h 4 MAC_PCU_WBTIMER
004128h 1x24 PAD0
004140h 4x16 MAC_PCU_GENERIC_TIMERS[0..15]
004180h 4 MAC_PCU_GENERIC_TIMERS_MODE
004184h 1x60 PAD1
0041C0h 4x16 MAC_PCU_GENERIC_TIMERS2[0..15]
004200h 4 MAC_PCU_GENERIC_TIMERS_MODE2
004204h 4 MAC_PCU_SLP1
004208h 4 MAC_PCU_SLP2
00420Ch 4 MAC_PCU_RESET_TSF
004210h 4 MAC_PCU_TSF_ADD_PLL
004214h 4 SLEEP_RETENTION
004218h 4 BTCOEXCTRL ;\
00421Ch 4 WBSYNC_PRIORITY1 ;
004220h 4 WBSYNC_PRIORITY2 ;
004224h 4 WBSYNC_PRIORITY3 ;
004228h 4 BTCOEX0 ;SYNC_DUR ;
00422Ch 4 BTCOEX1 ;CLK_THRES ;
004230h 4 BTCOEX2 ;FRAME_THRES ; Bluetooth
004234h 4 BTCOEX3 ;CLK_CNT ; Coexistance
004238h 4 BTCOEX4 ;FRAME_CNT ;
00423Ch 4 BTCOEX5 ;IDLE_CNT ;
004240h 4 BTCOEX6 ;IDLE_RESET_LVL_BITMAP ;
004244h 4 LOCK ;
004248h 4 NOLOCK_PRIORITY ;
00424Ch 4 WBSYNC ;
004250h 4 WBSYNC1 ;
004254h 4 WBSYNC2 ;
004258h 4 WBSYNC3 ;
00425Ch 4 WB_TIMER_TARGET ;
004260h 4 WB_TIMER_SLOP ;
004264h 4 BTCOEX_INT_EN ;
004268h 4 BTCOEX_INT_STAT ;
00426Ch 4 BTPRIORITY_INT_EN ;
004270h 4 BTPRIORITY_INT_STAT ;
004274h 4 BTPRIORITY_STOMP_INT_EN ;
004278h 4 BTPRIORITY_STOMP_INT_STAT ;/
00427Ch 4 MAC_PCU_BMISS_TIMEOUT
004280h 4 MAC_PCU_CAB_AWAKE
004284h 4 LP_PERF_COUNTER
004288h 4 LP_PERF_LIGHT_SLEEP
00428Ch 4 LP_PERF_DEEP_SLEEP
004290h 4 LP_PERF_ON
004294h 4 ST_64_BIT ;\
004298h 4 MESSAGE_WR ; also Bluetooth Coex
00429Ch 4 MESSAGE_WR_P ; related? (sorted as
0042A0h 4 MESSAGE_RD ; so in hw6 files)
0042A4h 4 MESSAGE_RD_P ;/
0042A8h 4 CHIP_MODE
0042ACh 4 CLK_REQ_FALL_EDGE
0042B0h 4 OTP
0042B4h 4 OTP_STATUS
0042B8h 4 PMU
0042BCh 1x4 PAD2
0042C0h 4x2 PMU_CONFIG[0..1]
0042C8h 4 PMU_BYPASS
0042CCh 4 MAC_PCU_TSF2_L32
0042D0h 4 MAC_PCU_TSF2_U32
0042D4h 4 MAC_PCU_GENERIC_TIMERS_MODE3
0042D8h 4 MAC_PCU_DIRECT_CONNECT
0042DCh 4 THERM_CTRL1
0042E0h 4 THERM_CTRL2
0042E4h 4 THERM_CTRL3
0042E8h - unused/unspecified
vmc_wlan_reg.h (hw4.0)
008000h 4x128 WLAN_MC_BCAM_VALID[0..127] ;\
008200h 4x128 WLAN_MC_BCAM_COMPARE[0..127] ; ROM Patches
008400h 4x128 WLAN_MC_BCAM_TARGET[0..127] ;/
008600h 4 WLAN_APB_ADDR_ERROR_CONTROL ;\
008604h 4 WLAN_APB_ADDR_ERROR_STATUS ; ADDR_ERROR
008608h 4 WLAN_AHB_ADDR_ERROR_CONTROL ;
00860Ch 4 WLAN_AHB_ADDR_ERROR_STATUS ;/
008610h 4 WLAN_BCAM_CONFLICT_ERROR
008614h 4 WLAN_CPU_PERF_CNT
008618h 4 WLAN_CPU_INST_FETCH
00861Ch 4 WLAN_CPU_DATA_FETCH
008620h 4 WLAN_CPU_RAM1_CONFLICT
008624h 4 WLAN_CPU_RAM2_CONFLICT
008628h 4 WLAN_CPU_RAM3_CONFLICT
00862Ch 4 WLAN_CPU_RAM4_CONFLICT
008630h - unused/unspecified
uart_reg.h (hw4.0)
00C000h 4 UART_DATA
00C004h 4 UART_CONTROL
00C008h 4 UART_CLKDIV
00C00Ch 4 UART_INT
00C010h 4 UART_INT_EN
00C014h - unused/unspecified
00D000h .. DBG_UART_BASE_ADDRESS ;another UART, as above, for debug?
00Dxxxh - unused/unspecified
umbox_wlan_reg.h (hw4.0)
00E000h 4x2 UMBOX_FIFO[0..1]
00E008h 4 UMBOX_FIFO_STATUS
00E00Ch 4 UMBOX_DMA_POLICY
00E010h 4 UMBOX0_DMA_RX_DESCRIPTOR_BASE
00E014h 4 UMBOX0_DMA_RX_CONTROL
00E018h 4 UMBOX0_DMA_TX_DESCRIPTOR_BASE
00E01Ch 4 UMBOX0_DMA_TX_CONTROL
00E020h 4 UMBOX_FIFO_TIMEOUT
00E024h 4 UMBOX_INT_STATUS
00E028h 4 UMBOX_INT_ENABLE
00E02Ch 4 UMBOX_DEBUG
00E030h 4 UMBOX_FIFO_RESET
00E034h 4 UMBOX_HCI_FRAMER
00E038h - unused/unspecified
si_reg.h (hw4.0)
010000h 4 SI_CONFIG
010004h 4 SI_CS
010008h 4 SI_TX_DATA0
01000Ch 4 SI_TX_DATA1
010010h 4 SI_RX_DATA0
010014h 4 SI_RX_DATA1
010018h - unused/unspecified
gpio_athr_wlan_reg.h (hw4.0)
014000h 4 WLAN_GPIO_OUT ;\GPIO Output Data
014004h 4 WLAN_GPIO_OUT_W1TS ; (direct, and Write-1-To-Set/Clr)
014008h 4 WLAN_GPIO_OUT_W1TC ;/
01400Ch 4 WLAN_GPIO_ENABLE ;\GPIO Output Enable
014010h 4 WLAN_GPIO_ENABLE_W1TS ; (direct, and Write-1-To-Set/Clr)
014014h 4 WLAN_GPIO_ENABLE_W1TC ;/
014018h 4 WLAN_GPIO_IN ;-GPIO Input
01401Ch 4 WLAN_GPIO_STATUS ;\GPIO Interrupt Status
014020h 4 WLAN_GPIO_STATUS_W1TS ; (direct, and Write-1-To-Set/Clr)
014024h 4 WLAN_GPIO_STATUS_W1TC ;/
014028h 4 WLAN_GPIO_PIN0 ;GPIO0 Bluetooth coex BT_FREQUENCY
01402Ch 4 WLAN_GPIO_PIN1 ;GPIO1 Bluetooth coex WLAN_ACTIVE
014030h 4 WLAN_GPIO_PIN2 ;GPIO2 Bluetooth coex BT_ACTIVE
014034h 4 WLAN_GPIO_PIN3 ;GPIO3 Bluetooth coex BT_PRIORITY
014038h 4 WLAN_GPIO_PIN4 ;GPIO4 -
01403Ch 4 WLAN_GPIO_PIN5 ;GPIO5 JTAG TMS input
014040h 4 WLAN_GPIO_PIN6 ;GPIO6 JTAG TCK input
014044h 4 WLAN_GPIO_PIN7 ;GPIO7 JTAG TDI input
014048h 4 WLAN_GPIO_PIN8 ;GPIO8 JTAG TDO output
01404Ch 4 WLAN_GPIO_PIN9 ;GPIO9 SDIO CMD
014050h 4 WLAN_GPIO_PIN10 ;GPIO10 SDIO D3
014054h 4 WLAN_GPIO_PIN11 ;GPIO11 SDIO D2
014058h 4 WLAN_GPIO_PIN12 ;GPIO12 SDIO D1
01405Ch 4 WLAN_GPIO_PIN13 ;GPIO13 SDIO D0
014060h 4 WLAN_GPIO_PIN14 ;GPIO14 SDIO CLK
014064h 4 WLAN_GPIO_PIN15 ;GPIO15 HCI UART TXD
014068h 4 WLAN_GPIO_PIN16 ;GPIO16 HCI UART RTS
01406Ch 4 WLAN_GPIO_PIN17 ;GPIO17 HCI UART RXD
014070h 4 WLAN_GPIO_PIN18 ;GPIO18 HCI UART CTS
014074h 4 WLAN_GPIO_PIN19 ;GPIO19 SDIO/GSPI interface select
014078h 4 WLAN_GPIO_PIN20 ;GPIO20 SDIO/GSPI interface select
01407Ch 4 WLAN_GPIO_PIN21 ;GPIO21 external input sleep clock
014080h 4 WLAN_GPIO_PIN22 ;GPIO22 wake on wireless input (WOW)
014084h 4 WLAN_GPIO_PIN23 ;GPIO23 reference clk output to BT chip
014088h 4 WLAN_GPIO_PIN24 ;GPIO24 request clk from BT chip
01408Ch 4 WLAN_GPIO_PIN25 ;GPIO25 request reference clk (CLK_REQ)
014090h 4 SDIO
014094h 4 FUNC_BUS
014098h 4 WL_SOC_APB
01409Ch 4 WLAN_SIGMA_DELTA
0140A0h 4 WL_BOOTSTRAP
0140A4h 4 CLOCK_GPIO
0140A8h 4 WLAN_DEBUG_CONTROL
0140ACh 4 WLAN_DEBUG_INPUT_SEL
0140B0h 4 WLAN_DEBUG_OUT
0140B4h 4 WLAN_RESET_TUPLE_STATUS
0140B8h 4 ANTENNA_SLEEP_CONTROL
0140BCh - unused/unspecified
MBOX Registers (mbox_wlan_reg.h) (hw4.0)
018000h 4x4 WLAN_MBOX_FIFO[0..3]
018010h 4 WLAN_MBOX_FIFO_STATUS
018014h 4 WLAN_MBOX_DMA_POLICY
018018h 4 WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE ;\
01801Ch 4 WLAN_MBOX0_DMA_RX_CONTROL ; MBOX 0
018020h 4 WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE ;
018024h 4 WLAN_MBOX0_DMA_TX_CONTROL ;/
018028h 4 WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE ;\
01802Ch 4 WLAN_MBOX1_DMA_RX_CONTROL ; MBOX 1
018030h 4 WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE ;
018034h 4 WLAN_MBOX1_DMA_TX_CONTROL ;/
018038h 4 WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE ;\
01803Ch 4 WLAN_MBOX2_DMA_RX_CONTROL ; MBOX 2
018040h 4 WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE ;
018044h 4 WLAN_MBOX2_DMA_TX_CONTROL ;/
018048h 4 WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE ;\
01804Ch 4 WLAN_MBOX3_DMA_RX_CONTROL ; MBOX 3
018050h 4 WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE ;
018054h 4 WLAN_MBOX3_DMA_TX_CONTROL ;/
018058h 4 WLAN_MBOX_INT_STATUS ;\Interrupt
01805Ch 4 WLAN_MBOX_INT_ENABLE ;/
018060h 4 WLAN_INT_HOST ;IRQ to sdio/host
018064h 1x28 PAD0
018080h 4x8 WLAN_LOCAL_COUNT[0..7] ;SDIO func1 ?
0180A0h 4x8 WLAN_COUNT_INC[0..7] ;SDIO func1 ?
0180C0h 4x8 WLAN_LOCAL_SCRATCH[0..7] ;SDIO func1 ?
0180E0h 4 WLAN_USE_LOCAL_BUS
0180E4h 4 WLAN_SDIO_CONFIG ;SDIO func0 ?
0180E8h 4 WLAN_MBOX_DEBUG
0180ECh 4 WLAN_MBOX_FIFO_RESET
0180F0h 4x4 WLAN_MBOX_TXFIFO_POP[0..3]
018100h 4x4 WLAN_MBOX_RXFIFO_POP[0..3]
018110h 4 WLAN_SDIO_DEBUG
018114h 4 WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE ;\
018118h 4 WLAN_GMBOX0_DMA_RX_CONTROL ;
01811Ch 4 WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE ; new (unlike hw2.0)
018120h 4 WLAN_GMBOX0_DMA_TX_CONTROL ;
018124h 4 WLAN_GMBOX_INT_STATUS ;
018128h 4 WLAN_GMBOX_INT_ENABLE ;/
01812Ch 1x7892 PAD1
01A000h 4x2048 WLAN_HOST_IF_WINDOW[0..2047]
analog_intf_athr_wlan_reg.h (hw4.0)
01C000h 4 RXRF_BIAS1
01C004h 4 RXRF_BIAS2
01C008h 4 RXRF_GAINSTAGES
01C00Ch 4 RXRF_AGC
01C010h 1x48 PAD__0
01C040h 4 TXRF1
01C044h 4 TXRF2
01C048h 4 TXRF3
01C04Ch 4 TXRF4
01C050h 4 TXRF5
01C054h 4 TXRF6
01C058h 4 TXRF7 ;PADRVGNTAB_0..4 ;\
01C05Ch 4 TXRF8 ;PADRVGNTAB_5..9 ;
01C060h 4 TXRF9 ;PADRVGNTAB_10..14 ;/
01C064h 4 TXRF10
01C068h 4 TXRF11
01C06Ch 4 TXRF12
01C070h 1x16 PAD__1
01C080h 4 SYNTH1
01C084h 4 SYNTH2
01C088h 4 SYNTH3
01C08Ch 4 SYNTH4
01C090h 4 SYNTH5
01C094h 4 SYNTH6
01C098h 4 SYNTH7
01C09Ch 4 SYNTH8
01C0A0h 4 SYNTH9
01C0A4h 4 SYNTH10
01C0A8h 4 SYNTH11
01C0ACh 4 SYNTH12
01C0B0h 4 SYNTH13
01C0B4h 4 SYNTH14
01C0B8h 1x8 PAD__2
01C0C0h 4 BIAS1
01C0C4h 4 BIAS2
01C0C8h 4 BIAS3
01C0CCh 4 BIAS4
01C0D0h 1x48 PAD__3
01C100h 4 RXTX1
01C104h 4 RXTX2
01C108h 4 RXTX3
01C10Ch 1x52 PAD__4
01C140h 4 BB1
01C144h 4 BB2
01C148h 4 BB3
01C14Ch 1x308 PAD__5
01C280h 4 PLLCLKMODA
01C284h 4 PLLCLKMODA2
01C288h 4 TOP
01C28Ch 4 THERM
01C290h 4 XTAL
01C294h 1x236 PAD__6
01C380h 4 RBIST_CNTRL ;with extra bit in newer revision
01C384h 4 TX_DC_OFFSET
01C388h 4 TX_TONEGEN0
01C38Ch 4 TX_TONEGEN1
01C390h 4 TX_LFTONEGEN0
01C394h 4 TX_LINEAR_RAMP_I
01C398h 4 TX_LINEAR_RAMP_Q
01C39Ch 4 TX_PRBS_MAG
01C3A0h 4 TX_PRBS_SEED_I
01C3A4h 4 TX_PRBS_SEED_Q
01C3A8h 4 CMAC_DC_CANCEL
01C3ACh 4 CMAC_DC_OFFSET
01C3B0h 4 CMAC_CORR
01C3B4h 4 CMAC_POWER
01C3B8h 4 CMAC_CROSS_CORR
01C3BCh 4 CMAC_I2Q2
01C3C0h 4 CMAC_POWER_HPF
01C3C4h 4 RXDAC_SET1
01C3C8h 4 RXDAC_SET2
01C3CCh 4 RXDAC_LONG_SHIFT
01C3D0h 4 CMAC_RESULTS_I
01C3D4h 4 CMAC_RESULTS_Q
01C3D8h 1x872 PAD__7
01C740h 4 PMU1
01C744h 4 PMU2
01C748h - unused/unspecified
mac_dma_reg.h (hw4.0)
020000h 1x8 -
020008h 4 MAC_DMA_CR - MAC Control Register
02000Ch 4 MAC_DMA_RXDP - MAC receive queue descriptor pointer
020010h 4 -
020014h 4 MAC_DMA_CFG - MAC configuration and status register
020018h 4 -
02001Ch 4 -
020020h 4 MAC_DMA_MIRT - Maximum rate threshold register
020024h 4 MAC_DMA_IER - MAC Interrupt enable register
020028h 4 MAC_DMA_TIMT - Transmit Interrupt Mitigation Threshold
02002Ch 4 MAC_DMA_RIMT - Receive Interrupt Mitigation Threshold
020030h 4 MAC_DMA_TXCFG - MAC tx DMA size config register
020034h 4 MAC_DMA_RXCFG - MAC rx DMA size config register
020038h 4 -
02003Ch 4 -
020040h 4 MAC_DMA_MIBC - MAC MIB control register
020044h 4 MAC_DMA_TOPS - MAC timeout prescale count
020048h 4 MAC_DMA_RXNPTO - MAC no frame received timeout
02004Ch 4 MAC_DMA_TXNPTO - MAC no frame trasmitted timeout
020050h 4 MAC_DMA_RPGTO - MAC receive frame gap timeout
020054h 4 MAC_DMA_RPCNT - MAC receive frame count limit
020058h 4 MAC_DMA_MACMISC - MAC miscellaneous control/status register
02005Ch .. -
MAC IRQ...
020080h 4 MAC_DMA_ISR - Primary Interrupt Status Register ;\
020084h 4 MAC_DMA_ISR_S0 - Secondary Interrupt 0 Status TX OK/DESC ;
020088h 4 MAC_DMA_ISR_S1 - Secondary Interrupt 1 Status TX ERR/EOL ;
02008Ch 4 MAC_DMA_ISR_S2 - Secondary Interrupt 2 Status TX URN/MISC ;
020090h 4 MAC_DMA_ISR_S3 - Secondary Interrupt 3 Status QCBR OVF/URN ;
020094h 4 MAC_DMA_ISR_S4 - Secondary Interrupt 4 Status QTRIG ;
020098h 4 MAC_DMA_ISR_S5 - Secondary Interrupt 5 Status TIMERS ;/
02009Ch 4 -
0200A0h 4 MAC_DMA_IMR - Primary Interrupt Mask Register ;\
0200A4h 4 MAC_DMA_IMR_S0 - Secondary Interrupt 0 Mask TX OK/DESC ;
0200A8h 4 MAC_DMA_IMR_S1 - Secondary Interrupt 1 Mask TX ERR/EOL ;
0200ACh 4 MAC_DMA_IMR_S2 - Secondary Interrupt 2 Mask TX URN/MISC ;
0200B0h 4 MAC_DMA_IMR_S3 - Secondary Interrupt 3 Mask QCBR OVF/URN ;
0200B4h 4 MAC_DMA_IMR_S4 - Secondary Interrupt 4 Mask QTRIG ;
0200B8h 4 MAC_DMA_IMR_S5 - Secondary Interrupt 5 Mask TIMERS ;/
0200BCh 4 -
0200C0h 4 MAC_DMA_ISR_RAC - Primary Interrupt Read-and-Clear ;\
0200C4h 4 MAC_DMA_ISR_S0_S - Secondary 0 Read-and-Clear TX OK/DESC ;
0200C8h 4 MAC_DMA_ISR_S1_S - Secondary 1 Read-and-Clear TX ERR/EOL ;
0200CCh 4 MAC_DMA_ISR_S2_S - Secondary 2 Read-and-Clear TX URN/MISC ;
0200D0h 4 MAC_DMA_ISR_S3_S - Secondary 3 Read-and-Clear QCBR OVF/URN ;
0200D4h 4 MAC_DMA_ISR_S4_S - Secondary 4 Read-and-Clear QTRIG ;
0200D8h 4 MAC_DMA_ISR_S5_S - Secondary 5 Read-and-Clear TIMERS ;/
0200DCh .. -
MAC QCU...
020800h 4x10 MAC_DMA_Q(0..9)_TXDP ;MAC Transmit Queue descr.ptr
020828h .. -
020840h 4 MAC_DMA_Q_TXE ;MAC Transmit Queue enable
020844h .. -
020880h 4 MAC_DMA_Q_TXD ;MAC Transmit Queue disable
020884h .. -
0208C0h 4x10 MAC_DMA_Q(0..9)_CBRCFG ;MAC CBR configuration
0208E8h .. -
020900h 4x10 MAC_DMA_Q(0..9)_RDYTIMECFG ;MAC ReadyTime configuration
020928h .. -
020940h 4 MAC_DMA_Q_ONESHOTMAC_DMAM_SC ;MAC OneShotArm set control
020944h .. -
020980h 4 MAC_DMA_Q_ONESHOTMAC_DMAM_CC ;MAC OneShotArm clear control
020984h .. -
0209C0h 4x10 MAC_DMA_Q(0..9)_MISC ;MAC Misc QCU settings
0209E8h .. -
020A00h 4x10 MAC_DMA_Q(0..9)_STS ;MAC Misc QCU status/counter
020A28h .. -
020A40h 4 MAC_DMA_Q_RDYTIMESHDN ;MAC ReadyTimeShutdown status
020A44h .. -
MAC DCU...
021000h 4x10 MAC_DMA_D(0..9)_QCUMASK - MAC QCU Mask (DCU-to-QCU or so?)
021028h 8 -
021030h 4 MAC_DMA_D_GBL_IFS_SIFS - DCU global SIFS settings
021034h 12 -
021040h 4x10 MAC_DMA_D(0..9)_LCL_IFS - MAC DCU-specific IFS settings
021068h 8 -
021070h 4 MAC_DMA_D_GBL_IFS_SLOT - DC global slot interval
021074h 12 -
021080h 4x10 MAC_DMA_D(0..9)_RETRY_LIMIT - MAC Retry limits
0210A8h 8 -
0210B0h 4 MAC_DMA_D_GBL_IFS_EIFS - DCU global EIFS setting
0210B4h 12 -
0210C0h 4x10 MAC_DMA_D(0..9)_CHNTIME - MAC ChannelTime settings
0210E8h 8 -
0210F0h 4 MAC_DMA_D_GBL_IFS_MISC - DCU global misc. IFS settings
0210F4h 12 -
021100h 4x10 MAC_DMA_D(0..9)_MISC - MAC Misc DCU-specific settings
021128h .. -
021140h 4 MAC_DMA_D_SEQNUM - MAC Frame sequence number
021144h .. -
021180h 4x10 MAC_DMA_D(0..9)_EOL -
0211A8h .. -
021230h 4 MAC_DMA_D_FPCTL - DCU frame prefetch settings
021234h .. -
021270h 4 MAC_DMA_D_TXPSE - DCU transmit pause control/status
021274h .. -
bb_lc_reg.h (hw4.0)
"BASEBAND_0"
029800h 4 BB_TEST_CONTROLS
029804h 4 BB_GEN_CONTROLS
029808h 4 BB_TEST_CONTROLS_STATUS
02980Ch 4 BB_TIMING_CONTROLS_1
029810h 4 BB_TIMING_CONTROLS_2
029814h 4 BB_TIMING_CONTROLS_3
029818h 4 BB_D2_CHIP_ID
02981Ch 4 BB_ACTIVE
029820h 4 BB_TX_TIMING_1
029824h 4 BB_TX_TIMING_2
029828h 4 BB_TX_TIMING_3
02982Ch 4 BB_ADDAC_PARALLEL_CONTROL
029830h 1x4 PAD__1
029834h 4 BB_XPA_TIMING_CONTROL
029838h 4 BB_MISC_PA_CONTROL
02983Ch 4 BB_TSTDAC_CONSTANT
029840h 4 BB_FIND_SIGNAL_LOW
029844h 4 BB_SETTLING_TIME
029848h 4 BB_GAIN_FORCE_MAX_GAINS_B0
02984Ch 4 BB_GAINS_MIN_OFFSETS_B0
029850h 4 BB_DESIRED_SIGSIZE
029854h 4 BB_TIMING_CONTROL_3A
029858h 4 BB_FIND_SIGNAL
02985Ch 4 BB_AGC
029860h 4 BB_AGC_CONTROL
029864h 4 BB_CCA_B0
029868h 4 BB_SFCORR
02986Ch 4 BB_SELF_CORR_LOW
029870h 1x4 PAD__2
029874h 4 BB_SYNTH_CONTROL
029878h 4 BB_ADDAC_CLK_SELECT
02987Ch 4 BB_PLL_CNTL
029880h 1x128 PAD__3
029900h 4 BB_VIT_SPUR_MASK_A
029904h 4 BB_VIT_SPUR_MASK_B
029908h 4 BB_PILOT_SPUR_MASK
02990Ch 4 BB_CHAN_SPUR_MASK
029910h 4 BB_SPECTRAL_SCAN
029914h 4 BB_ANALOG_POWER_ON_TIME
029918h 4 BB_SEARCH_START_DELAY
02991Ch 4 BB_MAX_RX_LENGTH
029920h 4 BB_TIMING_CONTROL_4
029924h 4 BB_TIMING_CONTROL_5
029928h 4 BB_PHYONLY_WARM_RESET
02992Ch 4 BB_PHYONLY_CONTROL
029930h 1x4 PAD__4
029934h 4 BB_POWERTX_RATE1 ;Power TX 0..3
029938h 4 BB_POWERTX_RATE2 ;Power TX 4..7
02993Ch 4 BB_POWERTX_MAX ;Power TX Flags
029940h 4 BB_EXTENSION_RADAR
029944h 4 BB_FRAME_CONTROL
029948h 4 BB_TIMING_CONTROL_6
02994Ch 4 BB_SPUR_MASK_CONTROLS
029950h 4 BB_RX_IQ_CORR_B0
029954h 4 BB_RADAR_DETECTION
029958h 4 BB_RADAR_DETECTION_2
02995Ch 4 BB_TX_PHASE_RAMP_B0
029960h 4 BB_SWITCH_TABLE_CHN_B0
029964h 4 BB_SWITCH_TABLE_COM1
029968h 4 BB_CCA_CTRL_2_B0
02996Ch 4 BB_SWITCH_TABLE_COM2
029970h 4 BB_RESTART
029974h 1x4 PAD__5
029978h 4 BB_SCRAMBLER_SEED
02997Ch 4 BB_RFBUS_REQUEST
029980h 1x32 PAD__6
0299A0h 4 BB_TIMING_CONTROL_11
0299A4h 4 BB_MULTICHAIN_ENABLE
0299A8h 4 BB_MULTICHAIN_CONTROL
0299ACh 4 BB_MULTICHAIN_GAIN_CTRL
0299B0h 1x4 PAD__7
0299B4h 4 BB_ADC_GAIN_DC_CORR_B0
0299B8h 4 BB_EXT_CHAN_PWR_THR_1
0299BCh 4 BB_EXT_CHAN_PWR_THR_2_B0
0299C0h 4 BB_EXT_CHAN_SCORR_THR
0299C4h 4 BB_EXT_CHAN_DETECT_WIN
0299C8h 4 BB_PWR_THR_20_40_DET
0299CCh 1x4 PAD__8
0299D0h 4 BB_SHORT_GI_DELTA_SLOPE
0299D4h 1x8 PAD__9
0299DCh 4 BB_CHANINFO_CTRL
0299E0h 4 BB_HEAVY_CLIP_CTRL
0299E4h 4 BB_HEAVY_CLIP_20
0299E8h 4 BB_HEAVY_CLIP_40
0299ECh 4 BB_RIFS_SRCH
0299F0h 4 BB_IQ_ADC_CAL_MODE
0299F4h 1x8 PAD__10
0299FCh 4 BB_PER_CHAIN_CSD
029A00h 4x128 BB_RX_OCGAIN[0..127]
029C00h 4 BB_TX_CRC
029C04h 1x12 PAD__11
029C10h 4 BB_IQ_ADC_MEAS_0_B0
029C14h 4 BB_IQ_ADC_MEAS_1_B0
029C18h 4 BB_IQ_ADC_MEAS_2_B0
029C1Ch 4 BB_IQ_ADC_MEAS_3_B0
029C20h 4 BB_RFBUS_GRANT
029C24h 4 BB_TSTADC
029C28h 4 BB_TSTDAC
029C2Ch 1x4 PAD__12
029C30h 4 BB_ILLEGAL_TX_RATE
029C34h 4 BB_SPUR_REPORT_B0
029C38h 4 BB_CHANNEL_STATUS
029C3Ch 4 BB_RSSI_B0
029C40h 4 BB_SPUR_EST_CCK_REPORT_B0
029C44h 1x104 PAD__13 ;(old 1x172)
029CF0h 4 BB_CHAN_INFO_NOISE_PWR ;\
029CF4h 4 BB_CHAN_INFO_GAIN_DIFF ; located HERE in
029CF8h 4 BB_CHAN_INFO_FINE_TIMING ; older revision
029CFCh 4 BB_CHAN_INFO_GAIN_B0 ; (unlike below)
029D00h 4x60 BB_CHAN_INFO_CHAN_TAB_B0[0..59] ;/
029CACh 4 BB_CHAN_INFO_NOISE_PWR ;\
029CB0h 4 BB_CHAN_INFO_GAIN_DIFF ; located HERE in
029CB4h 4 BB_CHAN_INFO_FINE_TIMING ; newer revision
029CB8h 4 BB_CHAN_INFO_GAIN_B0 ; (unlike above)
029CBCh 4x60 BB_CHAN_INFO_CHAN_TAB_B0[0..59] ;/
029DACh 1x56 PAD__14 ;(old 1x528 at 9DF0h)
029DE4h 4 BB_PAPRD_AM2AM_MASK ;\
029DE8h 4 BB_PAPRD_AM2PM_MASK ;
029DECh 4 BB_PAPRD_HT40_MASK ;
029DF0h 4 BB_PAPRD_CTRL0 ; exists ONLY in
029DF4h 4 BB_PAPRD_CTRL1 ; newer revision
029DF8h 4 BB_PA_GAIN123 ;
029DFCh 4 BB_PA_GAIN45 ;
029E00h 4x8 BB_PAPRD_PRE_POST_SCALE_(0..7) ;
029E20h 4x120 BB_PAPRD_MEM_TAB[....] ;/
"BASEBAND_1"
02A000h 4 BB_PEAK_DET_CTRL_1
02A004h 4 BB_PEAK_DET_CTRL_2
02A008h 4 BB_RX_GAIN_BOUNDS_1
02A00Ch 4 BB_RX_GAIN_BOUNDS_2
02A010h 4 BB_PEAK_DET_CAL_CTRL
02A014h 4 BB_AGC_DIG_DC_CTRL
02A018h 4 BB_AGC_DIG_DC_STATUS_I_B0
02A01Ch 4 BB_AGC_DIG_DC_STATUS_Q_B0
02A020h 1x468 PAD__15
02A1F4h 4 BB_BBB_TXFIR_0
02A1F8h 4 BB_BBB_TXFIR_1
02A1FCh 4 BB_BBB_TXFIR_2
02A200h 4 BB_MODES_SELECT
02A204h 4 BB_BBB_TX_CTRL
02A208h 4 BB_BBB_SIG_DETECT
02A20Ch 4 BB_EXT_ATTEN_SWITCH_CTL_B0
02A210h 4 BB_BBB_RX_CTRL_1
02A214h 4 BB_BBB_RX_CTRL_2
02A218h 4 BB_BBB_RX_CTRL_3
02A21Ch 4 BB_BBB_RX_CTRL_4
02A220h 4 BB_BBB_RX_CTRL_5
02A224h 4 BB_BBB_RX_CTRL_6
02A228h 4 BB_BBB_DAGC_CTRL
02A22Ch 4 BB_FORCE_CLKEN_CCK
02A230h 4 BB_RX_CLEAR_DELAY
02A234h 4 BB_POWERTX_RATE3 ;Power TX 1L,2L,2S
02A238h 4 BB_POWERTX_RATE4 ;Power TX 55L,55S,11L,11S
02A23Ch 1x4 PAD__16
02A240h 4 BB_CCK_SPUR_MIT
02A244h 4 BB_PANIC_WATCHDOG_STATUS
02A248h 4 BB_PANIC_WATCHDOG_CTRL_1
02A24Ch 4 BB_PANIC_WATCHDOG_CTRL_2
02A250h 4 BB_IQCORR_CTRL_CCK ;with extra bit in newer revision
02A254h 4 BB_BLUETOOTH_CNTL
02A258h 4 BB_TPC_1
02A25Ch 4 BB_TPC_2
02A260h 4 BB_TPC_3
02A264h 4 BB_TPC_4_B0
02A268h 4 BB_ANALOG_SWAP
02A26Ch 4 BB_TPC_5_B0
02A270h 4 BB_TPC_6_B0
02A274h 4 BB_TPC_7
02A278h 4 BB_TPC_8
02A27Ch 4 BB_TPC_9
02A280h 4x32 BB_PDADC_TAB_B0[0..31]
02A300h 4x16 BB_CL_TAB_B0[0..15]
02A340h 4 BB_CL_MAP_0_B0
02A344h 4 BB_CL_MAP_1_B0
02A348h 4 BB_CL_MAP_2_B0
02A34Ch 4 BB_CL_MAP_3_B0
02A350h 1x8 PAD__17
02A358h 4 BB_CL_CAL_CTRL
02A35Ch 4 BB_CL_MAP_PAL_0_B0 ;\
02A360h 4 BB_CL_MAP_PAL_1_B0 ; exists ONLY in
02A364h 4 BB_CL_MAP_PAL_2_B0 ; newer revision
02A368h 4 BB_CL_MAP_PAL_3_B0 ;/
02A36Ch 1x28 PAD__18 ;(old 1x44 at A35Ch)
02A388h 4 BB_RIFS
02A38Ch 4 BB_POWERTX_RATE5 ;Power TX HT20_0..3
02A390h 4 BB_POWERTX_RATE6 ;Power TX HT20_4..7
02A394h 4 BB_TPC_10
02A398h 4 BB_TPC_11_B0
02A39Ch 4 BB_CAL_CHAIN_MASK
02A3A0h 1x28 PAD__19
02A3BCh 4 BB_POWERTX_SUB ;Power TX Sub_for_2chain
02A3C0h 4 BB_POWERTX_RATE7 ;Power TX HT40_0..3
02A3C4h 4 BB_POWERTX_RATE8 ;Power TX HT40_4..7
02A3C8h 4 BB_POWERTX_RATE9 ;Power TX DUP40/EXT20_CCK/OFDM
02A3CCh 4 BB_POWERTX_RATE10 ;Power TX HT20_8..11
02A3D0h 4 BB_POWERTX_RATE11 ;Power TX HT20/40_12/13
02A3D4h 4 BB_POWERTX_RATE12 ;Power TX HT40_8..11
02A3D8h 4 BB_FORCE_ANALOG
02A3DCh 4 BB_TPC_12
02A3E0h 4 BB_TPC_13
02A3E4h 4 BB_TPC_14
02A3E8h 4 BB_TPC_15
02A3ECh 4 BB_TPC_16
02A3F0h 4 BB_TPC_17
02A3F4h 4 BB_TPC_18
02A3F8h 4 BB_TPC_19
02A3FCh 4 BB_TPC_20
02A400h 4x32 BB_TX_GAIN_TAB_(1..32)
02A480h 4x32 BB_TX_GAIN_TAB_PAL_(1..32)
02A500h 1x24 PAD__20
02A518h 4x16 BB_CALTX_GAIN_SET_(0,2,4,6,..,28,30)
02A558h 4x96 BB_TXIQCAL_MEAS_B0[0..95]
02A6D8h 4 BB_TXIQCAL_START
02A6DCh 4 BB_TXIQCAL_CONTROL_0
02A6E0h 4 BB_TXIQCAL_CONTROL_1
02A6E4h 4 BB_TXIQCAL_CONTROL_2
02A6E8h 4 BB_TXIQCAL_CONTROL_3
02A6ECh 4 BB_TXIQ_CORR_COEFF_01_B0
02A6F0h 4 BB_TXIQ_CORR_COEFF_23_B0
02A6F4h 4 BB_TXIQ_CORR_COEFF_45_B0
02A6F8h 4 BB_TXIQ_CORR_COEFF_67_B0
02A6FCh 4 BB_TXIQ_CORR_COEFF_89_B0
02A700h 4 BB_TXIQ_CORR_COEFF_AB_B0
02A704h 4 BB_TXIQ_CORR_COEFF_CD_B0
02A708h 4 BB_TXIQ_CORR_COEFF_EF_B0
02A70Ch 4 BB_CAL_RXBB_GAIN_TBL_0
02A710h 4 BB_CAL_RXBB_GAIN_TBL_4
02A714h 4 BB_CAL_RXBB_GAIN_TBL_8
02A718h 4 BB_CAL_RXBB_GAIN_TBL_12
02A71Ch 4 BB_CAL_RXBB_GAIN_TBL_16
02A720h 4 BB_CAL_RXBB_GAIN_TBL_20
02A724h 4 BB_CAL_RXBB_GAIN_TBL_24
02A728h 4 BB_TXIQCAL_STATUS_B0
02A72Ch 4 BB_PAPRD_TRAINER_CNTL1 ;\
02A730h 4 BB_PAPRD_TRAINER_CNTL2 ;
02A734h 4 BB_PAPRD_TRAINER_CNTL3 ; exists ONLY in
02A738h 4 BB_PAPRD_TRAINER_CNTL4 ; newer revision
02A73Ch 4 BB_PAPRD_TRAINER_STAT1 ;
02A740h 4 BB_PAPRD_TRAINER_STAT2 ;
02A744h 4 BB_PAPRD_TRAINER_STAT3 ;/
02A748h 1x144 PAD__21 ;(old 1x172 at A72Ch)
02A7D8h 4 BB_FCAL_1
02A7DCh 4 BB_FCAL_2_B0
02A7E0h 4 BB_RADAR_BW_FILTER
02A7E4h 4 BB_DFT_TONE_CTRL_B0
02A7E8h 4 BB_THERM_ADC_1
02A7ECh 4 BB_THERM_ADC_2
02A7F0h 4 BB_THERM_ADC_3
02A7F4h 4 BB_THERM_ADC_4
02A7F8h 4 BB_TX_FORCED_GAIN
02A7FCh 4 BB_ECO_CTRL
02A800h 1x72 PAD__22
02A848h 4 BB_GAIN_FORCE_MAX_GAINS_B1
02A84Ch 4 BB_GAINS_MIN_OFFSETS_B1
02A850h 1x432 PAD__23
02AA00h 4x128 BB_RX_OCGAIN2[0..127]
02AC00h 1x1548 PAD__24
02B20Ch 4 BB_EXT_ATTEN_SWITCH_CTL_B1
02B210h - unused/unspecified
rdma_reg.h (hw4.0)
030100h 4 DMA_CONFIG
030104h 4 DMA_CONTROL
030108h 4 DMA_SRC
03010Ch 4 DMA_DEST
030110h 4 DMA_LENGTH
030114h 4 VMC_BASE
030118h 4 INDIRECT_REG
03011Ch 4 INDIRECT_RETURN
030120h 4x16 RDMA_REGION_(0..15)_
030160h 4 DMA_STATUS
030164h 4 DMA_INT_EN
030168h - unused/unspecified
efuse_reg.h (hw4.0)
031000h 4 EFUSE_WR_ENABLE_REG
031004h 4 EFUSE_INT_ENABLE_REG
031008h 4 EFUSE_INT_STATUS_REG
03100Ch 4 BITMASK_WR_REG
031010h 4 VDDQ_SETTLE_TIME_REG
031014h 4 RD_STROBE_PW_REG
031018h 4 PG_STROBE_PW_REG
03101Ch 1x2020 PAD0
031800h 4x512 EFUSE_INTF[0..511]
032000h - unused/unspecified
rtc_soc_reg.h (hw6.0)
004000h 4 SOC_RESET_CONTROL
004004h 4 SOC_TCXO_DETECT
004008h 4 SOC_XTAL_TEST
00400Ch 1x20 PAD0
004020h 4 SOC_CPU_CLOCK
004024h 1x4 PAD1
004028h 4 SOC_CLOCK_CONTROL
00402Ch 1x4 PAD2
004030h 4 SOC_WDT_CONTROL ;\
004034h 4 SOC_WDT_STATUS ;
004038h 4 SOC_WDT ; Watchdog Timer
00403Ch 4 SOC_WDT_COUNT ;
004040h 4 SOC_WDT_RESET ;/
004044h 4 SOC_INT_STATUS ;-Interrupt Status
004048h 4 SOC_LF_TIMER0 ;\
00404Ch 4 SOC_LF_TIMER_COUNT0 ; Low-Freq Timer
004050h 4 SOC_LF_TIMER_CONTROL0 ;
004054h 4 SOC_LF_TIMER_STATUS0 ;/
004058h 4 SOC_LF_TIMER1 ;\
00405Ch 4 SOC_LF_TIMER_COUNT1 ; Low-Freq Timer
004060h 4 SOC_LF_TIMER_CONTROL1 ;
004064h 4 SOC_LF_TIMER_STATUS1 ;/
004068h 4 SOC_LF_TIMER2 ;\
00406Ch 4 SOC_LF_TIMER_COUNT2 ; Low-Freq Timer
004070h 4 SOC_LF_TIMER_CONTROL2 ;
004074h 4 SOC_LF_TIMER_STATUS2 ;/
004078h 4 SOC_LF_TIMER3 ;\
00407Ch 4 SOC_LF_TIMER_COUNT3 ; Low-Freq Timer
004080h 4 SOC_LF_TIMER_CONTROL3 ;
004084h 4 SOC_LF_TIMER_STATUS3 ;/
004088h 4 SOC_HF_TIMER ;\
00408Ch 4 SOC_HF_TIMER_COUNT ; High-Freq Timer
004090h 4 SOC_HF_LF_COUNT ;<-- ;
004094h 4 SOC_HF_TIMER_CONTROL ;
004098h 4 SOC_HF_TIMER_STATUS ;/
00409Ch 4 SOC_RTC_CONTROL ;\
0040A0h 4 SOC_RTC_TIME ;
0040A4h 4 SOC_RTC_DATE ;
0040A8h 4 SOC_RTC_SET_TIME ; Real-Time Clock
0040ACh 4 SOC_RTC_SET_DATE ;
0040B0h 4 SOC_RTC_SET_ALARM ;
0040B4h 4 SOC_RTC_CONFIG ;
0040B8h 4 SOC_RTC_ALARM_STATUS ;/
0040BCh 4 SOC_UART_WAKEUP
0040C0h 4 SOC_RESET_CAUSE
0040C4h 4 SOC_SYSTEM_SLEEP
0040C8h 4 SOC_SDIO_WRAPPER
0040CCh 4 SOC_INT_STATUS1
0040D0h 1x4 PAD3
0040D4h 4 SOC_LPO_CAL_TIME ;\
0040D8h 4 SOC_LPO_INIT_DIVIDEND_INT ;
0040DCh 4 SOC_LPO_INIT_DIVIDEND_FRACTION ; LPO
0040E0h 4 SOC_LPO_CAL ;
0040E4h 4 SOC_LPO_CAL_TEST_CONTROL ;
0040E8h 4 SOC_LPO_CAL_TEST_STATUS ;/
0040ECh 4 LEGACY_SOC_CHIP_ID ;\Chip ID
0040F0h 4 SOC_CHIP_ID ;/
0040F4h 1x24 PAD4
00410Ch 4 SOC_POWER_REG
004110h 4 SOC_CORE_CLK_CTRL
004114h 4 SOC_GPIO_WAKEUP_CONTROL
004118h 1x252 PAD5
004214h 4 SLEEP_RETENTION
004218h 1x108 PAD6
004284h 4 LP_PERF_COUNTER ;\
004288h 4 LP_PERF_LIGHT_SLEEP ; Perf
00428Ch 4 LP_PERF_DEEP_SLEEP ;
004290h 4 LP_PERF_ON ;/
004294h 1x20 PAD7
0042A8h 4 CHIP_MODE
0042ACh 4 CLK_REQ_FALL_EDGE
0042B0h 4 OTP ;\OTP
0042B4h 4 OTP_STATUS ;/
0042B8h 4 PMU
0042BCh 4 PMU_CONFIG
0042C0h 4 PMU_PAREG
0042C4h 4 PMU_BYPASS
0042C8h 1x20 PAD8
0042DCh 4 THERM_CTRL1 ;\
0042E0h 4 THERM_CTRL2 ; Therm
0042E4h 4 THERM_CTRL3 ;/
0042E8h 4 LISTEN_MODE1
0042ECh 4 LISTEN_MODE2
0042F0h 4 AUDIO_PLL_CONFIG
0042F4h 4 AUDIO_PLL_MODULATION
0042F8h 4 AUDIO_PLL_MOD_STEP
0042FCh 4 CURRENT_AUDIO_PLL_MODULATION
004300h 4 ETH_PLL_CONFIG
004304h 4 CPU_PLL_CONFIG
004308h 4 BB_PLL_CONFIG
00430Ch 4 ETH_XMII
004310h 4 USB_PHY_CONFIG
004314h 4 MITSUMI_INT_CONTROL_REG
004318h 4 MITSUMI_INT_STATUS_REG
00431Ch 4 CURRENT_WORKING_MODE
004320h 4 RTC_SLEEP_COUNT
004324h 4 MIT2_VAP
004328h 4 SECOND_HOST_INFT
00432Ch 4 SDIO_HOST
004330h 4 ENTERPRISE_CONFIG
004334h 4 RTC_DEBUG_BUS
004338h 4 RTC_EXT_CLK_BUF
rtc_sync_reg.h (hw6.0)
000000h 1x576 PAD__0
000240h 4 RTC_SYNC_RESET
000244h 4 RTC_SYNC_STATUS
000248h 4 RTC_SYNC_DERIVED
00024Ch 4 RTC_SYNC_FORCE_WAKE
000250h 4 RTC_SYNC_INTR_CAUSE
000254h 4 RTC_SYNC_INTR_ENABLE
000258h 4 RTC_SYNC_INTR_MASK
00025Ch .. -
rtc_wlan_reg.h (hw6.0)
005000h 4 WLAN_RESET_CONTROL
005004h 4 WLAN_XTAL_CONTROL
005008h 4 WLAN_REG_CONTROL0
00500Ch 4 WLAN_REG_CONTROL1
005010h 4 WLAN_QUADRATURE
005014h 4 WLAN_PLL_CONTROL
005018h 4 WLAN_PLL_SETTLE
00501Ch 4 WLAN_XTAL_SETTLE
005020h 4 WLAN_CLOCK_OUT
005024h 4 WLAN_BIAS_OVERRIDE
005028h 4 WLAN_RESET_CAUSE
00502Ch 4 WLAN_SYSTEM_SLEEP
005030h 4 WLAN_MAC_SLEEP_CONTROL
005034h 4 WLAN_KEEP_AWAKE
005038h 4 WLAN_DERIVED_RTC_CLK
00503Ch 4 MAC_PCU_SLP32_MODE
005040h 4 MAC_PCU_SLP32_WAKE
005044h 4 MAC_PCU_SLP32_INC
005048h 4 MAC_PCU_SLP_MIB1
00504Ch 4 MAC_PCU_SLP_MIB2
005050h 4 MAC_PCU_SLP_MIB3
005054h 4 MAC_PCU_TSF_L32
005058h 4 MAC_PCU_TSF_U32
00505Ch 4 MAC_PCU_WBTIMER_0
005060h 4 MAC_PCU_WBTIMER_1
005064h 4x16 MAC_PCU_GENERIC_TIMERS[0..15]
0050A4h 1x24 PAD__0
0050BCh 4 MAC_PCU_GENERIC_TIMERS_MODE
0050C0h 4 MAC_PCU_SLP1
0050C4h 4 MAC_PCU_SLP2
0050C8h 4 MAC_PCU_SLP3
0050CCh 4 MAC_PCU_SLP4
0050D0h 4 MAC_PCU_RESET_TSF
0050D4h 4 MAC_PCU_TSF2_L32
0050D8h 4 MAC_PCU_TSF2_U32
0050DCh 4x16 MAC_PCU_GENERIC_TIMERS2[0..15]
00511Ch 1x24 PAD__1
005134h 4 MAC_PCU_GENERIC_TIMERS_MODE2
005138h 1x12 PAD__2
005144h 4 MAC_PCU_TSF_THRESHOLD
005148h 4 WLAN_HT
00514Ch 1x4 PAD__3
005150h 4 MAC_PCU_GENERIC_TIMERS_TSF_SEL
005154h 4 MAC_PCU_BMISS_TIMEOUT
005158h 4 MAC_PCU_BMISS2_TIMEOUT
00515Ch 4 RTC_AXI_AHB_BRIDGE
005160h 4 UNIFIED_MAC_REVID
005164h .. -
wlan_coex_reg.h (hw6.0)
006000h 4 MCI_COMMAND0
006004h 4 MCI_COMMAND1
006008h 4 MCI_COMMAND2
00600Ch 4 MCI_RX_CTRL
006010h 4 MCI_TX_CTRL
006014h 4 MCI_MSG_ATTRIBUTES_TABLE
006018h 4 MCI_SCHD_TABLE_0
00601Ch 4 MCI_SCHD_TABLE_1
006020h 4 MCI_GPM_0
006024h 4 MCI_GPM_1
006028h 4 MCI_INTERRUPT_RAW
00602Ch 4 MCI_INTERRUPT_EN
006030h 4 MCI_REMOTE_CPU_INT
006034h 4 MCI_REMOTE_CPU_INT_EN
006038h 4 MCI_INTERRUPT_RX_MSG_RAW
00603Ch 4 MCI_INTERRUPT_RX_MSG_EN
006040h 4 MCI_CPU_INT
006044h 4 MCI_RX_STATUS
006048h 4 MCI_CONT_STATUS
00604Ch 4 MCI_BT_PRI0
006050h 4 MCI_BT_PRI1
006054h 4 MCI_BT_PRI2
006058h 4 MCI_BT_PRI3
00605Ch 4 MCI_BT_PRI
006060h 4 MCI_WL_FREQ0
006064h 4 MCI_WL_FREQ1
006068h 4 MCI_WL_FREQ2
00606Ch 4 MCI_GAIN
006070h 4 MCI_WBTIMER1
006074h 4 MCI_WBTIMER2
006078h 4 MCI_WBTIMER3
00607Ch 4 MCI_WBTIMER4
006080h 4 MCI_MAXGAIN
006084h 1x40 PAD__0
0060ACh 4 BTCOEX_CTRL
0060B0h 1x156 PAD__1
00614Ch 4 BTCOEX_CTRL2
006150h 1x260 PAD__2
006254h 4 BTCOEX_DBG
006258h 4 MCI_LAST_HW_MSG_HDR
00625Ch 4 MCI_LAST_HW_MSG_BDY
006260h 4 MCI_MAXGAIN_RST
006264h .. -
bt_coex_reg.h (hw6.0)
007000h 4 BTCOEXCTRL ;\
007004h 4 WBSYNC_PRIORITY1 ;
007008h 4 WBSYNC_PRIORITY2 ;
00700Ch 4 WBSYNC_PRIORITY3 ;
007010h 4 BTCOEX0 ;SYNC_DUR ;
007014h 4 BTCOEX1 ;CLK_THRES ;
007018h 4 BTCOEX2 ;FRAME_THRES ;
00701Ch 4 BTCOEX3 ;CLK_CNT ; moved from 004218h (hw4)
007020h 4 BTCOEX4 ;FRAME_CNT ; to 007000h (hw6)
007024h 4 BTCOEX5 ;IDLE_CNT ;
007028h 4 BTCOEX6 ;IDLE_RESET_LVL_BITMAP ;
00702Ch 4 LOCK ;
007030h 4 NOLOCK_PRIORITY ;
007034h 4 WBSYNC ;
007038h 4 WBSYNC1 ;
00703Ch 4 WBSYNC2 ;
007040h 4 WBSYNC3 ;
007044h 4 WB_TIMER_TARGET ;
007048h 4 WB_TIMER_SLOP ;
00704Ch 4 BTCOEX_INT_EN ;
007050h 4 BTCOEX_INT_STAT ;
007054h 4 BTPRIORITY_INT_EN ;
007058h 4 BTPRIORITY_INT_STAT ;
00705Ch 4 BTPRIORITY_STOMP_INT_EN ;
007060h 4 BTPRIORITY_STOMP_INT_STAT ;/
007064h 4 ST_64_BIT ;\
007068h 4 MESSAGE_WR ; moved from 004294h (hw4)
00706Ch 4 MESSAGE_WR_P ; to 007064h (hw6)
007070h 4 MESSAGE_RD ;
007074h 4 MESSAGE_RD_P ;/
007078h 4 BTPRIORITY_INT ;\
00707Ch 4 SCO_PARAMS ;
007080h 4 SCO_PRIORITY ;
007084h 4 SCO_SYNC ; new, hw6.0 only
007088h 4 BTCOEX_RAW_STAT ;
00708Ch 4 BTPRIORITY_RAW_STAT ;
007090h 4 BTPRIORITY_STOMP_RAW_STAT ;/
uart_reg.h (hw6.0)
00C000h 4 UART_DATA
00C004h 4 UART_CONTROL
00C008h 4 UART_CLKDIV
00C00Ch 4 UART_INT
00C010h 4 UART_INT_EN
00C014h .. -
00D000h .. ??
umbox_wlan_reg.h (hw6.0)
00E000h 4x2 UMBOX_FIFO[0..1]
00E008h 4 UMBOX_FIFO_STATUS
00E00Ch 4 UMBOX_DMA_POLICY
00E010h 4 UMBOX0_DMA_RX_DESCRIPTOR_BASE
00E014h 4 UMBOX0_DMA_RX_CONTROL
00E018h 4 UMBOX0_DMA_TX_DESCRIPTOR_BASE
00E01Ch 4 UMBOX0_DMA_TX_CONTROL
00E020h 4 UMBOX_FIFO_TIMEOUT
00E024h 4 UMBOX_INT_STATUS
00E028h 4 UMBOX_INT_ENABLE
00E02Ch 4 UMBOX_DEBUG
00E030h 4 UMBOX_FIFO_RESET
00E034h 4 UMBOX_HCI_FRAMER
gpio_athr_wlan_reg.h (hw6.0)
014000h 4 WLAN_GPIO_OUT_LOW ;\
014004h 4 WLAN_GPIO_OUT_W1TS_LOW ;
014008h 4 WLAN_GPIO_OUT_W1TC_LOW ; GPIO Output Data
01400Ch 4 WLAN_GPIO_OUT_HIGH ; (direct, and Write-1-To-Set/Clr)
014010h 4 WLAN_GPIO_OUT_W1TS_HIGH ;
014014h 4 WLAN_GPIO_OUT_W1TC_HIGH ;/
014018h 4 WLAN_GPIO_ENABLE_LOW ;\
01401Ch 4 WLAN_GPIO_ENABLE_W1TS_LOW ;
014020h 4 WLAN_GPIO_ENABLE_W1TC_LOW ; GPIO Output Enable
014024h 4 WLAN_GPIO_ENABLE_HIGH ; (direct, and Set/Clr)
014028h 4 WLAN_GPIO_ENABLE_W1TS_HIGH ;
01402Ch 4 WLAN_GPIO_ENABLE_W1TC_HIGH ;/
014030h 4 WLAN_GPIO_IN_LOW ;\
014034h 4 WLAN_GPIO_STATUS_LOW ;\ ; GPIO Input
014038h 4 WLAN_GPIO_IN_HIGH ; ;/
01403Ch 4 WLAN_GPIO_STATUS_HIGH ;
014040h 4 WLAN_GPIO_STATUS_W1TS_LOW ; GPIO Interrupt Status
014044h 4 WLAN_GPIO_STATUS_W1TC_LOW ; (direct, and Set/Clr)
014048h 4 WLAN_GPIO_STATUS_W1TS_HIGH ;
01404Ch 4 WLAN_GPIO_STATUS_W1TC_HIGH ;/
014050h 4 WLAN_GPIO_PIN0 ;GPIO0 or SDIO_CMD
014054h 4 WLAN_GPIO_PIN1 ;GPIO1 or SDIO_D3
014058h 4 WLAN_GPIO_PIN2 ;GPIO2 or SDIO_D2
01405Ch 4 WLAN_GPIO_PIN3 ;GPIO3 or SDIO_D1
014060h 4 WLAN_GPIO_PIN4 ;GPIO4 or SDIO_D0
014064h 4 WLAN_GPIO_PIN5 ;GPIO5 or SDIO_CLK
014068h 4 WLAN_GPIO_PIN6 ;GPIO6
01406Ch 4 WLAN_GPIO_PIN7 ;GPIO7
014070h 4 WLAN_GPIO_PIN8 ;...
014074h 4 WLAN_GPIO_PIN9 ;..
014078h 4 WLAN_GPIO_PIN10
01407Ch 4 WLAN_GPIO_PIN11
014080h 4 WLAN_GPIO_PIN12
014084h 4 WLAN_GPIO_PIN13
014088h 4 WLAN_GPIO_PIN14
01408Ch 4 WLAN_GPIO_PIN15
014090h 4 WLAN_GPIO_PIN16
014094h 4 WLAN_GPIO_PIN17
014098h 4 WLAN_GPIO_PIN18
01409Ch 4 WLAN_GPIO_PIN19
0140A0h 4 WLAN_GPIO_PIN20
0140A4h 4 WLAN_GPIO_PIN21
0140A8h 4 WLAN_GPIO_PIN22
0140ACh 4 WLAN_GPIO_PIN23
0140B0h 4 WLAN_GPIO_PIN24
0140B4h 4 WLAN_GPIO_PIN25
0140B8h 4 WLAN_GPIO_PIN26
0140BCh 4 WLAN_GPIO_PIN27
0140C0h 4 WLAN_GPIO_PIN28
0140C4h 4 WLAN_GPIO_PIN29
0140C8h 4 WLAN_GPIO_PIN30
0140CCh 4 WLAN_GPIO_PIN31
0140D0h 4 WLAN_GPIO_PIN32
0140D4h 4 WLAN_GPIO_PIN33
0140D8h 4 WLAN_GPIO_PIN34
0140DCh 4 WLAN_GPIO_PIN35
0140E0h 4 WLAN_GPIO_PIN36
0140E4h 4 WLAN_GPIO_PIN37
0140E8h 4 WLAN_GPIO_PIN38
0140ECh 4 WLAN_GPIO_PIN39
0140F0h 4 WLAN_GPIO_PIN40
0140F4h 4 WLAN_GPIO_PIN41
0140F8h 4 WLAN_GPIO_PIN42
0140FCh 4 WLAN_GPIO_PIN43
014100h 4 WLAN_GPIO_PIN44
014104h 4 WLAN_GPIO_PIN45
014108h 4 WLAN_GPIO_PIN46
01410Ch 4 WLAN_GPIO_PIN47
014110h 4 WLAN_GPIO_PIN48
014114h 4 WLAN_GPIO_PIN49
014118h 4 WLAN_GPIO_PIN50
01411Ch 4 WLAN_GPIO_PIN51
014120h 4 WLAN_GPIO_PIN52
014124h 4 WLAN_GPIO_PIN53
014128h 4 WLAN_GPIO_PIN54
01412Ch 4 WLAN_GPIO_PIN55
014130h 4 WLAN_GPIO_PIN56
014134h 4 SDIO
014138h 4 WL_SOC_APB
01413Ch 4 WLAN_SIGMA_DELTA
014140h 4 WL_BOOTSTRAP
014144h 4 CORE_BOOTSTRAP_LOW
014148h 4 CORE_BOOTSTRAP_HIGH
01414Ch 4 WLAN_DEBUG_CONTROL
014150h 4 WLAN_DEBUG_INPUT_SEL
014154h 4 WLAN_DEBUG_OUT
014158h 4 WLAN_RESET_TUPLE_STATUS
01415Ch 4 ANTENNA_CONTROL
014160h 4 SDIO2
014164h 4 SDHC
014168h 4 AMBA_DEBUG_BUS
01416Ch 4 CPU_MBIST
analog_intf_athr_wlan_reg.h (hw6.0)
01C000h 4 RXRF_BIAS1
01C004h 4 RXRF_BIAS2
01C008h 4 RXRF_GAINSTAGES
01C00Ch 4 RXRF_AGC
01C010h 1x48 PAD__0
01C040h 4 TXRF1
01C044h 4 TXRF2
01C048h 4 TXRF3
01C04Ch 4 TXRF4
01C050h 4 TXRF5
01C054h 4 TXRF6
01C058h 4 TXRF7
01C05Ch 4 TXRF8
01C060h 4 TXRF9
01C064h 4 TXRF10
01C068h 4 TXRF11
01C06Ch 4 TXRF12
01C070h 1x16 PAD__1
01C080h 4 SYNTH1
01C084h 4 SYNTH2
01C088h 4 SYNTH3
01C08Ch 4 SYNTH4
01C090h 4 SYNTH5
01C094h 4 SYNTH6
01C098h 4 SYNTH7
01C09Ch 4 SYNTH8
01C0A0h 4 SYNTH9
01C0A4h 4 SYNTH10
01C0A8h 4 SYNTH11
01C0ACh 4 SYNTH12
01C0B0h 4 SYNTH13
01C0B4h 4 SYNTH14
01C0B8h 1x8 PAD__2
01C0C0h 4 BIAS1
01C0C4h 4 BIAS2
01C0C8h 4 BIAS3
01C0CCh 4 BIAS4
01C0D0h 1x48 PAD__3
01C100h 4 RXTX1
01C104h 4 RXTX2
01C108h 4 RXTX3
01C10Ch 1x52 PAD__4
01C140h 4 BB1
01C144h 4 BB2
01C148h 4 BB3
01C14Ch 1x308 PAD__5
01C280h 4 PLLCLKMODA
01C284h 4 PLLCLKMODA2
01C288h 4 TOP
01C28Ch 4 THERM
01C290h 4 XTAL
01C294h 1x236 PAD__6
01C380h 4 RBIST_CNTRL
01C384h 4 TX_DC_OFFSET
01C388h 4 TX_TONEGEN0
01C38Ch 4 TX_TONEGEN1
01C390h 4 TX_LFTONEGEN0
01C394h 4 TX_LINEAR_RAMP_I
01C398h 4 TX_LINEAR_RAMP_Q
01C39Ch 4 TX_PRBS_MAG
01C3A0h 4 TX_PRBS_SEED_I
01C3A4h 4 TX_PRBS_SEED_Q
01C3A8h 4 CMAC_DC_CANCEL
01C3ACh 4 CMAC_DC_OFFSET
01C3B0h 4 CMAC_CORR
01C3B4h 4 CMAC_POWER
01C3B8h 4 CMAC_CROSS_CORR
01C3BCh 4 CMAC_I2Q2
01C3C0h 4 CMAC_POWER_HPF
01C3C4h 4 RXDAC_SET1
01C3C8h 4 RXDAC_SET2
01C3CCh 4 RXDAC_LONG_SHIFT
01C3D0h 4 CMAC_RESULTS_I
01C3D4h 4 CMAC_RESULTS_Q
01C3D8h 1x872 PAD__7
01C740h 4 PMU1
01C744h 4 PMU2
wmac_dma_reg.h (hw6.0)
020000h 1x8 PAD__0
020008h 4 MAC_DMA_CR
020004h 1x4 PAD__1
02000Ch 1x4 PAD__1
020014h 4 MAC_DMA_CFG
020018h 4 MAC_DMA_RXBUFPTR_THRESH
02001Ch 4 MAC_DMA_TXDPPTR_THRESH
020020h 4 MAC_DMA_MIRT
020024h 4 MAC_DMA_GLOBAL_IER
020028h 4 MAC_DMA_TIMT_0
02002Ch 4 MAC_DMA_RIMT
020030h 4 MAC_DMA_TXCFG
020034h 4 MAC_DMA_RXCFG
020038h 4 MAC_DMA_RXJLA
02003Ch 1x4 PAD__2
020040h 4 MAC_DMA_MIBC
020044h 4 MAC_DMA_TOPS
020048h 4 MAC_DMA_RXNPTO
02004Ch 4 MAC_DMA_TXNPTO
020050h 4 MAC_DMA_RPGTO
020054h 1x4 PAD__3
020058h 4 MAC_DMA_MACMISC
02005Ch 4 MAC_DMA_INTER
020060h 4 MAC_DMA_DATABUF
020064h 4 MAC_DMA_GTT
020068h 4 MAC_DMA_GTTM
02006Ch 4 MAC_DMA_CST
020070h 4 MAC_DMA_RXDP_SIZE
020074h 4 MAC_DMA_RX_QUEUE_HP_RXDP
020078h 4 MAC_DMA_RX_QUEUE_LP_RXDP
02007Ch 1x4 PAD__4
020080h 4 MAC_DMA_ISR_P - Primary Interrupt Status Register ;\
020084h 4 MAC_DMA_ISR_S0 - Secondary Interrupt 0 Status TX OK/DESC ;
020088h 4 MAC_DMA_ISR_S1 - Secondary Interrupt 1 Status TX ERR/EOL ;
02008Ch 4 MAC_DMA_ISR_S2 - Secondary Interrupt 2 Status TX URN/MISC ;
020090h 4 MAC_DMA_ISR_S3 - Secondary Interrupt 3 Status QCBR OVF/URN ;
020094h 4 MAC_DMA_ISR_S4 - Secondary Interrupt 4 Status QTRIG ;
020098h 4 MAC_DMA_ISR_S5 - Secondary Interrupt 5 Status TIMERS ;
02009Ch 4 MAC_DMA_ISR_S6 - Secondary Interrupt 6 Status UNKNOWN? ;/
0200A0h 4 MAC_DMA_IMR_P - Primary Interrupt Mask Register ;\
0200A4h 4 MAC_DMA_IMR_S0 - Secondary Interrupt 0 Mask TX OK/DESC ;
0200A8h 4 MAC_DMA_IMR_S1 - Secondary Interrupt 1 Mask TX ERR/EOL ;
0200ACh 4 MAC_DMA_IMR_S2 - Secondary Interrupt 2 Mask TX URN/MISC ;
0200B0h 4 MAC_DMA_IMR_S3 - Secondary Interrupt 3 Mask QCBR OVF/URN ;
0200B4h 4 MAC_DMA_IMR_S4 - Secondary Interrupt 4 Mask QTRIG ;
0200B8h 4 MAC_DMA_IMR_S5 - Secondary Interrupt 5 Mask TIMERS ;
0200BCh 4 MAC_DMA_IMR_S6 - Secondary Interrupt 6 Mask UNKNOWN? ;/
0200C0h 4 MAC_DMA_ISR_P_RAC - Primary Interrupt Read-and-Clear ;\
0200C4h 4 MAC_DMA_ISR_S0_S - Secondary 0 Read-and-Clr TX OK/DESC ;
0200C8h 4 MAC_DMA_ISR_S1_S - Secondary 1 Read-and-Clr TX ERR/EOL ;
0200CCh 4 MAC_DMA_ISR_S6_S - Secondary 6? Read-and-Clr UNKNOWN? <-- ;
0200D0h 4 MAC_DMA_ISR_S2_S - Secondary 2? Read-and-Clr TX URN/MISC ;
0200D4h 4 MAC_DMA_ISR_S3_S - Secondary 3? Read-and-Clr QCBR OVF/URN ;
0200D8h 4 MAC_DMA_ISR_S4_S - Secondary 4? Read-and-Clr QTRIG ;
0200DCh 4 MAC_DMA_ISR_S5_S - Secondary 5? Read-and-Clr TIMERS ;/
0200E0h 4 MAC_DMA_DMADBG_0
0200E4h 4 MAC_DMA_DMADBG_1
0200E8h 4 MAC_DMA_DMADBG_2
0200ECh 4 MAC_DMA_DMADBG_3
0200F0h 4 MAC_DMA_DMADBG_4
0200F4h 4 MAC_DMA_DMADBG_5
0200F8h 4 MAC_DMA_DMADBG_6
0200FCh 4 MAC_DMA_DMADBG_7
020100h 4 MAC_DMA_QCU_TXDP_REMAINING_QCU_7_0
020104h 4 MAC_DMA_QCU_TXDP_REMAINING_QCU_9_8
020108h 4 MAC_DMA_TIMT_1 ;note: "MAC_DMA_TIMT_0" is at 020028h
02010Ch 4 MAC_DMA_TIMT_2
020110h 4 MAC_DMA_TIMT_3
020114h 4 MAC_DMA_TIMT_4
020118h 4 MAC_DMA_TIMT_5
02011Ch 4 MAC_DMA_TIMT_6
020120h 4 MAC_DMA_TIMT_7
020124h 4 MAC_DMA_TIMT_8
020128h 4 MAC_DMA_TIMT_9
02012Ch 4 MAC_DMA_CHKACC
wmac_qcu_reg.h (hw6.0)
020800h 4x10 MAC_QCU_TXDP[0..9]
020828h 1x8 PAD__1
020830h 4 MAC_QCU_STATUS_RING_START
020834h 4 MAC_QCU_STATUS_RING_END
020838h 4 MAC_QCU_STATUS_RING_CURRENT
02083Ch 1x4 PAD__2
020840h 4 MAC_QCU_TXE
020844h 1x60 PAD__3
020880h 4 MAC_QCU_TXD
020884h 1x60 PAD__4
0208C0h 4x10 MAC_QCU_CBR[0..9]
0208E8h 1x24 PAD__5
020900h 4x10 MAC_QCU_RDYTIME[0..9]
020928h 1x24 PAD__6
020940h 4 MAC_QCU_ONESHOT_ARM_SC
020944h 1x60 PAD__7
020980h 4 MAC_QCU_ONESHOT_ARM_CC
020984h 1x60 PAD__8
0209C0h 4x10 MAC_QCU_MISC[0..9]
0209E8h 1x24 PAD__9
020A00h 4x10 MAC_QCU_CNT[0..9]
020A28h 1x24 PAD__10
020A40h 4 MAC_QCU_RDYTIME_SHDN
020A44h 4 MAC_QCU_DESC_CRC_CHK
020A48h 4 MAC_QCU_EOL
wmac_dcu_reg.h (hw6.0)
021000h 4x10 MAC_DCU_QCUMASK[0..9]
021028h 1x8 PAD__1
021030h 4 MAC_DCU_GBL_IFS_SIFS
021034h 1x4 PAD__2
021038h 4 MAC_DCU_TXFILTER_DCU0_31_0
02103Ch 4 MAC_DCU_TXFILTER_DCU8_31_0
021040h 4x10 MAC_DCU_LCL_IFS[0..9]
021068h 1x8 PAD__3
021070h 4 MAC_DCU_GBL_IFS_SLOT
021074h 1x4 PAD__4
021078h 4 MAC_DCU_TXFILTER_DCU0_63_32
02107Ch 4 MAC_DCU_TXFILTER_DCU8_63_32
021080h 4x10 MAC_DCU_RETRY_LIMIT[0..9]
0210A8h 1x8 PAD__5
0210B0h 4 MAC_DCU_GBL_IFS_EIFS
0210B4h 1x4 PAD__6
0210B8h 4 MAC_DCU_TXFILTER_DCU0_95_64
0210BCh 4 MAC_DCU_TXFILTER_DCU8_95_64
0210C0h 4x10 MAC_DCU_CHANNEL_TIME[0..9]
0210E8h 1x8 PAD__7
0210F0h 4 MAC_DCU_GBL_IFS_MISC
0210F4h 1x4 PAD__8
0210F8h 4 MAC_DCU_TXFILTER_DCU0_127_96
0210FCh 4 MAC_DCU_TXFILTER_DCU8_127_96
021100h 4x10 MAC_DCU_MISC[0..9]
021128h 1x16 PAD__9
021138h 4 MAC_DCU_TXFILTER_DCU1_31_0
02113Ch 4 MAC_DCU_TXFILTER_DCU9_31_0
021140h 4 MAC_DCU_SEQ
021144h 1x52 PAD__10
021178h 4 MAC_DCU_TXFILTER_DCU1_63_32
02117Ch 4 MAC_DCU_TXFILTER_DCU9_63_32
021180h 1x56 PAD__11
0211B8h 4 MAC_DCU_TXFILTER_DCU1_95_64
0211BCh 4 MAC_DCU_TXFILTER_DCU9_95_64
0211C0h 1x56 PAD__12
0211F8h 4 MAC_DCU_TXFILTER_DCU1_127_96
0211FCh 4 MAC_DCU_TXFILTER_DCU9_127_96
021200h 1x56 PAD__13
021238h 4 MAC_DCU_TXFILTER_DCU2_31_0
02123Ch 1x52 PAD__14
021270h 4 MAC_DCU_PAUSE
021274h 1x4 PAD__15
021278h 4 MAC_DCU_TXFILTER_DCU2_63_32
02127Ch 1x52 PAD__16
0212B0h 4 MAC_DCU_WOW_KACFG
0212B4h 1x4 PAD__17
0212B8h 4 MAC_DCU_TXFILTER_DCU2_95_64
0212BCh 1x52 PAD__18
0212F0h 4 MAC_DCU_TXSLOT
0212F4h 1x4 PAD__19
0212F8h 4 MAC_DCU_TXFILTER_DCU2_127_96
0212FCh 1x60 PAD__20
021338h 4 MAC_DCU_TXFILTER_DCU3_31_0 ;\
02133Ch 1x60 PAD__21 ;
021378h 4 MAC_DCU_TXFILTER_DCU3_63_32 ;
02137Ch 1x60 PAD__22 ;
0213B8h 4 MAC_DCU_TXFILTER_DCU3_95_64 ;
0213BCh 1x60 PAD__23 ;
0213F8h 4 MAC_DCU_TXFILTER_DCU3_127_96 ;/
0213FCh 1x60 PAD__24
021438h 4 MAC_DCU_TXFILTER_DCU4_31_0
02143Ch 4 MAC_DCU_TXFILTER_CLEAR
021440h 1x56 PAD__25
021478h 4 MAC_DCU_TXFILTER_DCU4_63_32
02147Ch 4 MAC_DCU_TXFILTER_SET
021480h 1x56 PAD__26
0214B8h 4 MAC_DCU_TXFILTER_DCU4_95_64
0214BCh 1x60 PAD__27
0214F8h 4 MAC_DCU_TXFILTER_DCU4_127_96
0214FCh 1x60 PAD__28
021538h 4 MAC_DCU_TXFILTER_DCU5_31_0 ;\
02153Ch 1x60 PAD__29 ;
021578h 4 MAC_DCU_TXFILTER_DCU5_63_32 ;
02157Ch 1x60 PAD__30 ;
0215B8h 4 MAC_DCU_TXFILTER_DCU5_95_64 ;
0215BCh 1x60 PAD__31 ;
0215F8h 4 MAC_DCU_TXFILTER_DCU5_127_96 ;/
0215FCh 1x60 PAD__32
021638h 4 MAC_DCU_TXFILTER_DCU6_31_0 ;\
02163Ch 1x60 PAD__33 ;
021678h 4 MAC_DCU_TXFILTER_DCU6_63_32 ;
02167Ch 1x60 PAD__34 ;
0216B8h 4 MAC_DCU_TXFILTER_DCU6_95_64 ;
0216BCh 1x60 PAD__35 ;
0216F8h 4 MAC_DCU_TXFILTER_DCU6_127_96 ;/
0216FCh 1x60 PAD__36
021738h 4 MAC_DCU_TXFILTER_DCU7_31_0 ;\
02173Ch 1x60 PAD__37 ;
021778h 4 MAC_DCU_TXFILTER_DCU7_63_32 ;
02177Ch 1x60 PAD__38 ;
0217B8h 4 MAC_DCU_TXFILTER_DCU7_95_64 ;
0217BCh 1x60 PAD__39 ;
0217F8h 4 MAC_DCU_TXFILTER_DCU7_127_96 ;/
efuse_wlan_reg.h (hw6.0)
030000h 4 EFUSE_WR_ENABLE_REG
030004h 4 EFUSE_INT_ENABLE_REG
030008h 4 EFUSE_INT_STATUS_REG
03000Ch 4 BITMASK_WR_REG
030010h 4 VDDQ_SETTLE_TIME_REG
030014h 4 VDDQ_HOLD_TIME_REG
030018h 4 RD_STROBE_PW_REG
03001Ch 4 PG_STROBE_PW_REG
030020h 4 PGENB_SETUP_HOLD_TIME_REG
030024h 4 STROBE_PULSE_INTERVAL_REG
030028h 4 CSB_ADDR_LOAD_SETUP_HOLD_REG
03002Ch 1x2004 PAD0
030800h 4x512 EFUSE_INTF0[0..511]
031000h 4x512 EFUSE_INTF1[0..511]
stereo_reg.h (hw6.0)
034000h 4 STEREO0_CONFIG ;\Stereo 0
034004h 4 STEREO0_VOLUME ;/
034008h 4 STEREO_MASTER_CLOCK ;-Stereo Master
03400Ch 4 STEREO0_TX_SAMPLE_CNT_LSB ;\
034010h 4 STEREO0_TX_SAMPLE_CNT_MSB ; Stereo 0
034014h 4 STEREO0_RX_SAMPLE_CNT_LSB ;
034018h 4 STEREO0_RX_SAMPLE_CNT_MSB ;/
chk_sum_seg_acc_reg.h (hw6.0)
035000h 4 CHKSUM_ACC_DMATX_CONTROL0
035004h 4 CHKSUM_ACC_DMATX_CONTROL1
035008h 4 CHKSUM_ACC_DMATX_CONTROL2
03500Ch 4 CHKSUM_ACC_DMATX_CONTROL3
035010h 4 CHKSUM_ACC_DMATX_DESC0
035014h 4 CHKSUM_ACC_DMATX_DESC1
035018h 4 CHKSUM_ACC_DMATX_DESC2
03501Ch 4 CHKSUM_ACC_DMATX_DESC3
035020h 4 CHKSUM_ACC_DMATX_DESC_STATUS
035024h 4 CHKSUM_ACC_DMATX_ARB_CFG
035028h 4 CHKSUM_ACC_RR_PKTCNT01
03502Ch 4 CHKSUM_ACC_RR_PKTCNT23
035030h 4 CHKSUM_ACC_TXST_PKTCNT
035034h 4 CHKSUM_ACC_DMARX_CONTROL
035038h 4 CHKSUM_ACC_DMARX_DESC
03503Ch 4 CHKSUM_ACC_DMARX_DESC_STATUS
035040h 4 CHKSUM_ACC_INTR
035044h 4 CHKSUM_ACC_IMASK
035048h 4 CHKSUM_ACC_ARB_BURST
03504Ch 1x4 PAD__0
035050h 4 CHKSUM_ACC_RESET_DMA
035054h 4 CHKSUM_CONFIG
mmac_reg.h (hw6.0)
038000h 4 RX_FRAME0
038004h 4 RX_FRAME_0
038008h 4 RX_FRAME1
03800Ch 4 RX_FRAME_1
038010h 4 MMAC_INTERRUPT_RAW
038014h 4 MMAC_INTERRUPT_EN
038018h 4 RX_PARAM1
03801Ch 4 RX_PARAM0
038020h 4 TX_COMMAND0
038024h 4 TX_COMMAND
038028h 4 TX_PARAM
03802Ch 4 BEACON_PARAM
038030h 4 BEACON
038034h 4 TSF_L
038038h 4 TSF_U
fpga_reg.h (hw6.0)
039000h 4 FPGA_REG1
039004h 4 FPGA_REG2
039008h 4 FPGA_REG4
bridge_intr_reg.h (hw6.0)
040000h 4 INTERRUPT
040004h 4 INTERRUPT_MASK
mii_reg.h (hw6.0)
040100h 4 MII0_CNTL
040104h 4 STAT_CNTL
mdio_reg.h (hw6.0)
040200h 4x8 MDIO_REG[0..7]
040220h 4 MDIO_ISR
040224h 4 PHY_ADDR
bridge_chain_gmac_0_rx_reg.h (hw6.0)
040800h 4 GMAC_RX_0_DESC_START_ADDRESS
040804h 4 GMAC_RX_0_DMA_START
040808h 4 GMAC_RX_0_BURST_SIZE
04080Ch 4 GMAC_RX_0_PKT_OFFSET
040810h 4 GMAC_RX_0_CHECKSUM
040814h 4 GMAC_RX_0_DBG_RX
040818h 4 GMAC_RX_0_DBG_RX_CUR_ADDR
04081Ch 4 GMAC_RX_0_DATA_SWAP
bridge_chain_gmac_0_tx_reg.h (hw6.0)
040C00h 4 GMAC_TX_0_DESC_START_ADDRESS
040C04h 4 GMAC_TX_0_DMA_START
040C08h 4 GMAC_TX_0_INTERRUPT_LIMIT
040C0Ch 4 GMAC_TX_0_BURST_SIZE
040C10h 4 GMAC_TX_0_DBG_TX
040C14h 4 GMAC_TX_0_DBG_TX_CUR_ADDR
040C18h 4 GMAC_TX_0_DATA_SWAP
usb_cast_reg.h (hw6.0)
054000h 4 ENDP0
054004h 1x4 PAD0
054008h 4 OUT1ENDP
05400Ch 4 IN1ENDP
054010h 4 OUT2ENDP
054014h 4 IN2ENDP
054018h 4 OUT3ENDP
05401Ch 4 IN3ENDP
054020h 4 OUT4ENDP
054024h 4 IN4ENDP
054028h 4 OUT5ENDP
05402Ch 4 IN5ENDP
054030h 1x92 PAD1
05408Ch 4 USBMODESTATUS
054090h 1x248 PAD2
054188h 4 EPIRQ
05418Ch 4 USBIRQ
054190h 1x4 PAD3
054194h 4 EPIEN
054198h 4 PIEN
05419Ch 1x8 PAD4
0541A4h 4 FNCTRL
0541A8h 1x20 PAD5
0541BCh 4 OTGREG
0541C0h 1x12 PAD6
0541CCh 4 DMASTART
0541D0h 4 DMASTOP
0541D4h 1x556 PAD7
054400h 4 EP0DMAADDR
054404h 1x28 PAD8
054420h 4 EP1DMAADDR
054424h 1x8 PAD9
05442Ch 4 OUT1DMACTRL
054430h 1x16 PAD10
054440h 4 EP2DMAADDR
054444h 1x8 PAD11
05444Ch 4 OUT2DMACTRL
054450h 1x16 PAD12
054460h 4 EP3DMAADDR
054464h 1x8 PAD13
05446Ch 4 OUT3DMACTRL
054470h 1x16 PAD14
054480h 4 EP4DMAADDR
054484h 1x8 PAD15
05448Ch 4 OUT4DMACTRL
054490h 1x16 PAD16
0544A0h 4 EP5DMAADDR
0544A4h 1x8 PAD17
0544ACh 4 OUT5DMACTRL
0544B0h 1x539472 PAD18 ;pad to BASE + 84000h
0D8000h 4 USB_IP_BASE
athrI2cSlaveApbCsr.h (hw6.0)
054E00h 4 I2CFIFOCONTROL
054E04h 4 I2CFIFOREADPTR
054E08h 4 I2CFIFOREADUPDATE
054E0Ch 4 I2CFIFOREADBASEADDR
054E10h 4 I2CFIFOWRITEPTR
054E14h 4 I2CFIFOWRITEUPDATE
054E18h 4 I2CFIFOWRITEBASEADDR
054E1Ch 4 I2CMEMCONTROL
054E20h 4 I2CMEMBASEADDR
054E24h 4 I2CREGREADDATA
054E28h 4 I2CREGWRITEDATA
054E2Ch 4 I2CREGCONTROL
054E30h 4 I2CCSRREADDATA
054E34h 4 I2CCSRWRITEDATA
054E38h 4 I2CCSRCONTROL
054E3Ch 4 I2CFILTERSIZE
054E40h 4 I2CADDR
054E44h 4 I2CINT
054E48h 4 I2CINTEN
054E4Ch 4 I2CINTCSR
mbox_i2s_reg.h (hw6.0)
055000h 4x1 MBOX_FIFO ;<-- defined as array of ONE word (?)
055004h 4 MBOX_FIFO_STATUS
055008h 4 MBOX_DMA_POLICY
05500Ch 4 MBOX0_DMA_RX_DESCRIPTOR_BASE
055010h 4 MBOX0_DMA_RX_CONTROL
055014h 4 MBOX0_DMA_TX_DESCRIPTOR_BASE
055018h 4 MBOX0_DMA_TX_CONTROL
05501Ch 4 MBOX_FRAME
055020h 4 FIFO_TIMEOUT
055024h 4 MBOX_INT_STATUS
055028h 4 MBOX_INT_ENABLE
05502Ch 4 MBOX_FIFO_RESET
055030h 4 MBOX_DEBUG_CHAIN0
055034h 4 MBOX_DEBUG_CHAIN1
055038h 4 MBOX_DEBUG_CHAIN0_SIGNALS
05503Ch 4 MBOX_DEBUG_CHAIN1_SIGNALS
map_rf_reg.h (hw6.0)
xxx000h 4x256 RAM1[0..255]
xxx400h 4x12 INT_PENDING[0..11]
xxx430h 4 BB_WR_MASK_0 ;\
xxx434h 4 BB_WR_MASK_1 ; BB Write Mask 0..3
xxx438h 4 BB_WR_MASK_2 ;
xxx43Ch 4 BB_WR_MASK_3 ;/
xxx440h 4 RF_WR_MASK_0 ;\RF Write Mask 0..1
xxx444h 4 RF_WR_MASK_1 ;/
xxx448h 4 BB_RD_MASK_0 ;\
xxx44Ch 4 BB_RD_MASK_1 ; BB Read Mask 0..3
xxx450h 4 BB_RD_MASK_2 ;
xxx454h 4 BB_RD_MASK_3 ;/
xxx458h 4 RF_RD_MASK_0 ;\RF Read Mask 0..1
xxx45Ch 4 RF_RD_MASK_1 ;/
xxx460h 4 INT_SRC
xxx464h 1x924 PAD__0
xxx800h 4x128 RAM2[0..127]
odin_reg.h (hw6.0)
xxx000h 4 PHY_CTRL0
xxx004h 4 PHY_CTRL1
xxx008h 4 PHY_CTRL2
xxx00Ch 4 PHY_CTRL3
xxx010h 4 PHY_CTRL4
xxx014h 4 PHY_CTRL5
xxx018h 4 PHY_CTRL6
xxx01Ch 4 PHY_STATUS
DSi Atheros Wifi - Internal I/O - Unknown and Unused Registers (hw2)
--------------------------------------------------------------------
The DSi does have a battery-backed RTC accessed via Port 4000138h on ARM7 side.
Below SOC_RTC would offer a second RTC, but it isn't actually used in DSi (the
SOC_RTC registers aren't battery-backed, and the DSi firmware isn't
initializing them from the ARM7 time either).
ATH:xxx240h - RTC_SYNC_RESET
0 RESET_L
ATH:xxx244h - RTC_SYNC_STATUS
0 SHUTDOWN_STATE (R)
1 ON_STATE (R)
2 SLEEP_STATE (R)
3 WAKEUP_STATE (R)
4 WRESET (R)
5 PLL_CHANGING (R)
ATH:xxx248h - RTC_SYNC_DERIVED
0 BYPASS
1 FORCE
2 FORCE_SWREG_PWD (W)
3 FORCE_LPO_PWD (W)
ATH:xxx24Ch - RTC_SYNC_FORCE_WAKE
0 ENABLE (R)
1 INTR
ATH:xxx250h - RTC_SYNC_INTR_CAUSE
0 SHUTDOWN_STATE
1 ON_STATE
2 SLEEP_STATE
3 WAKEUP_STATE
4 SLEEP_ACCESS
5 PLL_CHANGING
ATH:xxx254h - RTC_SYNC_INTR_ENABLE
0 SHUTDOWN_STATE
1 ON_STATE
2 SLEEP_STATE
3 WAKEUP_STATE
4 SLEEP_ACCESS
5 PLL_CHANGING
ATH:xxx258h - RTC_SYNC_INTR_MASK
0 SHUTDOWN_STATE
1 ON_STATE
2 SLEEP_STATE
3 WAKEUP_STATE
4 SLEEP_ACCESS
5 PLL_CHANGING
DSi Atheros Wifi - Internal I/O - 006000h - WLAN Coex (MCI) (hw6)
-----------------------------------------------------------------
The hw4 ROM patching is done in 32bit Data units, but 16bit/24bit Xtensa
opcodes aren't neccessarily 32bit aligned, so one may need 1-2 patch slots per
opcode.
Unknown if or how ROM Patches are supported on hw6 (the hw6 source code doesn't
define any TCAM/BCAM registers).
The UART_xxx registers are used to output TTY messages (ASCII strings) when
enabled in the "Host Interest" area:
LOCAL_SCRATCH[0].bit1 AR6K_OPTION_SERIAL_ENABLE --> TTY master enable
targaddr[14h] hi_serial_enable --> enable additional TTY msg's during BMI
targaddr[60h] hi_desired_baud_rate --> for TTY/UART (default=9600 decimal)
targaddr[C4h] hi_console_flags - whatever, UART related, maybe newer firmware
ATH:00E000h..00E004h - UMBOX_FIFO[0..1]
0-8 DATA ... uh, twice[0..1], with 9bit each ?
ATH:00E008h - UMBOX_FIFO_STATUS
0 RX_FULL
1 RX_EMPTY
2 TX_FULL
3 TX_EMPTY
ATH:00E00Ch - UMBOX_DMA_POLICY
0 RX_ORDER
1 RX_QUANTUM
2 TX_ORDER
3 TX_QUANTUM
ATH:00E010h - UMBOX0_DMA_RX_DESCRIPTOR_BASE
ATH:00E018h - UMBOX0_DMA_TX_DESCRIPTOR_BASE
2-27 ADDRESS
ATH:00E014h - UMBOX0_DMA_RX_CONTROL
ATH:00E01Ch - UMBOX0_DMA_TX_CONTROL
0 STOP
1 START
2 RESUME
ATH:00E020h - UMBOX_FIFO_TIMEOUT
0-7 VALUE
8 ENABLE_SET
ATH:00E024h - UMBOX_INT_STATUS
ATH:00E028h - UMBOX_INT_ENABLE
0 RX_NOT_FULL
1 TX_NOT_EMPTY
2 RX_UNDERFLOW
3 TX_OVERFLOW
4 HCI_SYNC_ERROR
5 TX_DMA_COMPLETE
6 TX_DMA_EOM_COMPLETE
7 RX_DMA_COMPLETE
8 HCI_FRAMER_OVERFLOW
9 HCI_FRAMER_UNDERFLOW
ATH:00E02Ch - UMBOX_DEBUG
0-2 SEL
ATH:00E030h - UMBOX_FIFO_RESET
0 INIT
ATH:00E034h - UMBOX_HCI_FRAMER
0-1 CONFIG_MODE
2 OVERFLOW
3 UNDERFLOW
4 SYNC_ERROR
5 ENABLE
6 CRC_OVERRIDE
These registers are providing a general purpose I2C/SPI serial bus. The SI_xxx
registers are exactly same in hw2/hw4/hw6.
In the DSi, they are used in I2C mode - for reading wifi calibration data:
--> DSi Atheros Wifi I2C EEPROM
ATH:010000h - SI_CONFIG
0-3 DIVIDER (probably transfer rate, should be 6 on DSi)
4 INACTIVE_CLK (whatever, should be 1 for I2C)
5 INACTIVE_DATA (whatever, should be 1 for I2C)
6 POS_DRIVE (whatever, should be zero for I2C)
7 POS_SAMPLE (whatever, should be 1 for I2C)
8-15 -
16 I2C (0=SPI, 1=I2C)
17 -
18 BIDIR_OD_DATA (whatever, should be 1 for I2C)
19 ERR_INT (whatever, enable or status?)
On DSi, this is register is set to 500B6h.
ATH:010004h - SI_CS
0-3 TX_CNT Number of TX bytes (0..8) (should be 1..8 for I2C device)
4-7 RX_CNT Number of RX bytes (0..8)
8 START Write 1 to start transfer
9 DONE_INT Status (0=Busy, 1=Done/Okay)
10 DONE_ERR Status (1=Error)
11-13 BIT_CNT_IN_LAST_BYTE (0=Normal/8bit, 1..7=whatever)
For I2C with TX_CNT and RX_CNT both nonzero: TX data is transferred first.
Unknown when the DONE flags are cleared (possibly when writing 0 to bit9,10, or
when writing 1 to bit8, or maybe automatically after reading).
ATH:010008h..01000Ch - SI_TX_DATA0/SI_TX_DATA1
0-7 DATA0 1st TX byte (device number in case of I2C mode)
8-15 DATA1 2nd TX byte (if any)
16-23 DATA2 ...
24-31 DATA3 ..
32-39 DATA4
40-47 DATA5
48-55 DATA6
56-63 DATA7
ATH:010010h..010014h - SI_RX_DATA0/SI_RX_DATA1
0-7 DATA0 1st RX byte (if any)
8-15 DATA1 2nd RX byte (if any)
16-23 DATA2 ...
24-31 DATA3 ..
32-39 DATA4
40-47 DATA5
48-55 DATA6
56-63 DATA7
DSi Atheros Wifi - Internal I/O - 014000h - GPIO 18/26/57 pin (hw2/hw4/hw6)
---------------------------------------------------------------------------
ATH:018000h..01800Ch - WLAN_MBOX_FIFO[0..3]
0-7 DATA: DATABYTE
8-11 DATA: zero?
12-15 DATA: zero? maybe copy of MBOX_FIFO_STATUS bit12-15 ? (FULL)
16-19 DATA: looks like copy of MBOX_FIFO_STATUS bit16-19 ? (EMPTY)
20-31 -
READ: Allows to read incoming MBOX data; before reading this register, the data
MUST be manually copied to this register via WLAN_MBOX_TXFIFO_POP[n], then read
this register, and check the EMPTY flag; this requires "double indexing" as so:
for MBOX(n), test "WLAN_MBOX_FIFO[n].bit(16+n)", if the bit is zero, then
bit0-7 contains valid data.
WRITE: Allows to send outgoing MBOX data (write the databyte, with zeroes in
bit8-31); before doing so, one SHOULD check if the FIFO is full via
WLAN_MBOX_FIFO_STATUS.
ATH:0180F0h..0180FCh - WLAN_MBOX_TXFIFO_POP[0..3]
0 DATA ... uh 4x1bit ? for MBOX0..3 ?
1-31 -
Writing 0 to WLAN_MBOX_TXFIFO_POP[n] does remove the oldest "TXFIFO" entry (the
data transmitted from SDIO side to xtensa side via MBOXn), and stores that
value (and a copy of the WLAN_MBOX_FIFO_STATUS bits) in WLAN_MBOX_FIFO[n].
ATH:018100h..01810Ch - WLAN_MBOX_RXFIFO_POP[0..3]
0 DATA ... uh 4x1bit ? for MBOX0..3 ?
1-31 -
Probably similar as above, but for opposite direction (ie. allowing to read
data that was "sent-to-the-host"; normally such data should be read by the
host, so one would use this feature only if one wants to screw up the normal
transfer flow).
ATH:018014h - WLAN_MBOX_DMA_POLICY
0 RX_ORDER
1 RX_QUANTUM
2 TX_ORDER
3 TX_QUANTUM
4-31 -
ATH:018018h - WLAN_MBOX0_DMA_RX_DESCRIPTOR_BASE
ATH:018020h - WLAN_MBOX0_DMA_TX_DESCRIPTOR_BASE
ATH:018028h - WLAN_MBOX1_DMA_RX_DESCRIPTOR_BASE
ATH:018030h - WLAN_MBOX1_DMA_TX_DESCRIPTOR_BASE
ATH:018038h - WLAN_MBOX2_DMA_RX_DESCRIPTOR_BASE
ATH:018040h - WLAN_MBOX2_DMA_TX_DESCRIPTOR_BASE
ATH:018048h - WLAN_MBOX3_DMA_RX_DESCRIPTOR_BASE
ATH:018050h - WLAN_MBOX3_DMA_TX_DESCRIPTOR_BASE
ATH:018114h - WLAN_GMBOX0_DMA_RX_DESCRIPTOR_BASE - hw4/hw6 only
ATH:01811Ch - WLAN_GMBOX0_DMA_TX_DESCRIPTOR_BASE - hw4/hw6 only
0-1 -
2-27 ADDRESS
28-31 -
ATH:01801Ch - WLAN_MBOX0_DMA_RX_CONTROL
ATH:018024h - WLAN_MBOX0_DMA_TX_CONTROL
ATH:01802Ch - WLAN_MBOX1_DMA_RX_CONTROL
ATH:018034h - WLAN_MBOX1_DMA_TX_CONTROL
ATH:01803Ch - WLAN_MBOX2_DMA_RX_CONTROL
ATH:018044h - WLAN_MBOX2_DMA_TX_CONTROL
ATH:01804Ch - WLAN_MBOX3_DMA_RX_CONTROL
ATH:018054h - WLAN_MBOX3_DMA_TX_CONTROL
ATH:018118h - WLAN_GMBOX0_DMA_RX_CONTROL - hw4/hw6 only
ATH:018120h - WLAN_GMBOX0_DMA_TX_CONTROL - hw4/hw6 only
0 STOP
1 START
2 RESUME
3-31 -
ATH:018010h - WLAN_MBOX_FIFO_STATUS
0-11 -
12-15 FULL flags for MBOX 0..3
16-19 EMPTY flags for MBOX 0..3
20-31 -
ATH:018058h - WLAN_MBOX_INT_STATUS
ATH:01805Ch - WLAN_MBOX_INT_ENABLE
0-7 HOST Interrupt 0..7 from Host ;SDIO 1:00472h.bit0..7
8-11 RX_NOT_FULL MBOX0..3 RX FIFO Not Full
12-15 TX_NOT_EMPTY MBOX0..3 TX FIFO Not Empty
16 RX_UNDERFLOW MBOX RX Underflow (tried to read from empty fifo)
17 TX_OVERFLOW MBOX TX Overflow (tried to write to full fifo)
18 hw6: FRAME_DONE ;\hw6.0 only
19 hw6: NO_RX_MBOX_DATA_AVA ;/
20-23 TX_DMA_COMPLETE MBOX0..3 TX DMA Complete
24-27 TX_DMA_EOM_COMPLETE MBOX0..3 TX DMA Complete .. End of message?
28-31 RX_DMA_COMPLETE MBOX0..3 RX DMA Complete
ATH:018060h - WLAN_INT_HOST
0-7 VECTOR Interrupt 0..7 to Host ;SDIO 1:00401h.bit0..7
8-31 -
ATH:018080h..01809Ch - WLAN_LOCAL_COUNT[0..7]
ATH:0180A0h..0180BCh - WLAN_COUNT_INC[0..7]
0-7 VALUE (credit counter) ;SDIO 1:00420h..00427h
8-31 -
See COUNT and COUNT_DEC.
ATH:0180C0h..0180DCh - WLAN_LOCAL_SCRATCH[0..7]
0-7 VALUE (scratch) ;SDIO 1:00460h..00467h
8-31 -
ATH:0180E0h - WLAN_USE_LOCAL_BUS
0 PIN_INIT ;whatever, maybe PCI bus related (non-SDIO) ?
1-31 -
ATH:0180E4h - WLAN_SDIO_CONFIG
0 CCCR_IOR1 ;SDIO Func I/O Ready bit1 ? ;SDIO 0:00002h.bit1
1-31 -
ATH:01A000h..01BFFCh - WLAN_HOST_IF_WINDOW[0..2047]
0-7 DATA ;SDIO 1:00000h..007FFh
8-31 -
Allows to access the SDIO Host registers via Internal registers, should be done
only for testing purposes.
ATH:0180E8h - WLAN_MBOX_DEBUG
0-2 SEL
3-31 -
ATH:0180ECh - WLAN_MBOX_FIFO_RESET
0 INIT
1-31 -
ATH:018110h - WLAN_SDIO_DEBUG
0-3 SEL
4-31 -
ATH:01C014h - SYNTH_SYNTH6
0-2 SPARE_BIAS
3-4 VCOBUFBIAS
5-7 ICVCO
8-10 ICSPAREB
11-13 ICSPAREA
14-16 ICLOMIX
17-19 ICLODIV
20-22 ICPRESC
23-25 IRSPARE
26-28 IRVCMON
29-31 IRCP
ATH:01C020h - RF5G_RF5G1
0-1 SPARE
2 REGLO_BYPASS5
3 LO5CONTROL
4-6 LO5_ATB_SEL
7 PDREGLO5
8 PDLO5AGC
9 PDQBUF5
10 PDLO5MIX
11 PDLO5DIV
12-14 TX5_ATB_SEL
15-17 OB5
18-20 DB5
21-23 PWDTXPKD
24-26 TUNE_PADRV5
27 PDPAOUT5
28 PDPADRV5
29 PDTXBUF5
30 PDTXMIX5
31 PDTXLO5
ATH:01C024h - RF5G_RF5G2
0-1 SPARE
2-4 TUNE_LO
5 ENABLE_PCA
6-7 LNA5_ATTENMODE
8 REGFE_BYPASS5
9-11 BVGM5
12-14 BCSLNA5
15-17 BRFVGA5
18-20 TUNE_RFVGA5
21 PDREGFE5
22 PDRFVGA5
23 PDCSLNA5
24 PDVGM5
25 PDCMOSLO5
26-28 RX5_ATB_SEL
29-31 AGCLO_B
ATH:01C028h - RF2G_RF2G1
0-4 SPARE
5 SHORTLNA2
6 LOCONTROL
7 SELLNA
8-10 RF_ATB_SEL
11-13 FE_ATB_SEL
14-16 OB
17-19 DB
20-22 BLNA2
23-25 BLNA1BUF
26-28 BLNA1F
29-31 BLNA1
ATH:01C02Ch - RF2G_RF2G2
0-16 SPARE
17 ENABLE_PCB
18 REGLO_BYPASS
19 REGLNA_BYPASS
20 PDTXMIX
21 PDTXLO
22 PDRXLO
23 PDRFGM
24 PDREGLO
25 PDREGLNA
26 PDPAOUT
27 PDPADRV
28 PDDIV
29 PDCSLNA
30 PDCGLNABUF
31 PDCGLNA
ATH:01C030h - TOP_GAIN
0 SPARE
1-2 RX6DBHIQGAIN
3-5 RX1DBLOQGAIN
6-7 RX6DBLOQGAIN
8-10 RFGMGN
11-12 RFVGA5GAIN
13-16 LNAGAIN
17 LNAON
18-20 PAOUT2GN
21-23 PADRVGN
24 PABUF5GN
25-26 TXV2IGAIN
27-29 TX1DBLOQGAIN
30-31 TX6DBLOQGAIN
ATH:01C034h - TOP_TOP
0 FORCE_XPAON
1 INT2GND
2 PAD2GND
3 INTH2PAD
4 INT2PAD
5-7 REVID
8-9 DATAOUTSEL
10 PDBIAS
11 SYNTHON_FORCE
12 SCLKEN_FORCE
13 OSCON
14 PWDCLKIN
15 LOCALXTAL
16 PWDDAC
17 PWDADC
18 PWDPLL
19 LOCALADDAC
20 CALTX
21 PAON
22 TXON
23 RXON
24 SYNTHON
25 BMODE
26 CAL_RESIDUE
27 CALDC
28 CALFC
29 LOCALMODE
30 LOCALRXGAIN
31 LOCALTXGAIN
ATH:01C038h - BIAS_BIAS_SEL
0 PWD_ICLDO25
1-3 PWD_ICTXPC25
4-6 PWD_ICTSENS25
7-9 PWD_ICXTAL25
10-12 PWD_ICCOMPBIAS25
13 PWD_ICCPLL25
14 PWD_ICREFOPAMPBIAS25
15 PWD_IRREFMASTERBIAS12P5
16 PWD_IRDACREGREF12P5
17-19 PWD_ICREFBUFBIAS12P5
20 SPARE
21-24 SEL_SPARE
25-30 SEL_BIAS
31 PADON
ATH:01C03Ch - BIAS_BIAS1
0-1 SPARE
2-4 PWD_IC5GMIXQ25
5-7 PWD_IC5GQB25
8-10 PWD_IC5GTXBUF25
11-13 PWD_IC5GTXPA25
14 PWD_IC5GRXRF25
15 PWD_ICDETECTORA25
16 PWD_ICDETECTORB25
17-19 PWD_IC2GLNAREG25
20-22 PWD_IC2GLOREG25
23-25 PWD_IC2GRFFE25
26-28 PWD_IC2GVGM25
29-31 PWD_ICDAC2BB25
ATH:01C040h - BIAS_BIAS2
0-2 PWD_IR5GRFVREF2525
3-5 PWD_IR2GLNAREG25
6-8 PWD_IR2GLOREG25
9-11 PWD_IR2GTXMIX25
12 PWD_IRLDO25
13-15 PWD_IRTXPC25
16-18 PWD_IRTSENS25
19-21 PWD_IRXTAL25
22 PWD_IRPLL25
23-25 PWD_IC5GLOREG25
26-28 PWD_IC5GDIV25
29-31 PWD_IC5GMIXI25
ATH:01C044h - BIAS_BIAS3
0 SPARE
1-3 PWD_ICDACREG12P5
4-6 PWD_IR25SPARE2
7-9 PWD_IR25SPARE1
10-12 PWD_IC25SPARE2
13-15 PWD_IC25SPARE1
16 PWD_IRBB50
17 PWD_IRSYNTH50
18-20 PWD_IC2GDIV50
21 PWD_ICBB50
22 PWD_ICSYNTH50
23-25 PWD_ICDAC50
26-28 PWD_IR5GAGC25
29-31 PWD_IR5GTXMIX25
ATH:01C048h - TXPC_TXPC
0-1 ATBSEL
2 SELCOUNT
3-4 SELINIT
5 ON1STSYNTHON
6-13 N
14-15 TSMODE
16 SELCMOUT
17 SELMODREF
18 CLKDELAY
19 NEGOUT
20 CURHALF
21 TESTPWDPC
22-27 TESTDAC
28-29 TESTGAIN
30 TEST
31 SELINTPD
ATH:01C04Ch - TXPC_MISC
0-5 SPARE
6-7 XTALDIV
8-17 DECOUT
18-20 SPARE_A
21 SELTSN
22 SELTSP
23 LOCALBIAS2X
24 LOCALBIAS
25 PWDXINPAD
26 PWDCLKIND
27 NOTCXODET
28 LDO_TEST_MODE
29-30 LEVEL
31 FLIPBMODE
ATH:01C050h - RXTXBB_RXTXBB1
0 PDHIQ
1 PDLOQ
2 PDOFFSETI2V
3 PDOFFSETHIQ
4 PDOFFSETLOQ
5 PDRXTXBB
6 PDI2V
7 PDV2I
8 PDDACINTERFACE
6-16 SEL_ATB
17-18 FNOTCH
19-31 SPARE
ATH:01C054h - RXTXBB_RXTXBB2
0 PATH_OVERRIDE
1 PATH1LOQ_EN
2 PATH2LOQ_EN
3 PATH3LOQ_EN
4 PATH1HIQ_EN
5 PATH2HIQ_EN
6 FILTERDOUBLEBW
7 LOCALFILTERTUNING
8-12 FILTERFC
13-14 CMSEL
15 SEL_I2V_TEST
16 SEL_HIQ_TEST
17 SEL_LOQ_TEST
18 SEL_DAC_TEST
19 SELBUFFER
20 SHORTBUFFER
21-22 SPARE
23-25 IBN_37P5_OSI2V_CTRL
26-28 IBN_37P5_OSLO_CTRL
29-31 IBN_37P5_OSHI_CTRL
ATH:01C058h - RXTXBB_RXTXBB3
0-2 IBN_100U_TEST_CTRL
3-5 IBRN_12P5_CM_CTRL
6-8 IBN_25U_LO2_CTRL
9-11 IBN_25U_LO1_CTRL
12-14 IBN_25U_HI2_CTRL
15-17 IBN_25U_HI1_CTRL
18-20 IBN_25U_I2V_CTRL
21-23 IBN_25U_BKV2I_CTRL
24-26 IBN_25U_CM_BUFAMP_CTRL
27-31 SPARE
ATH:01C05Ch - RXTXBB_RXTXBB4
0-4 OFSTCORRI2VQ
5-9 OFSTCORRI2VI
10-14 OFSTCORRLOQ
15-19 OFSTCORRLOI
20-24 OFSTCORRHIQ
25-29 OFSTCORRHII
30 LOCALOFFSET
31 SPARE
ATH:01C060h - ADDAC_ADDAC1 ;aka "A/D and D/A Converter"
0-5 SPARE
6 DISABLE_DAC_REG
7-8 CM_SEL
9 INV_CLK160_ADC
10 SELMANPWDS
11 FORCEMSBLOW
12 PWDDAC
13 PWDADC
14 PWDPLL
15-22 PLL_FILTER
23-25 PLL_ICP
26-27 PLL_ATB
28-30 PLL_SCLAMP
31 PLL_SVREG
ATH:01C080h - SW_OVERRIDE
0 ENABLE
1 SUPDATE_DELAY
ATH:01C084h - SIN_VAL
0 SIN
ATH:01C088h - SW_SCLK
0 SW_SCLK
ATH:01C08Ch - SW_CNTL
0 SW_SOUT
1 SW_SUPDATE
2 SW_SCAPTURE
These registers are same in hw4/hw6, except for some small differences:
0001C050h one new bit in hw6.0
0001C148h several new bits in hw6.0
0001C740h added/removed/renumbered bits in hw6.0
0001C744h two changed/renamed bits in hw6.0
ATH:01C000h - PHY_ANALOG_RXRF_BIAS1
0 SPARE
1-3 PWD_IR25SPARE
4-6 PWD_IR25LO18
7-9 PWD_IC25LO36
10-12 PWD_IC25MXR2_5GH
13-15 PWD_IC25MXR5GH
16-18 PWD_IC25VGA5G
19-21 PWD_IC75LNA5G
22-24 PWD_IR25LO24
25-27 PWD_IC25MXR2GH
28-30 PWD_IC75LNA2G
31 PWD_BIAS
ATH:01C004h - PHY_ANALOG_RXRF_BIAS2
0 SPARE
1-3 PKEN
4-6 VCMVALUE
7 PWD_VCMBUF
8-10 PWD_IR25SPAREH
11-13 PWD_IR25SPARE
14-16 PWD_IC25LNABUF
17-19 PWD_IR25AGCH
20-22 PWD_IR25AGC
23-25 PWD_IC25AGC
26-28 PWD_IC25VCMBUF
29-31 PWD_IR25VCM
ATH:01C008h - PHY_ANALOG_RXRF_GAINSTAGES
0 SPARE
1 LNAON_CALDC
2-3 VGA5G_CAP
4-5 LNA5G_CAP
6 LNA5G_SHORTINP
7 PWD_LO5G
8 PWD_VGA5G
9 PWD_MXR5G
10 PWD_LNA5G
11-12 LNA2G_CAP
13 LNA2G_SHORTINP
14 LNA2G_LP
15 PWD_LO2G
16 PWD_MXR2G
17 PWD_LNA2G
18-19 MXR5G_GAIN_OVR
20-22 VGA5G_GAIN_OVR
23-25 LNA5G_GAIN_OVR
26-27 MXR2G_GAIN_OVR
28-30 LNA2G_GAIN_OVR
31 RX_OVERRIDE
ATH:01C00Ch - PHY_ANALOG_RXRF_AGC
0 RF5G_ON_DURING_CALPA
1 RF2G_ON_DURING_CALPA
2 AGC_OUT (R)
3 LNABUFGAIN2X
4 LNABUF_PWD_OVR
5 PWD_LNABUF
6-8 AGC_FALL_CTRL
9-14 AGC5G_CALDAC_OVR
15-18 AGC5G_DBDAC_OVR
19-24 AGC2G_CALDAC_OVR
25-28 AGC2G_DBDAC_OVR
29 AGC_CAL_OVR
30 AGC_ON_OVR
31 AGC_OVERRIDE
ATH:01C040h - PHY_ANALOG_TXRF1
0 PDLOBUF5G
1 PDLODIV5G
2 LOBUF5GFORCED
3 LODIV5GFORCED
4-7 PADRV2GN5G
8-11 PADRV3GN5G
12-15 PADRV4GN5G
16 LOCALTXGAIN5G
17 PDOUT2G
18 PDDR2G
19 PDMXR2G
20 PDLOBUF2G
21 PDLODIV2G
22 LOBUF2GFORCED
23 LODIV2GFORCED
24-30 PADRVGN2G
31 LOCALTXGAIN2G
ATH:01C044h - PHY_ANALOG_TXRF2
0-2 D3B5G
3-5 D4B5G
6-8 OCAS2G
9-11 DCAS2G
12-14 OB2G_PALOFF
15-17 OB2G_QAM
18-20 OB2G_PSK
21-23 OB2G_CCK
24-26 DB2G
27-30 PDOUT5G
31 PDMXR5G
ATH:01C048h - PHY_ANALOG_TXRF3
0-1 FILTR2G
2 PWDFB2_2G
3 PWDFB1_2G
4 PDFB2G
5-6 RDIV5G
7-9 CAPDIV5G
10 PDPREDIST5G
11-12 RDIV2G
13 PDPREDIST2G
14-16 OCAS5G
17-19 D2CAS5G
20-22 D3CAS5G
23-25 D4CAS5G
26-28 OB5G
29-31 D2B5G
ATH:01C04Ch - PHY_ANALOG_TXRF4
0-1 PK1B2G_CCK
2-4 MIOB2G_QAM
5-7 MIOB2G_PSK
8-10 MIOB2G_CCK
11-13 COMP2G_QAM
14-16 COMP2G_PSK
17-19 COMP2G_CCK
20-22 AMP2B2G_QAM
23-25 AMP2B2G_PSK
26-28 AMP2B2G_CCK
29-31 AMP2CAS2G
ATH:01C050h - PHY_ANALOG_TXRF5
0 hw4: SPARE5
0 hw6: TXMODPALONLY ;-hw6.0 only
1 PAL_LOCKED (R)
2 FBHI2G (R)
3 FBLO2G (R)
4 NOPALGAIN2G
5 ENPACAL2G
6-12 OFFSET2G
13 ENOFFSETCAL2G
14-16 REFHI2G
17-19 REFLO2G
20-21 PALCLAMP2G
22-23 PK2B2G_QAM
24-25 PK2B2G_PSK
26-27 PK2B2G_CCK
28-29 PK1B2G_QAM
30-31 PK1B2G_PSK
ATH:01C054h - PHY_ANALOG_TXRF6
0 PALCLKGATE2G
1-8 PALFLUCTCOUNT2G
9-10 PALFLUCTGAIN2G
11 PALNOFLUCT2G
12-14 GAINSTEP2G
15 USE_GAIN_DELTA2G
16-19 CAPDIV_I2G
20-23 PADRVGN_INDEX_I2G
24-26 VCMONDELAY2G
27-30 CAPDIV2G
31 CAPDIV2GOVR
ATH:01C064h - PHY_ANALOG_TXRF10
0-2 SPARE10
3 PDOUT5G_3CALTX
4-6 D3B5GCALTX
7-9 D4B5GCALTX
10-16 PADRVGN2GCALTX
17-19 DB2GCALTX
20 CALTXSHIFT
21 CALTXSHIFTOVR
22-27 PADRVGN2G_SMOUT (R)
28-31 PADRVGN_INDEX2G_SMOUT (R)
ATH:01C068h - PHY_ANALOG_TXRF11
0-1 SPARE11
2-4 PWD_IR25MIXDIV5G
5-7 PWD_IR25PA2G
8-10 PWD_IR25MIXBIAS2G
11-13 PWD_IR25MIXDIV2G
14-16 PWD_ICSPARE
17-19 PWD_IC25TEMPSEN
20-22 PWD_IC25PA5G2
23-25 PWD_IC25PA5G1
26-28 PWD_IC25MIXBUF5G
29-31 PWD_IC25PA2G
ATH:01C06Ch - PHY_ANALOG_TXRF12
0-7 SPARE12_2 (R)
8-9 SPARE12_1
10-13 ATBSEL5G
14-16 ATBSEL2G
17-19 PWD_IRSPARE
20-22 PWD_IR25TEMPSEN
23-25 PWD_IR25PA5G2
26-28 PWD_IR25PA5G1
29-31 PWD_IR25MIXBIAS5G
ATH:01C080h - PHY_ANALOG_SYNTH1
0-2 SEL_VCMONABUS
3-5 SEL_VCOABUS
6 MONITOR_SYNTHLOCKVCOK
7 MONITOR_VC2LOW
8 MONITOR_VC2HIGH
9 MONITOR_FB_DIV2
10 MONITOR_REF
11 MONITOR_FB
12 SEVENBITVCOCAP
13-15 PWUP_PD
16 PWD_VCOBUF
17-18 VCOBUFGAIN
19-20 VCOREGLEVEL
21 VCOREGBYPASS
22 PWUP_LOREF
23 PWD_LOMIX
24 PWD_LODIV
25 PWD_LOBUF5G
26 PWD_LOBUF2G
27 PWD_PRESC
28 PWD_VCO
29 PWD_VCMON
30 PWD_CP
31 PWD_BIAS
ATH:01C084h - PHY_ANALOG_SYNTH2
0-3 CAPRANGE3
4-7 CAPRANGE2
8-11 CAPRANGE1
12-15 LOOPLEAKCUR_INTN
16 CPLOWLK_INTN
17 CPSTEERING_EN_INTN
18-19 CPBIAS_INTN
20-22 VC_LOW_REF
23-25 VC_MID_REF
26-28 VC_HI_REF
29-31 VC_CAL_REF
ATH:01C088h - PHY_ANALOG_SYNTH3
0-5 WAIT_VC_CHECK
6-11 WAIT_CAL_LIN
12-17 WAIT_CAL_BIN
18-23 WAIT_PWRUP
24-29 WAIT_SHORTR_PWRUP
30 SEL_CLK_DIV2
31 DIS_CLK_XTAL
ATH:01C08Ch - PHY_ANALOG_SYNTH4
0 PS_SINGLE_PULSE
1 LONGSHIFTSEL
2-3 LOBUF5GTUNE_OVR
4 FORCE_LOBUF5GTUNE
5 PSCOUNT_FBSEL
6-7 SDM_DITHER1
8 SDM_MODE
9 SDM_DISABLE
10 RESET_PRESC
11-12 PRESCSEL
13 PFD_DISABLE
14 PFDDELAY_FRACN
15 FORCE_LO_ON
16 CLKXTAL_EDGE_SEL
17 VCOCAPPULLUP
18-25 VCOCAP_OVR
26 FORCE_VCOCAP
27 FORCE_PINVC
28 SHORTR_UNTIL_LOCKED
29 ALWAYS_SHORTR
30 DIS_LOSTVC
31 DIS_LIN_CAPSEARCH
ATH:01C090h - PHY_ANALOG_SYNTH5
0-1 VCOBIAS
2-4 PWDB_ICLOBUF5G50
5-7 PWDB_ICLOBUF2G50
8-10 PWDB_ICVCO25
11-13 PWDB_ICVCOREG25
14 PWDB_IRVCOREG50
15-17 PWDB_ICLOMIX
18-20 PWDB_ICLODIV50
21-23 PWDB_ICPRESC50
24-26 PWDB_IRVCMON25
27-29 PWDB_IRPFDCP
30-31 SDM_DITHER2
ATH:01C094h - PHY_ANALOG_SYNTH6
0-1 LOBUF5GTUNE (R)
2-8 LOOP_IP (R)
9 VC2LOW (R)
10 VC2HIGH (R)
11 RESET_SDM_B (R)
12 RESET_PSCOUNTERS (R)
13 RESET_PFD (R)
14 RESET_RFD (R)
15 SHORT_R (R)
16-23 VCO_CAP_ST (R)
24 PIN_VC (R)
25 SYNTH_LOCK_VC_OK (R)
26 CAP_SEARCH (R)
27-30 SYNTH_SM_STATE (R)
31 SYNTH_ON (R)
ATH:01C098h - PHY_ANALOG_SYNTH7
0 OVRCHANDECODER
1 FORCE_FRACLSB
2-18 CHANFRAC
19-27 CHANSEL
28-29 AMODEREFSEL
30 FRACMODE
31 LOADSYNTHCHANNEL
ATH:01C09Ch - PHY_ANALOG_SYNTH8
0 CPSTEERING_EN_FRACN
1-7 LOOP_ICPB
8-11 LOOP_CSB
12-16 LOOP_RSB
17-21 LOOP_CPB
22-26 LOOP_3RD_ORDER_RB
27-31 REFDIVB
ATH:01C0A0h - PHY_ANALOG_SYNTH9
0 PFDDELAY_INTN
1-3 SLOPE_ICPA0
4-7 LOOP_ICPA0
8-11 LOOP_CSA0
12-16 LOOP_RSA0
17-21 LOOP_CPA0
22-26 LOOP_3RD_ORDER_RA
27-31 REFDIVA
ATH:01C0A4h - PHY_ANALOG_SYNTH10
0-1 SPARE10A
2-4 PWDB_ICLOBIAS50
5-7 PWDB_IRSPARE25
8-10 PWDB_ICSPARE25
11-13 SLOPE_ICPA1
14-17 LOOP_ICPA1
18-21 LOOP_CSA1
22-26 LOOP_RSA1
27-31 LOOP_CPA1
ATH:01C0A8h - PHY_ANALOG_SYNTH11
0-4 SPARE11A
5 FORCE_LOBUF5G_ON
6-7 LOREFSEL
8-9 LOBUF2GTUNE
10 CPSTEERING_MODE
11-13 SLOPE_ICPA2
14-17 LOOP_ICPA2
18-21 LOOP_CSA2
22-26 LOOP_RSA2
27-31 LOOP_CPA2
ATH:01C0ACh - PHY_ANALOG_SYNTH12
0-9 SPARE12A
10-13 LOOPLEAKCUR_FRACN
14 CPLOWLK_FRACN
15-16 CPBIAS_FRACN
17 SYNTHDIGOUTEN
18 STRCONT
19-22 VREFMUL3
23-26 VREFMUL2
27-30 VREFMUL1
31 CLK_DOUBLER_EN
ATH:01C0B0h - PHY_ANALOG_SYNTH13
0 SPARE13A
1-3 SLOPE_ICPA_FRACN
4-7 LOOP_ICPA_FRACN
8-11 LOOP_CSA_FRACN
12-16 LOOP_RSA_FRACN
17-21 LOOP_CPA_FRACN
22-26 LOOP_3RD_ORDER_RA_FRACN
27-31 REFDIVA_FRACN
ATH:01C0B4h - PHY_ANALOG_SYNTH14
0-1 SPARE14A
2-3 LOBUF5GTUNE_3
4-5 LOBUF2GTUNE_3
6-7 LOBUF5GTUNE_2
8-9 LOBUF2GTUNE_2
10 PWD_LOBUF5G_3
11 PWD_LOBUF2G_3
12 PWD_LOBUF5G_2
13 PWD_LOBUF2G_2
14-16 PWUPLO23_PD
17-19 PWDB_ICLOBUF5G50_3
20-22 PWDB_ICLOBUF2G50_3
23-25 PWDB_ICLOBUF5G50_2
26-28 PWDB_ICLOBUF2G50_2
29-31 PWDB_ICLVLSHFT
ATH:01C0C0h - PHY_ANALOG_BIAS1
0-6 SPARE1
7-9 PWD_IC25V2IQ
10-12 PWD_IC25V2II
13-15 PWD_IC25BB
16-18 PWD_IC25DAC
19-21 PWD_IC25FIR
22-24 PWD_IC25ADC
25-31 BIAS_SEL
ATH:01C0C4h - PHY_ANALOG_BIAS2
0-4 SPARE2
5-7 PWD_IC25XPA
8-10 PWD_IC25XTAL
11-13 PWD_IC25TXRF
14-16 PWD_IC25RXRF
17-19 PWD_IC25SYNTH
20-22 PWD_IC25PLLREG
23-25 PWD_IC25PLLCP2
26-28 PWD_IC25PLLCP
29-31 PWD_IC25PLLGM
ATH:01C0C8h - PHY_ANALOG_BIAS3
0-1 SPARE3
2-4 PWD_IR25SAR
5-7 PWD_IR25TXRF
8-10 PWD_IR25RXRF
11-13 PWD_IR25SYNTH
14-16 PWD_IR25PLLREG
17-19 PWD_IR25BB
20-22 PWD_IR50DAC
23-25 PWD_IR25DAC
26-28 PWD_IR25FIR
29-31 PWD_IR50ADC
ATH:01C0CCh - PHY_ANALOG_BIAS4
0-10 SPARE4
11-13 PWD_IR25SPARED
14-16 PWD_IR25SPAREC
17-19 PWD_IR25SPAREB
20-22 PWD_IR25XPA
23-25 PWD_IC25SPAREC
26-28 PWD_IC25SPAREB
29-31 PWD_IC25SPAREA
ATH:01C100h - PHY_ANALOG_RXTX1
0 SCFIR_GAIN
1 MANRXGAIN
2-5 AGC_DBDAC
6 OVR_AGC_DBDAC
7 ENABLE_PAL
8 ENABLE_PAL_OVR
9-11 TX1DB_BIQUAD
12-13 TX6DB_BIQUAD
14 PADRVHALFGN2G
15-18 PADRV2GN
19-22 PADRV3GN5G
23-26 PADRV4GN5G
27-30 TXBB_GC
31 MANTXGAIN
ATH:01C104h - PHY_ANALOG_RXTX2
0 BMODE
1 BMODE_OVR
2 SYNTHON
3 SYNTHON_OVR
4-5 BW_ST
6 BW_ST_OVR
7 TXON
8 TXON_OVR
9 PAON
10 PAON_OVR
11 RXON
12 RXON_OVR
13 AGCON
14 AGCON_OVR
15-17 TXMOD
18 TXMOD_OVR
19-21 RX1DB_BIQUAD
22-23 RX6DB_BIQUAD
24-25 MXRGAIN
26-28 VGAGAIN
29-31 LNAGAIN
ATH:01C108h - PHY_ANALOG_RXTX3
0-2 SPARE3
3 SPURON
4 PAL_LOCKEDEN
5 DACFULLSCALE
6 ADCSHORT
7 DACPWD
8 DACPWD_OVR
9 ADCPWD
10 ADCPWD_OVR
11-16 AGC_CALDAC
17 AGC_CAL
18 AGC_CAL_OVR
19 LOFORCEDON
20 CALRESIDUE
21 CALRESIDUE_OVR
22 CALFC
23 CALFC_OVR
24 CALTX
25 CALTX_OVR
26 CALTXSHIFT
27 CALTXSHIFT_OVR
28 CALPA
29 CALPA_OVR
30 TURBOADC
31 TURBOADC_OVR
ATH:01C140h - PHY_ANALOG_BB1
0 I2V_CURR2X
1 ENABLE_LOQ
2 FORCE_LOQ
3 ENABLE_NOTCH
4 FORCE_NOTCH
5 ENABLE_BIQUAD
6 FORCE_BIQUAD
7 ENABLE_OSDAC
8 FORCE_OSDAC
9 ENABLE_V2I
10 FORCE_V2I
11 ENABLE_I2V
12 FORCE_I2V
13-15 CMSEL
16-17 ATBSEL
18 PD_OSDAC_CALTX_CALPA
19-23 OFSTCORRI2VQ
24-28 OFSTCORRI2VI
29 LOCALOFFSET
30-31 RANGE_OSDAC
ATH:01C144h - PHY_ANALOG_BB2
0-3 SPARE
4-7 MXR_HIGHGAINMASK
8-9 SEL_TEST
10-14 RCFILTER_CAP
15 OVERRIDE_RCFILTER_CAP
16-19 FNOTCH
20 OVERRIDE_FNOTCH
21-25 FILTERFC
26 OVERRIDE_FILTERFC
27 I2V2RXOUT_EN
28 BQ2RXOUT_EN
29 RXIN2I2V_EN
30 RXIN2BQ_EN
31 SWITCH_OVERRIDE
ATH:01C148h - PHY_ANALOG_BB3
0-7 SPARE
8-15 hw4: SPARE
8-9 hw6: SEL_OFST_READBK ;\
10 hw6: OVERRIDE_RXONLY_FILTERFC ; hw6.0 only
11-15 hw6: RXONLY_FILTERFC ;/
16-20 FILTERFC (R)
21-25 OFSTCORRI2VQ (R)
26-30 OFSTCORRI2VI (R)
31 EN_TXBBCONSTCUR
ATH:01C280h - PHY_ANALOG_PLLCLKMODA
0 PWD_PLLSDM
1 PWDPLL
2-16 PLLFRAC
17-20 REFDIV
21-30 DIV
31 LOCAL_PLL
ATH:01C284h - PHY_ANALOG_PLLCLKMODA2
0-3 SPARE
4 DACPWD
5 ADCPWD
6 LOCAL_ADDAC
7-8 DAC_CLK_SEL
9-12 ADC_CLK_SEL
13 LOCAL_CLKMODA
14 PLLBYPASS
15 LOCAL_PLLBYPASS
16-17 PLLATB
18 PLL_SVREG
19 HI_FREQ_EN
20 RST_WARM_INT_L
21 RST_WARM_OVR
22-23 PLL_KVCO
24-26 PLLICP
27-31 PLLFILTER
ATH:01C288h - PHY_ANALOG_TOP
0-2 SPARE
3 PWDBIAS
4 FLIP_XPABIAS
5 XPAON2
6 XPAON5
7 XPASHORT2GND
8-11 XPABIASLVL
12 XPABIAS_EN
13 ATBSELECT
14 LOCAL_XPA
15 XPABIAS_BYPASS
16 TEST_PADQ_EN
17 TEST_PADI_EN
18 TESTIQ_RSEL
19 TESTIQ_BUFEN
20 PAD2GND
21 INTH2PAD
22 INTH2GND
23 INT2PAD
24 INT2GND
25 PWDPALCLK
26 INV_CLK320_ADC
27 FLIP_REFCLK40
28 FLIP_PLLCLK320
29 FLIP_PLLCLK160
30-31 CLK_SEL
ATH:01C28Ch - PHY_ANALOG_THERM
0-2 LOREG_LVL
3-5 RFREG_LVL
6 SAR_ADC_DONE (R)
7-14 SAR_ADC_OUT (R)
15-22 SAR_DACTEST_CODE
23 SAR_DACTEST_EN
24 SAR_ADCCAL_EN
25-26 THERMSEL
27 SAR_SLOW_EN
28 THERMSTART
29 SAR_AUTOPWD_EN
30 THERMON
31 LOCAL_THERM
ATH:01C290h - PHY_ANALOG_XTAL
0-5 SPARE
6 XTAL_NOTCXODET
7 LOCALBIAS2X
8 LOCAL_XTAL
9 XTAL_PWDCLKIN
10 XTAL_OSCON
11 XTAL_PWDCLKD
12 XTAL_LOCALBIAS
13 XTAL_SHRTXIN
14-15 XTAL_DRVSTR
16-22 XTAL_CAPOUTDAC
23-29 XTAL_CAPINDAC
30 XTAL_BIAS2X
31 TCXODET (R)
ATH:01C380h - PHY_ANALOG_RBIST_CNTRL
0 ATE_TONEGEN_DC_ENABLE
1 ATE_TONEGEN_TONE0_ENABLE
2 ATE_TONEGEN_TONE1_ENABLE
3 ATE_TONEGEN_LFTONE0_ENABLE
4 ATE_TONEGEN_LINRAMP_ENABLE_I
5 ATE_TONEGEN_LINRAMP_ENABLE_Q
6 ATE_TONEGEN_PRBS_ENABLE_I
7 ATE_TONEGEN_PRBS_ENABLE_Q
8 ATE_CMAC_DC_WRITE_TO_CANCEL
9 ATE_CMAC_DC_ENABLE
10 ATE_CMAC_CORR_ENABLE
11 ATE_CMAC_POWER_ENABLE
12 ATE_CMAC_IQ_ENABLE
13 ATE_CMAC_I2Q2_ENABLE
14 ATE_CMAC_POWER_HPF_ENABLE
15 ATE_RXDAC_CALIBRATE
16 ATE_RBIST_ENABLE
17 ATE_ADC_CLK_INVERT ;-newer revision only
ATH:01C384h - PHY_ANALOG_TX_DC_OFFSET
0-10 ATE_TONEGEN_DC_I
16-26 ATE_TONEGEN_DC_Q
ATH:01C388h - PHY_ANALOG_TX_TONEGEN0
ATH:01C38Ch - PHY_ANALOG_TX_TONEGEN1
ATH:01C390h - PHY_ANALOG_TX_LFTONEGEN0
0-6 ATE_TONEGEN_TONE_FREQ
8-11 ATE_TONEGEN_TONE_A_EXP
16-23 ATE_TONEGEN_TONE_A_MAN
24-30 ATE_TONEGEN_TONE_TAU_K
ATH:01C394h - PHY_ANALOG_TX_LINEAR_RAMP_I
ATH:01C398h - PHY_ANALOG_TX_LINEAR_RAMP_Q
0-10 ATE_TONEGEN_LINRAMP_INIT
12-21 ATE_TONEGEN_LINRAMP_DWELL
24-29 ATE_TONEGEN_LINRAMP_STEP
ATH:01C39Ch - PHY_ANALOG_TX_PRBS_MAG
0-9 ATE_TONEGEN_PRBS_MAGNITUDE_I
16-25 ATE_TONEGEN_PRBS_MAGNITUDE_Q
ATH:01C3A0h - PHY_ANALOG_TX_PRBS_SEED_I
0-30 ATE_TONEGEN_PRBS_SEED
ATH:01C3A4h - PHY_ANALOG_TX_PRBS_SEED_Q
0-30 ATE_TONEGEN_PRBS_SEED
ATH:01C3A8h - PHY_ANALOG_CMAC_DC_CANCEL
0-9 ATE_CMAC_DC_CANCEL_I
16-25 ATE_CMAC_DC_CANCEL_Q
ATH:01C3ACh - PHY_ANALOG_CMAC_DC_OFFSET
0-3 ATE_CMAC_DC_CYCLES
ATH:01C3B0h - PHY_ANALOG_CMAC_CORR
0-4 ATE_CMAC_CORR_CYCLES
8-13 ATE_CMAC_CORR_FREQ
ATH:01C3B4h - PHY_ANALOG_CMAC_POWER
0-3 ATE_CMAC_POWER_CYCLES
ATH:01C3B8h - PHY_ANALOG_CMAC_CROSS_CORR
0-3 ATE_CMAC_IQ_CYCLES
ATH:01C3BCh - PHY_ANALOG_CMAC_I2Q2
0-3 ATE_CMAC_I2Q2_CYCLES
ATH:01C3C0h - PHY_ANALOG_CMAC_POWER_HPF
0-3 ATE_CMAC_POWER_HPF_CYCLES
4-7 ATE_CMAC_POWER_HPF_WAIT
ATH:01C3C4h - PHY_ANALOG_RXDAC_SET1
0-1 ATE_RXDAC_MUX
4 ATE_RXDAC_HI_GAIN
8-13 ATE_RXDAC_CAL_WAIT
16-19 ATE_RXDAC_CAL_MEASURE_TIME
ATH:01C3C8h - PHY_ANALOG_RXDAC_SET2
0-4 ATE_RXDAC_I_HI
8-12 ATE_RXDAC_Q_HI
16-20 ATE_RXDAC_I_LOW
24-28 ATE_RXDAC_Q_LOW
ATH:01C3CCh - PHY_ANALOG_RXDAC_LONG_SHIFT
0-4 ATE_RXDAC_I_STATIC
8-12 ATE_RXDAC_Q_STATIC
ATH:01C3D0h - PHY_ANALOG_CMAC_RESULTS_I
0-31 ATE_CMAC_RESULTS
ATH:01C3D4h - PHY_ANALOG_CMAC_RESULTS_Q
0-31 ATE_CMAC_RESULTS
ATH:01C740h - PHY_ANALOG_PMU1
This register differs in hw4/hw6 (in hw6, bits are renumbered, new OVERRIDE
bits are added, and the SREG_LVLCTR bit is removed):
hw4 hw6 name
0-10 0-3 SPARE ;-unused
11 4 OTP_V25_PWD ;-OTP V25
12 5 PAREGON_MAN ;\PA REG
- 6 PAREGON_OVERRIDE_EN ;/
13 7 OTPREGON_MAN ;\OTP REG
- 8 OTPREGON_OVERRIDE_EN ;/
14 9 DREGON_MAN ;\DREG
- 10 DREGON_OVERRIDE_EN ;/
15 11 DISCONTMODEEN ;\DISCONT MODE
- 12 SWREGDISCONT_OVERRIDE_EN ;/
16 13 SWREGON_MAN ;\
- 14 SWREGON_OVERRIDE_EN ;
17-18 15-16 SWREG_FREQCUR ;
19-21 17-19 SWREG_FREQCAP ; SW REG
- 20 SWREGFREQ_OVERRIDE_EN ;
22-23 21-22 SWREG_LVLCTR ;
- 23 SWREGLVL_OVERRIDE_EN ;/
24-25 - hw4:SREG_LVLCTR ;-SREG ;<---- removed in hw6 (!)
26-27 24-25 DREG_LVLCTR ;\DREG
- 26 DREGLVL_OVERRIDE_EN ;/
28 27 PAREG_XPNP ;\
29-31 28-30 PAREG_LVLCTR ; PA REG
- 31 PAREGLVL_OVERRIDE_EN ;/
ATH:01C744h - PHY_ANALOG_PMU2
0-7 SPARE
8 VBATT_1_3TOATB
9 VBATT_1_2TOATB
10 VBATT_2_3TOATB
11 PWD_BANDGAP_MAN
12 PWD_LFO_MAN
13 VBATT_LT_3P2
14 VBATT_LT_2P8
15 VBATT_GT_4P2
16 hw4: PMU_MAN_OVERRIDE_EN ;\changed/renamed in hw4/hw6
16 hw6: PMU_XPNP_OVERRIDE_EN ;/
17-18 VBATT_GT_LVLCTR
19 SWREGVSSL2ATB
20-21 SWREGVSSL_LVLCTR
22 SWREGVDDH2ATB
23-24 SWREGVDDH_LVLCTR
25-27 SWREG2ATB
28 OTPREG2ATB
29-30 OTPREG_LVLCTR
31 hw4: DREG_LVLCTR_MANOVR_EN ;\changed/renamed in hw4/hw6
31 hw6: OTPREG_LVLCTR_MANOVR_EN ;/
DSi Atheros Wifi - Internal I/O - 020080h - WMAC IRQ Interrupt (hw4/hw6)
------------------------------------------------------------------------
DSi Atheros Wifi - Internal I/O - 020800h - WMAC QCU Queue (hw4/hw6)
--------------------------------------------------------------------
Below "MCIxxx" registers exist on hw2 only. Purpose is unknown. There seems to
be nothing equivalent in hw4. However, hw6 is having several "MCI_xxx"
registers (see WLAN Coex section; unknown if that's related to hw2 MCI stuff).
Below outcommented stuff is found in hw2 source code, maybe it was used in
older hw2 revisions (in case there multiple hw2 revisions), or maybe it was
used in even older pre-hw2 chips, or maybe it's just some experimental stuff
that was never implemented in hardware.
______________ below in hw4.2 and hw6 only (not original hw4) ______________
hw4 does have only a few "B1" registers defined, although it does have a lot of
"B0" registers - which would suggest the presence of corresponding "B1"
registers, but those seem to exist only on hw6.
Maybe the hw4 designed was already aimed at adding "B1" registers in future.
Or maybe the "B1" registers DO EXIST even on hw4, being accessd by using
something like "address of B0 register PLUS some offset", or by using the
so-called "BASEBAND_2" and/or "BASEBAND_3" regions - and without mentioning
that anywhere in hw4 source code?
ATH:034004h - STEREO0_VOLUME
0-4 CHANNEL0
8-12 CHANNEL1
ATH:034008h - STEREO_MASTER_CLOCK
0 MCK_SEL
ATH:03400Ch - STEREO0_TX_SAMPLE_CNT_LSB
ATH:034010h - STEREO0_TX_SAMPLE_CNT_MSB
ATH:034014h - STEREO0_RX_SAMPLE_CNT_LSB
ATH:034018h - STEREO0_RX_SAMPLE_CNT_MSB
0-15 CH0
16-31 CH1
ATH:035000h - CHKSUM_ACC_DMATX_CONTROL0
ATH:035004h - CHKSUM_ACC_DMATX_CONTROL1
ATH:035008h - CHKSUM_ACC_DMATX_CONTROL2
ATH:03500Ch - CHKSUM_ACC_DMATX_CONTROL3
0 TXEN
1 LITTLEENDIAN
ATH:035010h - CHKSUM_ACC_DMATX_DESC0
ATH:035014h - CHKSUM_ACC_DMATX_DESC1
ATH:035018h - CHKSUM_ACC_DMATX_DESC2
ATH:03501Ch - CHKSUM_ACC_DMATX_DESC3
0-31 ADDR
ATH:035020h - CHKSUM_ACC_DMATX_DESC_STATUS
0 UNDERRUN0
1 UNDERRUN1
2 UNDERRUN2
3 UNDERRUN3
4 BUSERROR
5-8 DESC_INTR
16-23 PKTCNT0
24-25 CHAIN_NUM (R)
ATH:035024h - CHKSUM_ACC_DMATX_ARB_CFG
0 RRMODE
8-13 WGT0
14-19 WGT1
20-25 WGT2
26-31 WGT3
ATH:035030h - CHKSUM_ACC_TXST_PKTCNT
0-7 N/A ?
8-15 PKTCNT1 ;8bit each
16-23 PKTCNT2
24-31 PKTCNT3
ATH:035034h - CHKSUM_ACC_DMARX_CONTROL
0 RXEN
1 LITTLEENDIAN
ATH:035038h - CHKSUM_ACC_DMARX_DESC
0-31 ADDR
ATH:03503Ch - CHKSUM_ACC_DMARX_DESC_STATUS
0 OVERFLOW
1 BUSERROR
2 DESC_INTR
16-23 PKTCNT
ATH:035048h - CHKSUM_ACC_ARB_BURST
0-9 MAX_TX
10 INCR16_EN
11 INCR8_EN
16-25 MAX_RX
ATH:035050h - CHKSUM_ACC_RESET_DMA
0 TX
1 RX
ATH:035054h - CHKSUM_CONFIG
0 CHKSUM_SWAP
4-9 TXFIFO_MAX_TH
16-21 TXFIFO_MIN_TH
22-31 SPARE
ATH:038000h - RX_FRAME0
ATH:038008h - RX_FRAME1
0 OWN
1-12 LEN (R)
13-14 SEQ_NUM (R)
ATH:038004h - RX_FRAME_0
ATH:03800Ch - RX_FRAME_1
0-31 ADDR
ATH:038010h - MMAC_INTERRUPT_RAW
ATH:038014h - MMAC_INTERRUPT_EN
0 RX_DONE0
1 RX_CRC_FAIL0
2 ACK_RESP_FAIL0
3 RX_DONE1
4 RX_CRC_FAIL1
5 ACK_RESP_FAIL1
6 RX_ERR_OVERFLOW
7 TX_DONE
8 TX_DONE_ACK_MISSING
9 TX_DONE_ACK_RECEIVED
10 TX_ERROR
ATH:038018h - RX_PARAM1
0-31 VAP_ADDR_L
ATH:03801Ch - RX_PARAM0
0-15 VAP_ADDR_U
16-21 SIFS
22-23 CAPTURE_MODE
24-26 TYPE_FILTER
27 LIVE_MODE
ATH:038020h - TX_COMMAND0
0-11 LEN
12 CRC
13 EXP_ACK
ATH:038024h - TX_COMMAND
0-31 ADDR
ATH:038028h - TX_PARAM
0 ACK_MODE_EN
1-6 ACK_TIMEOUT
7-14 BACKOFF
15 FORCE_ACKF_RSSI
16-23 ACKF_RSSI
ATH:03802Ch - BEACON_PARAM
0-15 INTERVAL
16-27 LEN
28 EN
29 CRC
30 RESET_TS
ATH:038030h - BEACON
0-31 ADDR
ATH:038034h - TSF_L
ATH:038038h - TSF_U
0-31 COUNT
ATH:039000h - FPGA_REG1
2 DCM_RELEASE
4-7 EMUL_RADIO_CLOCK_RATIO
8-9 LONG_SHIFT_CHAIN_OVERRIDE_INDEX
10 ENABLE_LONG_SHIFT_CHAIN_OVERRIDE_INDEX
11-15 LONG_SHIFT_DRIVE_PHASE
16-20 LONG_SHIFT_SAMPLE_PHASE
21-30 SPARE_FPGA_REG1
31 FPGA_SRIF_DELAY
ATH:039004h - FPGA_REG2
0-3 FPGA_PLATFORM_TYPE
4-7 FPGA_IP_RELEASE_VERSION
8-11 FPGA_IP_REVISION
12 FPGA_OWL_PLL_ENABLED
13 FPGA_LOOPBACK_I2C
14-31 FPGA_SPARE
ATH:039008h - FPGA_REG4
0 RADIO_0_TCK
1 RADIO_0_TDI
2 RADIO_0_TMS
3 RADIO_0_TDO
ATH:040000h - INTERRUPT
ATH:040004h - INTERRUPT_MASK
0-7 RX_(0..7)_COMPLETE
8-15 RX_(0..7)_END
16-23 TX_(0..7)_COMPLETE
24-31 TX_(0..7)_END
ATH:040100h - MII0_CNTL
0-1 SELECT
2 MASTER
4-5 SPEED
8-9 RGMII_DELAY
ATH:040200h - MDIO_REG[0..7]
0-15 VALUE
ATH:040220h - MDIO_ISR
0-7 REGS
8-15 MASK
ATH:040804h - GMAC_RX_0_DMA_START
ATH:040C04h - GMAC_TX_0_DMA_START
0 START
4 RESTART
ATH:040C08h - GMAC_TX_0_INTERRUPT_LIMIT
0-3 COUNT
4-15 TIMEOUT
ATH:040808h - GMAC_RX_0_BURST_SIZE
ATH:040C0Ch - GMAC_TX_0_BURST_SIZE
0-1 BURST
ATH:04080Ch - GMAC_RX_0_PKT_OFFSET
0-7 OFFSET
ATH:040810h - GMAC_RX_0_CHECKSUM
0 TCP
1 UDP
ATH:040814h - GMAC_RX_0_DBG_RX
0-3 STATE
ATH:040C10h - GMAC_TX_0_DBG_TX
16-31 FIFO_TOTAL_LEN
0-2 STATE
ATH:040818h - GMAC_RX_0_DBG_RX_CUR_ADDR
ATH:040C14h - GMAC_TX_0_DBG_TX_CUR_ADDR
0-31 ADDR
ATH:04081Ch - GMAC_RX_0_DATA_SWAP
ATH:040C18h - GMAC_TX_0_DATA_SWAP
0 SWAP
1 SWAPD
ATH:054000h - ENDP0
0-7 MAXP
16 STALL
17 HSNAK
20 DSTALL
23 CHGSETUP
ATH:054008h - OUT1ENDP
ATH:054010h - OUT2ENDP
ATH:054018h - OUT3ENDP
ATH:054020h - OUT4ENDP
ATH:054028h - OUT5ENDP
ATH:05400Ch - IN1ENDP
ATH:054014h - IN2ENDP
ATH:05401Ch - IN3ENDP
ATH:054024h - IN4ENDP
ATH:05402Ch - IN5ENDP
0-10 MAXP
18-19 TYPE
20-21 ISOD
22 STALL
23 VAL
24 ISOERR
28 HCSET ;<-- for INxENDP registers only (not OUTxENDP)
ATH:05408Ch - USBMODESTATUS
0 LS
1 FS
2 HS
4 HOST
5 DEVICE
ATH:0541A4h - FNCTRL
0-2 MFR
3-7 FRMNR0
8-13 FRMNR1
16-22 FNADDR
24-31 CLKGATE
ATH:0541BCh - OTGREG
0 OTGIRQ_IDLEIRQ
1 OTGIRQ_SRPDETIRQ
2 OTGIRQ_LOCSOFIRQ
3 OTGIRQ_VBUSERRIRQ
4 OTGIRQ_PERIPHIRQ
8-11 OTGSTATE
16 OTGCTRL_BUSREQ
17 OTGCTRL_ABUSDROP
18 OTGCTRL_ASETBHNPEN
19 OTGCTRL_BHNPEN
20 OTGCTRL_SRPVBUSDETEN
21 OTGCTRL_SRPDATDETEN
23 OTGCTRL_FORCEBCONN
24 OTGSTATUS_BSE0SRP
25 OTGSTATUS_CONN
27 OTGSTATUS_ASESSVAL
28 OTGSTATUS_BSESSEND
29 OTGSTATUS_AVBUSVAL
30 OTGSTATUS_ID
ATH:0541CCh - DMASTART
ATH:0541D0h - DMASTOP
0-15 IN 0..15
16..31 OUT 0..15
ATH:05442Ch - OUT1DMACTRL
ATH:05444Ch - OUT2DMACTRL
ATH:05446Ch - OUT3DMACTRL
ATH:05448Ch - OUT4DMACTRL
ATH:0544ACh - OUT5DMACTRL
2-15 RINGSIZ
16 ENDIAN
17 DMASTOP
18 DMASTART
20 DMATUNLIM
21 DMANINCR
22 DMARING
25 HLOCK
26-27 HSIZE
28-31 HRPROT
ATH:0D8000h - USB_IP_BASE
?
ATH:055000h - MBOX_FIFO
0-19 DATA
ATH:055004h - MBOX_FIFO_STATUS
0 FULL
2 EMPTY
ATH:055008h - MBOX_DMA_POLICY
0 RX_ORDER
1 RX_QUANTUM
2 TX_ORDER
3 TX_QUANTUM
4-7 TX_FIFO_THRESH0
ATH:05500Ch - MBOX0_DMA_RX_DESCRIPTOR_BASE
ATH:055014h - MBOX0_DMA_TX_DESCRIPTOR_BASE
2-27 ADDRESS
ATH:055010h - MBOX0_DMA_RX_CONTROL
ATH:055018h - MBOX0_DMA_TX_CONTROL
0 STOP
1 START
2 RESUME
ATH:05501Ch - MBOX_FRAME
0 RX_SOM
2 RX_EOM
ATH:055020h - FIFO_TIMEOUT
0-7 VALUE
8 ENABLE
ATH:055024h - MBOX_INT_STATUS
ATH:055028h - MBOX_INT_ENABLE
0 RX_NOT_FULL
2 TX_NOT_EMPTY
4 RX_UNDERFLOW
5 TX_OVERFLOW
6 TX_DMA_COMPLETE
8 TX_DMA_EOM_COMPLETE
10 RX_DMA_COMPLETE
ATH:05502Ch - MBOX_FIFO_RESET
0 TX_INIT
2 RX_INIT
ATH:055030h - MBOX_DEBUG_CHAIN0
ATH:055034h - MBOX_DEBUG_CHAIN1
0-31 ADDRESS
ATH:055038h - MBOX_DEBUG_CHAIN0_SIGNALS
ATH:05503Ch - MBOX_DEBUG_CHAIN1_SIGNALS
0-31 COLLECTION
ATH:xxx430h - BB_WR_MASK_0
ATH:xxx434h - BB_WR_MASK_1
ATH:xxx438h - BB_WR_MASK_2
ATH:xxx43Ch - BB_WR_MASK_3
ATH:xxx448h - BB_RD_MASK_0
ATH:xxx44Ch - BB_RD_MASK_1
ATH:xxx450h - BB_RD_MASK_2
ATH:xxx454h - BB_RD_MASK_3
0-10 REG (11bit)
ATH:xxx440h - RF_WR_MASK_0
ATH:xxx444h - RF_WR_MASK_1
ATH:xxx458h - RF_RD_MASK_0
ATH:xxx45Ch - RF_RD_MASK_1
0-8 REG (9bit)
ATH:xxx000h - RAM1[0..255]
0-7 DATA (8bit)
8-31 -
ATH:xxx800h - RAM2[0..127]
0-6 DATA (7bit)
7-31 -
ATH:xxx000h - PHY_CTRL0
0-2 PLL_ICP
3-5 PLL_RS
6-14 PLL_DIV
15-17 PLL_MOD
18 PLL_OVERIDE
19 TEST_SPEED_SELECT
20 RX_PATTERN_EN
21 TX_PATTERN_EN
22 ANA_LOOPBACK_EN
23 DIG_LOOPBACK_EN
24-31 LOOPBACK_ERR_CNT (R)
ATH:xxx004h - PHY_CTRL1
0-1 RX_FILBW_SEL
2 RX_FORCERXON
3 RX_BYPASSEQ
4 RX_LOWR_PDET
5-6 RX_SELIR_100M
7 RX_SELVREF0P6
8 RX_SELVREF0P25
9-11 RX_RSVD
12 NO_PLL_PWD
13 FORCE_SUSPEND
18-19 TX_PATTERN_SEL
20 USE_PLL_LOCKDETECT
21-22 USE_PLL_LOCK_DLY_SEL
23-25 CLKOBS_SEL
26 ENABLE_REFCLK_GATE
27 DISABLE_CLK_GATING
31 PLL_OBS_MODE_N
ATH:xxx008h - PHY_CTRL2
0 HSTXBIAS_PS_EN
1 HSRXPHASE_PS_EN
2-7 PWD_IPLL
8-13 PWD_ISP
20 TX_CAL_EN
21 TX_CAL_SEL
22-25 TX_MAN_CAL
26 TX_LCKDET_OVR
27-30 TX_RSVD
31 PWD_EXTBIAS
ATH:xxx00Ch - PHY_CTRL3
0-18 PWD_ITX
21 TX_DISABLE_SHORT_DET
22-24 TX_SELTEST
25 TX_STARTCAL
ATH:xxx010h - PHY_CTRL4
0-11 PWD_IRX
ATH:xxx014h - PHY_CTRL5
0-6 TX_BIAS_DELAY
7-12 EB_WATERMARK
13 FORCE_IDDQ
14 FORCE_TEST_J
15 FORCE_TEST_K
16 FORCE_TEST_SE0_NAK
17 TEST_JK_OVERRIDE
18-19 XCVR_SEL
20 TERM_SEL
21 SUSPEND_N
22 DP_PULLDOWN
23 DM_PULLDOWN
24 HOST_DISCON_FIX_ON
25 HOST_DISCON_DETECT_ON
26-28 HOST_DISCON_SAMPLE_WIDTH
ATH:xxx018h - PHY_CTRL6
0 AVALID
1 BVALID
2 VBUSVALID
3 SESSEND
4 IDDIG
Observe that HP#SP could be used as Output (output/low will probably cause the
DSi to believe that there is no headphone connected, thus forcing the internal
speakers to be enabled; possibly with/without disabling the headphones?).
Serial/Barcode
The barcode is found on a sticker on the bottom of console (and on an identical
sticker underneath of the battery). It's also stored as ASCII string in
HWINFO_S.dat file, and at 2FFFD71h in RAM.
The serial/barcode consists of 2-3 letters, followed by 8 digits, followed by a
checksum digit.
The first letter indicates the console model:
DSi T (or V for devunits)
DSi XL/LL W (or unknown for devunits)
3DS C (or E for devunits)
3DS XL/LL S (or R for devunits)
2DS A (or P for devunits)
New 3DS Y (or Yxx00 for devunits)
New 3DS XL/LL Q (or Qxx00 for devunits)
New 2DS XL/LL N (or Nxx01 for devunits)
The next 1-2 letter(s) indicate the region:
JPN Japan JF,JH,JM
USA North America W
USA Middle East, Southeast Asia S
EUR Europe EF,EH,EM
AUS Australia (for 3DS: part of EUR) AG,AH
CHN China (iQue) CF,CH,CM
KOR South Korea KF,KH,KM
The checksum can be calculated across 1st-8th digit (and ignoring the leading
letters):
9th = (250 - (1st+3rd+5th+7th) - 3*(2nd+4th+6th+8th)) mod 10
Unknown if the barcode is internally used for any purposes (such like
encryption, or network identification).
dev.kp
This file contains another "TWxxxxxxxx" ID (with "xxxxxxxx" being a 32bit
lowercase hex number), this 32bit Console ID is also used in .tik files (except
in tickets for free system titles).
Wifi MAC Address - Found in Main RAM, Wifi FLASH, and Wifi EEPROM
The MAC is a unique 48bit number needed for Wifi communications. The MAC is
stored in SPI bus Wifi FLASH, and it's also stored at 2FFFCF4h in RAM. The same
MAC value is also stored in I2C bus Wifi EEPROM. The MAC can be also viewed in
Firmware (see System Settings, Internet, Options, System Information). Common
values for DSi are:
00 22 4C xx xx xx ;seen in DSi XL
00 23 CC xx xx xx ;seen in DSi
00 24 1E xx xx xx ;seen in DSi
00 27 09 xx xx xx ;seen in DSi
The value isn't used for eMMC encryption (the eMMC is still accessible when
swapping the Wifi daughterboard). However, the MAC value is included in game
".bin" files stored on SD card (unknown if that is causing any issues when
loading those games on a console with swapped Wifi daughterboard).
Nintendo WFC ID
This is some unknown purpose value stored in Wifi FLASH. The value can be
viewed in Firmware (see System Settings, Internet, Options, System
Information). The firmware does only show the lower 43bit of the value, in
decimal format, multiplied by 1000, whilst the actual WFC in FLASH seems to be
about 14 bytes (112bit). The firmware does also allow to "delete" and
"transfer" the "WFC Configuration" (whatever that means).
Flipnote Studio ID
This ID consists of a 16-digit HEX number (can be viewed by clicking the "tool"
symbol in upper right of Flipnote's main menu).
The first 8-digits have unknown meaning. The last 8-digits are same as the last
8-digits of the wifi MAC address.
40021A0h ... second NDS cart slot, DSi prototype relict (?)
ARM9: Can be set to 00000000h or 0000E043h
ARM7: Can be set to 00000000h or 0000E043h
40021A4h ... second NDS cart slot, DSi prototype relict (?)
ARM9: Can be set to 20000000h or FF7F7FFFh
ARM7: Can be set to 00000000h or FF7F7FFFh
Can be all-zero on arm7, uh, or is that due to port being disabled somehow?
DSi Notes
---------
DSi Detection
Cartridges are using the same executable for NDS and DSi mode, the executable
must thus detect whether it is running on a NDS console or DSi console. At ARM9
this is usually done as follows:
if ([4004000h] AND 03h)=01h then DSi_mode else NDS_mode
On ARM7 side, the executables are attempting to do the same thing, but they are
(maybe accidently) skipping the detection depending on a 2nd I/O port:
;Caution: Below detection won't work with DSi exploits (because they are
; usually having the ARM7 SCFG registers disabled - it would be thus better
; to do the dection only on ARM9 side as described above, and then forward
; the result to ARM7 side).
if ([4004008h] AND 80000000h)=0 then skip_detection_and_assume_NDS_mode
else if ([4004000h] AND 03h)=01h then DSi_mode else NDS_mode
In DSi_mode, the game can use additional hardware features, and it must be also
aware of some changed BIOS SWI functions.
In NDS_mode, the game can use only old hardware features, in case of
DSi-exclusive games: The cartridge must contain a small NDS function that
displays a message saying that the game will work only on DSi consoles.
DSi Executables
The boot executables & entrypoints are always defined in the ARM9/ARM7 entries
in cartridge header, regardless of whether the game is running on a NDS console
or DSi console. The ARM9/ARM7 executables are thus restricted to max 2MByte
size (for not violating the NDS memory limit). The ARM9i/ARM7i entries are
allowing to load additional code or data, presumably to addresses (almost)
anywhere within the DSi's 16MByte memory space. Of course, if you want to use
separate executables for NDS and DSi mode, then you can put some small
bootstrap loader into the ARM9/ARM7 area, which will then load the actual main
executables.
DSi Exploits
------------
DSi executables require RSA signatures (signed with Nintendo's private key),
which is making it impossible to run any unlicensed/homebrew code, except via
exploits (eg. modified .sav data for tweaking licensed games into booting
unlicensed code).
Ready for use DSiware Exploits (crashing system titles from SD card)
There are two exploitable titles that can be exploited via simple SD card files
(without needing hardmod or downgrading): DSi Camera and Flipnote
DSi Camera (aka Memory Pit exploit):
The DSI Camera is installed in all regions, and people can't install it, so
this exploit should work for everyone. The original Memory Pit exploit (from
shutterbug2000) worked only on unspecified firmwares, but there is newer Memory
Pit (from zoogie) the works in all regions and firmware versions.
Usage: Replace the SD:\private\ds\app\484E494A\pit.bin file, then go to Camera
SD Card Album.
Flipnote:
Flipnote exists for US+EUR+AUS+JAP regions (not CHN or KOR), and it has been
available for free (either pre-installed, or free download from DSi shop), so
many people should have that title (though, surprisingly, quite some people
don't have it because they had never downloaded it for free when the DSi shop
was still online; and some might have deleted it).
Anyways, if you have flipnote: Use the "Flipnote Lenny (or whatever it is
called)" exploit, working for all four flipnote regions (US+EUR+AUS+JAP), the
download URL seems to be this weird link:
https://davejmurphy.com/%25CD%25A1-%25CD%259C%25CA%2596-%25CD%25A1/
downloading seems to require buying a newer PC, and a browser with strong https
support and youtube playing capabilities for watching the installation guide
(unless the download contains instructions in regular .txt format).
Other DSiware Exploits (DSi shop downloads crashed with .sav files)
Installing DSiware exploits requires downgrading the firmware (and in case of
sudoku: also downgrading the game). Downgrading can be done by soldering a few
wires to the eMMC chip and then using utilities like "TWLTool". Most
recommended title would be Sudoku (it's cheapest and doesn't require any menu
navigation; apart from getting through a "touch to start" screen).
Region Price Title
US,EU/AU $2 Sudoku (Electronic Arts) (updated version in DSi shop)
US,EU/AU $5 Fieldrunners (original version still in DSi shop)
US,EU/AU $5 Guitar Rock Tour ("grtpwn") (no longer in DSi shop)
US,EU/AU,JP $8 Legends of Exidia (original version still in DSi shop)
US,...? Free Zelda 4 Swords (no longer in DSi shop)
Once when the game+exploit are installed, the exploits will boot a file called
"boot.nds" from SD card (eg. rename dslink to that name for wifi boot).
The DSi shop closed in 2017, so one can no longer legally buy DSiware. One
could install pirate copies with tweaked .tik files for exploitable games, but
it would be pointless (doing so would require a hardmod, and if you have a
hardmod, then you could as well install unlaunch directly).
Note: Originally, dsiwarehax were installed via SD card without soldering, but
that works only when having downloaded the exploitable games prior to release
of firmware 1.4.2.
As of 2017, the DSi shop is closing (one cannot add new DSi points to the shop
account, but can still use old DSi points that are already on the account for a
few months).
Note: Buying DSiware was quite expensive (ie. buying a $15 wii/dsi point card
worked, but you couldn't resell or reuse the remaining dsi points on other
consoles).
DSi Flashcarts
The majority of DSi Flashcarts are "DSi compatible", which does barely mean
that they can boot DS games on DSi consoles in DS mode (but cannot run DSi
software in DSi mode). The only flashcart with "DSi mode" support is/was
CycloDS iEvolution (based on Cooking Coach exploit, without support for newer
firmwares).
Essentially, flashcarts aren't of too much use: Booting from built-in SD Card
slot would also work without flashcarts, and Wifi boot would be more
comfortable anyways.
DSi Regions
-----------
Note that Nintendo might expand those regions in newer european firmware
versions.
The Country option implies localized Age Ratings in Parental Controls (eg. "USK
ab 18" for germany, or "18'TM" for france/finland). Changing the Country will
require to re-agree EULA crap.
The "Language" option affects the Firmware GUI, and the game title (from
Icon/Title structure). Some games are also (trying to) adopt the Firmware's
language setting for choosing the in-game language; but that can fail badly if
the game doesn't support the selected language.
3DS Reference
-------------
3DS Summary
--> 3DS Memory and I/O Map
Misc
--> 3DS eMMC and MCU Images
--> 3DS Component Lists
--> 3DS Testpoints
--> 3DS Connector Pinouts
--> 3DS Chipset Pinouts
Operating System
http://forums.nesdev.com/viewtopic.php?f=23&t=18490&p=242531#p242456
http://www.3dbrew.org/wiki/Services
http://www.3dbrew.org/wiki/Services_API
Credits
http://www.3dbrew.org/wiki/IO_Registers
3DS Memory and I/O Map
----------------------
ARM9-only Registers
Physaddr Old3DS A9/A11 Category
10000000h Yes A9 CONFIG9 Registers
10001000h Yes A9 IRQ Registers
10002000h Yes A9 NDMA Registers DMA (alike DSi's NDMA)
10003000h Yes A9 TIMER Registers Timers (alike GBA/NDS/DSi)
10004000h Yes A9 CTRCARD Registers ROM cart in 3DS mode
10005000h A9 CTRCARD? 2nd ROM cart slot?
10006000h Yes A9 SDMMC Registers For eMMC and SD Card slot
10007000h Yes A9 Alternate SD/MMC Slot controller ;CFG9_SDMMC_CTL
10008000h Yes A9 PXI Registers aka IPC
10009000h Yes A9 AES Registers Crypto
1000A000h Yes A9 SHA Registers Crypto
1000B000h Yes A9 RSA Registers Crypto
1000C000h Yes A9 XDMA Registers DMA
1000D000h Yes A9 SPI_CARD Registers Savedata in ROM carts
10010000h Yes A9 CONFIG Registers More CONFIG9 registers
10011000h Yes A9 PRNG Registers Pseudo Random Generator
10012000h Yes A9 OTP Registers Console IDs
10018000h Yes A9 ARM7 Registers GBA/NDS/DSi mode config
ARM11/ARM9 Registers
Below registers can be accessed by both ARM11 and ARM9. However, most of them
are working best on ARM11 side (because IRQ and DMA startup modes are
implemented on ARM11 side only; and, in some cases, even FIFOs are in a
separate ARM11-only area at 10300000h and up).
One exception is NTRCARD (this does have IRQ/DMA on both ARM9 and ARM11 side).
10100000h Yes A11/A9 Alternate SD/MMC Slot controller ;CFG9_SDMMC_CTL
10101000h Yes A11/A9 HASH Registers Crypto (same as SHA)
10102000h Yes A11/A9 Y2R_0 Registers First YUV-to-RGBA
10103000h Yes A11/A9 CSND Registers Sound channels and capture
10110000h Yes A11/A9 LGYFB_0 Legacy GBA/NDS Video
10111000h Yes A11/A9 LGYFB_1 Legacy GBA/NDS Video
10120000h Yes A11/A9 Camera Registers Camera Bus 0 (DSi cameras)
10121000h Yes A11/A9 Camera Registers Camera Bus 1 (left-eye)
10122000h Yes A11/A9 WIFI Registers SDIO Wifi
10123000h Yes A11/A9 ? SDIO? ;uh, actually data.abt
10130000h No A11/A9 L2B_0 New3DS: First RGB-to-RGBA
10131000h No A11/A9 L2B_1 New3DS: Second RGB-to-RGBA
10132000h No A11/A9 Y2R_1 New3DS: Second YUV-to-RGBA
10140000h Yes A11/A9 CONFIG11 Registers
10141000h Yes A11/A9 CONFIG11 Registers
10142000h Yes A11/A9 SPI Registers SPI Bus1 (Tsc)
10143000h Yes A11/A9 SPI Registers SPI Bus2 (unused)
10144000h Yes A11/A9 I2C Registers I2C Bus1 (for 3DS devices)
10145000h Yes A11/A9 CODEC Registers ? aka I2S registers
10146000h Yes A11/A9 HID Registers Keypad
10147000h Yes A11/A9 GPIO Registers
10148000h Yes A11/A9 I2C Registers I2C Bus2 (for 3DS gimmicks)
10160000h Yes A11/A9 SPI Registers SPI Bus0 (Pwrman,WifiFlash,Tsc)
10161000h Yes A11/A9 I2C Registers I2C Bus0 (for DSi devices)
10162000h Yes A11/A9 MIC Registers Microphone
10163000h Yes A11/A9 PXI Registers aka IPC
10164000h Yes A9/A11 NTRCARD Registers ROM Cart in NDS/DSi mode
10165000h Yes A11/A9 MP Registers NDS-Wifi WIFIWAITCNT(10165206h)
10170000h Yes A11/A9 MP Registers NDS-Wifi WS0 Area (8000h bytes)
10178000h Yes A11/A9 MP Registers NDS-Wifi WS1 Area (8000h bytes)
10180000h (end of above area)
ARM11-only Registers
10200000h Yes A11 CDMA DMA
10201000h Yes A11 FCRAM Registers FCRAM Control
10202000h Yes A11 LCD Registers LCD
10203000h Yes A11 DSP Registers Teak DSP (if enabled)
10204000h No A11 UNKNOWN New3DS: ?
10205000h ? - N/A ? ?
10206000h No A11 CDMA New3DS: DMA
10207000h No A11 MVD Registers New3DS: Movie Decoder or so?
1020F000h Yes A11 AXI ?
10300000h Yes A11 FIFO? debug? Maybe debug wifi FIFOs or so?
10301000h Yes A11 FIFO HASH (SHA) contains FIFO
10302000h Yes A11 FIFO Y2R_0
10310000h Yes A11 FIFO LGYFB_0
10311000h Yes A11 FIFO LGYFB_1
10320000h Yes A11 FIFO Camera Bus 0 (20h-word window FIFO)
10321000h Yes A11 FIFO Camera Bus 1 (20h-word window FIFO)
10322000h Yes A11 FIFO? wifi?? Maybe contains DATA32 FIFOs or so?
10323000h ? ? data abort (maybe SDIO FIFO for 10123000h, if any)
10330000h No A11 FIFO L2B_0 New3DS: L2B_0 FIFO (empty=data_abt)
10331000h No A11 FIFO L2B_1 New3DS: L2B_1 FIFO (empty=data_abt)
10332000h No A11 FIFO MVD Y2R_1 New3DS: MVD Y2R FIFO
10400000h Yes A11 GPU External Registers
10401000h Yes A11 GPU Internal Registers
17E00000h 100h A11 MPCore SCU (Snoop Control Unit)
17E00100h 100h A11 MPCore CPU Interrupt Interface
17E00200h 100h A11 MPCore CPU0 Interrupt Interface ;\
17E00300h 100h A11 MPCore CPU1 Interrupt Interface ; (aliased for
17E00400h 100h A11 MPCore CPU2 Interrupt Interface ; debug purposes)
17E00500h 100h A11 MPCore CPU3 Interrupt Interface ;/
17E00600h 100h A11 MPCore CPU Timer and Watchdog
17E00700h 100h A11 MPCore CPU0 Timer and Watchdog ;\
17E00800h 100h A11 MPCore CPU1 Timer and Watchdog ; (aliased, too?)
17E00900h 100h A11 MPCore CPU2 Timer and Watchdog ; <-- N/A in 3DS?
17E00A00h 100h A11 MPCore CPU3 Timer and Watchdog ;/ <-- N/A in 3DS?
17E00B00h 500h A11 MPCore Reserved (access causes a DECERR abort)
17E01000h 1000h A11 MPCore Global Interrupt Distributor
17E10000h No A11 New3DS: L2C-310 Level 2 Cache Controller
IO registers starting at physical address 10200000h are not accessible from the
ARM9 (which includes all LCD/GPU registers). It seems IO registers below
physical address 10100000h are not accessible from the ARM11 bus (=trigger data
abort, as so on all unused 1000h-byte areas).
ARM11 kernel virtual address mappings for these registers varies for different
builds. For ARM11 user mode applications you have:
physaddr = virtaddr-1EC00000h+10100000h
That is:
Physical Virtual
101xxxxxh 1ECxxxxxh
102xxxxxh 1EDxxxxxh
SD/MMC Registers
10006000h A9 Standard controller for SD/MMC Slot and internal eMMC
10006200h A9 mirrors of above (each 200h bytes)
10007000h A9 Alternate SD/MMC Slot controller (see CFG9_SDMMC_CTL.8/9)
10007200h A9 mirrors of above (each 200h bytes)
10100000h A11/A9 Alternate SD/MMC Slot controller (see CFG9_SDMMC_CTL.8/9)
10122000h A11/A9 SDIO Wifi controller
10123000h A11/A9 Unknown, reportedly SDIO? (actually just data abort?)
10300000h A11 DATA32 FIFO for registers at 10100000h (Alternate SD/MMC)
10322000h A11 DATA32 FIFO for registers at 10122000h (SDIO Wifi)
10323000h A11 DATA32 FIFO for registers at 10123000h (Unknown)
These registers are used to access the system NAND and the inserted SD card.
Both devices use the same interface.
HCLK of the SDMMC controller is 67.027964 MHz (double of the DSi HCLK).
Unknown if eMMC and Wifi are fast enough to support HCLK/2 on 3DS.
Standard SD cards may require HCLK/4 on 3DS (unless the card was detected to
support HCLK/2; don't know if it requires further card initialization to enable
fast mode?).
--> DSi SD/MMC Protocol and I/O Ports
--> DSi SD/MMC Filesystem
--> DSi Atheros Wifi SDIO Interface
--> DSi Atheros Wifi Internal Hardware
See also: CFG9_SDMMC_CTL
DATA FIFOs
The ARM9 controllers (10006000h/10007000h) have DATA32 FIFO at base+10Ch.
The ARM11 controllers (10100000h/10122000h/10123000h) have DATA32 FIFO at
base+200000h (the ARM11 controllers can be also accessed from ARM9 side, but
the DATA32 FIFOs (and DRQs/IRQs) are on ARM11 side only; so ARM9 could only use
DATA16 FIFOs and polling in place of DRQs/IRQs).
IRQ_STAT
3 SD card removal flag (Set to 1 when SD card is removed)
4 SD card insertion flag (Set to 1 when SD card is inserted)
5 SD card insertion status (0=Missing, 1=Inserted) SIGSTATE
SD card insertion status
Assertion happens around 250 ms after SD card insertion and/or enabling the
EMMC hardware (delay could possibly be due to an SD bus timeout?).
PXI Registers
Address Width Old3DS Name Used by
10008000h 4 Yes PXI_SYNC9 Boot9, Process9 ;-SYNC
10008004h 2 Yes PXI_CNT9 Boot9, Process9 ;\
10008008h 4 Yes PXI_SEND9 ; FIFO
1000800Ch 4 Yes PXI_RECV9 ;/
10163000h 4 Yes PXI_SYNC11 Boot11 ;-SYNC
10163004h 2 Yes PXI_CNT11 Boot11 ;\
10163008h 4 Yes PXI_SEND11 ; FIFO
1016300Ch 4 Yes PXI_RECV11 ;/
The PXI registers are similar to those on DS. Uh, aka what is known as IPC.
But, except, SYNC is 8bit (instead 4bit)!
The FIFO registers seem to be exactly same as on NDS.
ARM11-to-ARM11 Messages
ARM11 cores can use the Software Interrupt Register, Port 17E01F00h (and data
in AXI memory or other RAM locations) to communicate with each other.
Other Inputs
Circle Pad: Connected to Touchscreen/Sound controller
Power/Home buttons: see I2C MCU
Wifi button: see I2C MCU (older 3DS only)
Volume/3D Sliders: see I2C MCU
Accelerometer: see I2C MCU (also includes pedometer step counter)
Gyroscope: see I2C Gyroscope
Hinge/Shell: see GPIO (and/or reportedly also I2C MCU)
DebugPad: See I2C (whatever that is)
MIC, Cameras, IR, QTM, Charge, SD slot, ROM slot
Old3DS: NFC reader/writer (external adaptor, instead of New3DS built-in)
Old3DS: Circle Pad Pro (2nd Circle Pad and R/ZL/ZR buttons, on IR port)
New3DS: C-stick and ZL/ZR: see I2C (instead of Old3DS's circle pad pro)
New3DS: NFC built-in (instead of Old3DS's external adaptor)
New3DS: Head-tracking (whatever that is, probably just camera with IR-LED..?)
New3DS: Invisible camera IR-LED (unknown how to control/test that)
1020B0DCh - ?
GPIO Registers
10147000h 2 GPIO_DATA0 IN ;GPIO services bitmask 7h
10147010h 4x1 GPIO_DATA1 IN/OUT ;GPIO services bitmask 18h
10147014h 2 GPIO_DATA2 OUT ;GPIO services bitmask 20h
10147020h 4x2 GPIO_DATA3 IN/OUT ;GPIO services bitmask 3FFC0h
10147028h 2 GPIO_DATA4_WIFI OUT ;GPIO services bitmask 40000h
10147100h .. Legacy RTC (for RTC emulation in NDS/DSi mode)
10147100h - RTC_CNT
0 Latch STAT1 (0=No change, 1=Apply) (W)
1 Latch STAT2 (0=No change, 1=Apply) (W)
2 Latch CLKADJ (0=No change, 1=Apply) (W)
3 Latch FREE (0=No change, 1=Apply) (W)
4 Latch TIME (0=No change, 1=Apply) (W)
5 Latch ALRMTIM1 (0=No change, 1=Apply) (W)
6 Latch ALRMTIM2 (0=No change, 1=Apply) (W)
7 Latch COUNT (0=No change, 1=Apply) (W)
8 Latch FOUT1 (0=No change, 1=Apply) (W)
9 Latch FOUT2 (0=No change, 1=Apply) (W)
10 Latch ALRMDAT1 (0=No change, 1=Apply) (W)
11 Latch ALRMDAT2 (0=No change, 1=Apply) (W)
12 ARM7 Busy? This may be chipselect (R)
13 ARM7 write command received? (writing 1 clears it seems) (R/ack)
14 ARM7 read command received? (writing 1 clears it seems) (R/ack)
15 DS SIO SI pin (rtc irq pin) (R/W)
Bit0-11 are used to forward the settings from 10147110h-10147166h to the actual
NDS RTC registers.
Unknown why RTC IRQ pin is write-able, maybe ARM11 must manually trigger it?
But if the ALARM registers are write-only then ARM11 couldn't know their
current value (except, by assuming that the written value wasn't changed from
NDS side).
Notes
When AES_CNT.bit31 is set, then AES_CNT essentially becomes locked and doesn't
change when written to. However if AES_CNT.bit26 is "set", keyslot-selection is
cued to be handled when AES_CNT.bit31 is cleared.
Clearing AES_CNT.bit31 while the AES engine is doing crypto will result in the
AES engine stopping crypto, once it finishes processing the current block.
10009040h/10009070h/100090A0h/100090D0h - AES_KEY0/1/2/3
These registers are the same as they were on TWL, and are likely preserved for
compatibility reasons. The keyslot is updated immediately after *any*
data(u8/u32/...) is written here, which was used on DSi to break the
key-generator.
SHA Registers
1000A000h 4 ARM9 SHA_CNT ;\
1000A004h 4 ARM9 SHA_BLKCNT ; for ARM9
1000A040h 20h ARM9 SHA_HASH ;
1000A080h 40h ARM9 SHA_FIFO ;/
10101000h 4 ARM11/ARM9 SHA_CNT ;\for ARM11 (some registers
10101004h 4 ARM11/ARM9 SHA_BLKCNT ; can be also accessed by ARM9,
10101040h 20h ARM11/ARM9 SHA_HASH ; but FIFO and DMA DRQs are
10301000h 40h ARM11 SHA_FIFO ;/working for ARM11 only)
Blurb
Writing to RSA_MOD does not change the exponent written with RSA_EXPFIFO. An
attack based on the Pohlig-Hellman algorithm exists to "read" the contents of
RSA_EXPFIFO as a result (see 3DS System Flaws).
RSA Overview
The RSA module is essentially a hardware-accelerated modular exponentiation
engine. It is specially optimized for RSA applications, so its behavior can be
incoherent when RSA's invariants are broken.
The PKCS (Public-Key Cryptography Standards) message padding must be manually
checked by software, as hardware will only do raw RSA operations.
OTP Registers
10012000h 100h OTP_ENCRYPTED - Encrypted 3DS OTP (R)
10012100h 8 OTP_TWLMODE - DSi OTP Console ID (R/W)
Access to this region is disabled once the ARM9 writes 02h to CFG9_SYSPROT9.
Decrypted OTP
000h 90h Copied into ITCM. The encrypted version of this is what
New3DS-arm9loader hashes for key-generation.
000h 4 Always DEADB00Fh
004h 4 DeviceId (aka Console ID, used in tickets)
008h 10h Fall-back keyY used for movable.sed keyY when
movable.sed doesn't exist in NAND (the last(???) two words
here are used on retail for generating console-unique TWL
keydata/etc).
This is also used for "LocalFriendCodeSeed", etc.
018h 1 CTCert byte order? (usually 05h)
019h 1 CTCert issuer type:
zero = retail ("Nintendo CA - G3_NintendoCTR2prod")
non-zero = dev ("Nintendo CA - G3_NintendoCTR2dev")
01Ah 6 Manufacturing date (year-1900, month, day, hour, minute, second)
020h 4 CTCert ECDSA exponent (byte-swapped when OTP[018h]>=5)
024h 2 Zero?
026h 1Eh CTCert ECDSA private key
044h 3Ch CTCert ECDSA signature
080h 10h Zerofilled
090h 1Ch Seed 1 for AES keys ;<-- used for console-unique AES keys
0ACh 1Ch Seed 2 for AES keys ;\
0C8h 1Ch Seed 3 for AES keys ; not actually used ;\overlaps SHA256
0E4h 1Ch Seed 4 for AES keys ;/ ;/(see below)
0E0h 20h SHA256 hash across [000h..0DFh]
OTP Blurp
After decryption, the first 90h-bytes of plaintext are copied to ITCM+3800h at
01FFB800h aka 07FFB800h if hash verification passes.
On development units (UNITINFO != 0) ARM9 uses the first 8-bytes from 10012000h
for the TWL Console ID. This region doesn't seem to be used by NATIVE_FIRM on
retail at all, besides New3DS key-generation in the ARM9-loader.
Random notes
After writing to a keyslot, the keyslot must be selected again (write
AES_KEYSEL + set AES_CNT bit26), even when writing to the same keyslot. Writing
the last word to a key FIFO immediately after selecting a keyslot will not
affect the keyslot keydata that gets used at that time, the new keydata will
not get used until the keyslot gets selected again.
Writing to the key FIFOs with byte writes results in the AES engine converting
the byte to a word (word=byte*01010101h). The result is the same regardless of
which FIFO register byte was written to.
The key FIFOs can be written simultaneously. For example, executing the
following will result in the keyX and keyY being set to all-zero (unknown for
normalkey): memset(0x10009100, 0, 0x100); uh, does that mean there are mirrors
at 1000910Ch and up?
Each key FIFO has a 10h-byte tmp-buffer for storing the words written to that
FIFO. Once the last word is written to a key FIFO, the filled tmp-buffer is
then written to the key-data for the keyslot selected by AES_KEYCNT at the time
the last word was written.
Misc keys:
key_y.05h = 4D,80,4F,4E,99,90,19,46,13,A2,04,AC,58,44,60,BE ;by New3DS FIRM
key_y.30h = movable.sed[110h..11Fh]
key_y.34h = movable.sed[110h..11Fh]
key_y.3Ah = movable.sed[110h..11Fh]
NCCH retail keys:
key_x.25h = CE,E7,D8,AB,30,C0,0D,AE,85,0E,F5,E3,82,AC,5A,F3 ;NCCH firm 7.0
key_x.18h = 82,E9,C9,BE,BF,B8,BD,B8,75,EC,C0,A0,7D,47,43,74 ;NCCH firm 9.3
key_x.1Bh = 45,ad,04,95,39,92,c7,c8,93,72,4a,9a,7b,ce,61,82 ;NCCH firm 9.6
NCCH debug keys:
fix_sys = 52,7C,E6,30,A9,CA,30,5F,36,96,F3,CD,E9,54,19,4B ;fixed system key
fix_zero = 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ;fixed zero key
key_x.25h = 81,90,7A,4B,6F,1B,47,32,3A,67,79,74,CE,4A,D7,1B ;NCCH firm 7.0
key_x.18h = 30,4B,F1,46,83,72,EE,64,11,5E,BD,40,93,D8,42,76 ;NCCH firm 9.3
key_x.1Bh = 6C,8B,29,44,A0,72,60,35,F9,41,DF,C0,18,52,4F,B6 ;NCCH firm 9.6
DSi keys (in little endian):
OTP_TWLMODE = decrypted_otp+08h..0Fh xor 08C267B7B358A6AFh or 80000000h
key_x.03h[0..3]: OTP_TWLMODE[0..3]
key_x.03h[4..B]: "NINTENDO" ;<-- this unlike as on real DSi
key_x.03h[C..F]: OTP_TWLMODE[4..7]
key_y.03h[0..F]: 0AB9DC76h,BD4DC4D3h,202DDD1Dh,E1A00005h
Note: DSi-keys can be set by 3DS/ARM9, but the 3DS-to-DSi mode switch does
reset all AES KEY/IV registers to zero, so one must (re-)initialize them
via DSi/ARM7 after switching to DSi-mode.
sighax is a set of fake RSA signatures which are causing the bootrom to always
pass RSA checks.
How it works
derrek's sighax relies on some bugs in the bootrom RSA signature verification.
RSA doesn't throw errors when decrypting a wrong signature with wrong key
(instead, it does just output "random" gibberish). The decrypted signature
should normally consist of leading FFh-padding bytes, a header, and a SHA
checksum.
However, the 3DS bootrom doesn't insist on the padding bytes, and it does
ignore most of the header bytes. Finally, it does allow the header size to be
as large as occupying the whole 100h-byte signature area, which results in the
SHA value being read from next higher address AFTER the signature area - and
the bootrom happens to store the computed SHA at that location (causing the
bootrom to compare the computed SHA against itself, instead of against of what
should have been the decrypted SHA value).
Alltogether, brute-forcing requires only 6 specific bytes in the decrypted
signature (and the remaining 250 bytes are don't care).
The bootrom uses three RSA keys for different retail signatures, and another
three RSA keys for debug version.
NCSD Signature (in eMMC)
The eMMC's NCSD Header is unencrypted, and can be changed without needing any
AES keys (however, booting custom code requires to change FIRM, not NCSD).
6CF52F89F378120BFA4E1061D7361634D9A254A4F57AA5BD9F2C30934F0E68CB ;\
E6611D90D74CAAACB6A995565647333DC17092D320131089CCCD6331CB3A595D ;
1BA299A32FF4D8E5DD1EB46A2A57935F6FE637322D3BC4F67CFED6C2254C089C ; retail
62FA11D0824A844C79EE5A4F273D46C23BBBF0A2AF6ACADBE646F46B86D1289C ; version
7FF7E816CFDA4BC33DFF9D175AC69F72406C071B51F45A1ACB87F168C177CB9B ;
E6C392F0341849AE5D510D26EEC1097BEBFB9D144A1647301BEAF9520D22C55A ;
F46D49284CC7F9FBBA371A6D6E4C55F1E536D6237FFF54B3E9C11A20CFCCAC0C ;
6B06F695766ACEB18BE33299A94CFCA7E258818652F7526B306B52E0AED04218 ;/
53CB0E4EB1A6FF84284BE0E7385AB4A686A8BBCBC16102479280E0583655D271 ;\
3FE506FAEE74F8D10F1220441CC2FF5D6DDE99BE79C19B386CAF68D5EB8CED1A ;
AB4D243C5F398680D31CD2E3C9DD5670F2A88D563B8F65F5B234FD2EBB3BE44A ; debug
3B6C302722A2ADFB56AE3E1F6417BDEC1E5A86AABBAFBE9419ACA8FDCD45E2CD ; version
F1EB695F6EA87816122D7BE98EEF92C0814B16B215B31D8C813BB355CEA8138F ;
B3BF2374246842CD91E1F9AAFF76878617CE02064777AEA0876A2C245C784341 ;
CDEE90D691745908A6FF9CE781166796F9F1238F884C84D6F1EEBB2E40B4BCA0 ;
0A7B1E913E0980D29FF6061D8AA944C663F2638127F7CCAB6FC71538471A5138 ;/
SIGHAX.BIN
This signature is for unknown purpose (probably Retail eMMC FIRM, too):
6EFF209C8F4AF61F062413D602CA6B4DA1EB5AB9B6F1A2AB226A711DA2CCC27C
74DE1741143BF69058284CAF444F92A45AAFD5A068043323D48AF1D0EC05564E
BC79B55134E91A86C3788C97BC29D5A58A8A45255843B89122C7804542F72677
C8DA5EB7429BAF18F7A8B02E8BB940FE990E9DC97EDCF49DDB18092C28206E74
6753CC7C6E92362AA8D546B38D9E8D4311A6B1930DA14897807E304B5E1EC085
6EEFD62CEAEEF28B08BD80397A181560AE6FCE39D09C39DC3DED8C870AB6ABCE
2894940C0E9C4174F0131A0DA0747C4A7A42C9EC3487F109E252B7A9B865AE47
7895E8D6A42A0717C40BCCC7A735F33B1E3766AB0E4B5D681BAB410734AB62B0
ARM9 NDMA
--> 3DS DMA - NDMA Registers
Nocash Syntax
Allows MOV instead LP, and LOOP instead LPEND, and "ADD reg,+/-imm" instead of
"ADDH/ADNH reg,imm".
10000000h - CFG9_SYSPROT9
0 Disables ARM9 bootrom "(+8000h)" when set to 1, and enables access to
FCRAM. Cannot be cleared to 0 once set to 1. Boot9
1 Disables OTP area when set to 1. Cannot be cleared to 0 once set to 1.
NewKernel9Loader, Process9
2-7 Unused (0)
On New 3DS, the above is instead done by the Kernel9 loader. In addition to
using the OTP data for initializing the TWL console-unique keys, the Kernel9
loader will generate the decryption key for NATIVE_FIRM. The final keyslot for
NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can
be reused, since the OTP would then be inaccessible.
10000001h - CFG9_SYSPROT11
0 Disables ARM11 bootrom "(+8000h)" when set to 1, and enables access
to FCRAM. Cannot be cleared to 0 once set to 1. Boot9
1-7 Unused (0)
10000002h - CFG9_RST11
0 Presumably takes ARM11 out of reset. Cannot be set to 1 once it has
been cleared.
Reportedly: Bit0 is actually for "write-protecting the bootrom area"?
1-7 Unused (0)
10000004h - CFG9_DEBUG_CTL
0-31 Whatever, debug related (readonly, always zero on retail consoles)
10000020h - CFG9_SDMMC_CTL
This register controls power of multiple ports/controllers and allows to map
controller 3 to ARM9 or ARM11. The SD card can be accessed on ARM11 by setting
bit8 and clearing bit9.
0 Controller 1/3 port 0 power (0=On, 1=Off) ;10xxx000h.port0 SD slot TP13
1 Controller 1 port 1 power (0=On, 1=Off) ;10006000h.port1 eMMC
2 Controller 2 port 0 power (0=On, 1=Off) ;10122000h.port0 Wifi SDIO
3 ...Unknown... (initially 1 on Old3DS, initially 0 on New3DS)
4-5 Unused (0)
6 ...Unknown... Wifi port related? Pull up? Set at cold boot
7 ...Unknown... New3DS: initially 1 (R/W), Old3DS: Unused (0)
8 Controller 3 mapping (0=ARM9 10007000h, 1=ARM11 10100000h)
9 SD card controller select (0=10007000h/10100000h, 1=10006000h)
10-15 Unused (0)
10000100h - CFG9_UNKNOWN
0-1 Unknown (R/W)
2 Unused (0)
3 Unknown (R/W)
4-7 Unused (0)
8-13 Unknown (R/W)
14-15 Unused (0)
10000200h - New3DS - CFG9_EXTMEMCNT9
0 New3DS: Extended ARM9 memory at 08100000h..0817FFFFh (0=Off, 1=On)
1-31 Unused (0)
10010000h - CFG9_BOOTENV
0-31 Value (0..FFFFFFFFh) (R/W)
This register is used to determine what the previous running FIRM was. Its
value is kept following an MCU reboot.
Its initial value (on a cold boot) is 0.
NATIVE_FIRM sets it to 1 on shutdown/FIRM launch.
LGY FIRM writes value 3 here when launching a TWL title
LGY FIRM writes value 7 when launching an AGB title
NATIVE_FIRM will only launch titles if this is not value 0, and will only save
the AGB_FIRM savegame to SD if this is value 7.
10140104h - CFG11_FIQ_CNT
0-1 FIQ related? (R/W)
2-3 New3DS only: unknown...? ;initially set, (R/W) in New3DS mode!
4-7 Unused (0)
"Writing bit1 to this register disables FIQ interrupts.
This bit is set upon receipt of a FIQ interrupt and when svcUnbindInterrupt is
called on the FIQ-abstraction software interrupt for the current core. It is
cleared when binding that software interrupt to an event and just before that
event is signaled."
Maybe bit0-3 are for CPU0-3 (with above mentioned bit1 being for CPU1)? If the
bits are really FIQ related, then they are probably used on debug hardware
only.
10140105h - ???
0-1 Unknown...? (R/W)
2-3 New3DS only: unknown...? ;initially set, (R/W) in New3DS mode!
4-7 Unused (0)
Unknown. Maybe bit0-3 are for CPU0-3?
10140140h - CFG11_GPUPROT
0-3 Old FCRAM DMA cutoff size, 0 = no protection
4-7 New FCRAM DMA cutoff size, 0 = no protection ;<--New3DS mode only
8 AXI WRAM protection, 0 = accessible
9-10 QTM DMA cutoff size ;<--New3DS mode only
11-31 Unused (0)
The New3DS bits are writeable only after enabling New3DS mode.
When this register is set to value 0, the GPU can access the entire FCRAM, AXI
WRAM, and on New3DS all QTM-mem. On cold boot this reg is set to 0.
Initialized during kernel boot, and used with SVC 59h which was implemented
with v11.3.
The first 800000h-bytes of Old FCRAM cannot be protected.
The first 800000h-bytes of New FCRAM are protected if Old FCRAM cutoff<>0
The first 100000h-bytes of QTM cannot be protected.
Old FCRAM DMA cutoff protects from 28000000h-(800000h*x) until end of FCRAM
New FCRAM DMA cutoff protects from 30000000h-(800000h*x) until end of FCRAM
QTM DMA cutoff protects from 1F400000h-(100000h*x) until end of QTM
10140180h - CFG11_WIFICNT
0 Enable wifi subsystem
1-7 Unused (0)
101401C0h - CFG11_SPI_CNT
0 SPI_BUS0 Mode (registers at 10160000h) (0=Manual, 1=Fifo/Autopoll)
1 SPI_BUS1 Mode (registers at 10142000h) (0=Manual, 1=Fifo/Autopoll)
2 SPI_BUS2 Mode (registers at 10143000h) (0=Manual, 1=Fifo/Autopoll)
3-31 Unused (0)
The registers for the deselected mode are disconnected from the bus, but they
are still working internally (that is, transfer attempts will finish after the
expected amount of time, but SPI reads return nothing useful: FFh for Manual
reads, and 00h for FIFO/Autopoll reads).
10140200h - ???
0-31 Unknown (R/W)
Unknown.
10141120h - 1 - R:0 ?
Unknown. Always zero? Is that register really used by TwlBg?
10141220h - CFG11_SPEAKER_CNT
0 Unknown (R/W)
1 Audio Clock TP152 (Speaker PWM?) (0=Off/Muted Sound, 1=8MHz/16MHz On)
2-31 Unused (0)
Should be set to 02h. The Speaker Clock seems to drive speaker PWM (sound gets
muted when bit1=0, although audio I2S clock/data are kept running).
10141224h - CFG11_CAMERA_CNT
0 Camera 16MHz Enable TP229 (for camera I2C bus) (0=Disable, 1=Enable)
(1) Unused (0) ;<--- reportedly "turn on/off cameras" uh???
1-31 Unused (0)
Datasheets
Reportedly "CoreLink NIC-301 r1p0" (aka NIC-301 Network Interconnect)
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0422a/CHDGHIID.html
DDI0422.pdf
But, the ID values don't match up (at least not on New3DS, it's actually: r1p2)
DDI0422D_hpm_pl301_r1p2_ts.pdf
The somewhat misnamed "ARM7" registers are actually ARM9 registers, used to
configure GBA/NDS/DSi mode.
10018000h 1 ARM7_CNT ;\GBA/NDS/DSi mode
10018080h 20h ARM7_BOOTCODE ;/
10018100h 2 ARM7_SAVE_TYPE ;\GBA savedata
10018104h 2 ARM7_SAVE_CNT ;/
10018108h 2 ARM7_RTC_CNT ;\
10018110h 4 ARM7_RTC_BCD_DATE ;
10018114h 4 ARM7_RTC_BCD_TIME ; GBA real time clock
10018118h 4 ARM7_RTC_HEX_TIME ;
1001811Ch 4 ARM7_RTC_HEX_DATE ;/
10018120h 4 ARM7_SAVE_CFG_? ;\
10018124h 4 ARM7_SAVE_CFG_? ; GBA savedata write/erase timings?
10018128h 4 ARM7_SAVE_CFG_? ;
1001812Ch 4 ARM7_SAVE_CFG_? ;/
04700000h 4 <-- on ARM7 side, disable bootcode overlay
For specs on GBA/NDS/DSi mode:
--> GBA Reference
--> NDS Reference
--> DSi Reference
The ARM7_RTC_xxx registers are emulating the GBA cartridge RTC. The RTC for
NDS/DSi mode is emulated separately via registers in the 3DS GPIO register
space:
--> 3DS GPIO Registers
The GBA/NDS/DSi video must be forwarded to 3DS framebuffers via ARM11 DMA:
--> 3DS Video LGY Registers (Legacy GBA/NDS Video to Framebuffer)
GBA Audio requires enabling amplifiers via TSC register, and enabling GBA sound
via CODEC_SNDEXCNT.
NDS/DSi sound probably requires something similar, and more extensive TSC
initialization for NDS or DSi touchscreen mode; and adjusting the TSC
calibration points depending on whether using LGYFB scaling.
The HEX registers below contain some control flags, and some weird signed
offsets for the time/date values (the hardware does automatically
increase/decrease the BCD time/date using that offsets; set the offsets to zero
to avoid that).
GBA Titles
Nintendo did never actually release GBA titles for 3DS (except, they did
release ten "ambassador" GBA titles as a surprise gift for people who had
connected to the eshop during the first some months after the Old3DS release
date; that was before 3DS XL and 2DS and New3DS were released, so those GBA
titles seem to exist for original Old3DS only; the System Transfer tool might
allow to transfer them from Old3DS to New3DS though).
GBA Footers
GBA ROM-images are reportedly stored in .code files (in NCCH .app files, which
can also contain the usual NCCH icon/banner/logo).
Nintendo is using 360h-byte footers in GBA ROM-images (at the end of the .code
file?).
Config Data:
000h 4 Unknown (usually 0) (maybe ROM-image Offset, or version)
004h 4 ROM-image Size (usually Romsize)
008h 4 Cartridge Type (Port 10018100h, ARM7_SAVE_TYPE)
00Ch 4 Unknown (usually 0000FFFFh) (guess: savedata fillvalue?)
010h 4 Unknown (Port 10018120h, reportedly 1561662 or 2607238) ;\maybe
014h 4 Unknown (Port 10018124h, reportedly 156166 or 577077 ) ; write
018h 4 Unknown (Port 10018128h, reportedly 134 or 388 ) ; erase
01Ch 4 Unknown (Port 1001812Ch, reportedly 187667 or 201072 ) ;/timings?
020h 4 LCD Ghosting (01h..FFh) (uh, what is that?)
024h 300h LCD Video LUT (guess: maybe for Port 10400484h/10400584h or so?)
324h 0Ch Padding (0)
1st Descriptor:
330h 4 Descriptor Type (00h=ROM-Image)
334h 4 ROM-image Offset (usually 0)
338h 4 ROM-image Size (usually Romsize)
33Ch 4 Padding (0)
2nd Descriptor:
340h 4 Descriptor Type (01h=Config Data)
344h 4 Config Offset (usually Romsize+0)
348h 4 Config Size (usually 324h)
34Ch 4 Padding (0)
Footer Entrypoint (in last 10h-byte of .code file):
350h 4 GBA Footer ID (".CAA")
354h 4 Maybe Version (must be 1)
358h 4 Descriptor List Offset (usually Romsize+330h)
35Ch 4 Descriptor List Size (usually 20h) (2*10h)
lcd_ghosting_enum:
0xFFFF: no # Some seems to use this ..
0xFF: no
0xF0: little
0xC0: official_standard
0x80: official_more
0x90: official_more_plus # ?
0x20: insane
0x01: max
Ghosting seems to be an alpha value for blending the picture with the previous
frame, which was itself blended with the previous frames, thus generating a
horribly smeared picture resembling old 8bit monochrome gameboys (unknown why
Nintendo has used that effect that for GBA titles).
GBA Savedata
Upon power-off, GBA savedata is usually temporarily stored in a small eMMC
partition, and later copied to the actual savedata file upon reboot. The file
format and filename for that savedata are unknown...?
SPI Bus
--> 3DS SPI Registers
SPI Devices
--> 3DS SPI Devices
I2C Bus
--> 3DS I2C Registers
I2C Device List
--> 3DS I2C Device List
SPI Registers
There are four SPI buses (most of them can have up to 3 devices attached):
1000D000h ARM9 SPI_CARD (savedate in game card SPI FLASH memory)
10160000h ARM9/ARM11 SPI_BUS0 (0=Powerman, 1=Wifi-FLASH, 2=Touchscr/sound)
10142000h ARM9/ARM11 SPI_BUS1 (0=Touchscr/sound with extra 3ds registers)
10143000h ARM9/ARM11 SPI_BUS2 (unused)
The separate registers (at the above base addresses) are:
10xxx000h 2 SPI_MANUAL_CNT (R/W) ;\Manual Access
10xxx002h 1/2 SPI_MANUAL_DATA (R/W) ;/
10xxx800h 4 SPI_FIFO_CNT (R/W) ;\
10xxx804h 4 SPI_FIFO_DONE (R/W) ;
10xxx808h 4 SPI_FIFO_BLKLEN (R/W) ; FIFO Access
10xxx80Ch 4 SPI_FIFO_DATA (R/W) ; (and AUTOPOLL for
10xxx810h 4 SPI_FIFO_STATUS (R) ; status reads)
10xxx814h 4 SPI_AUTOPOLL (R/W) ;
10xxx818h 4 SPI_FIFO_INT_MASK (R/W) ;
10xxx81Ch 4 SPI_FIFO_INT_STAT (R/ack);/
Interrupt IDs and DMA/FIFO startup/peripheral IDs are:
SPI_CARD ARM9 IF.bit23 Various (ARM9 NDMA and ARM9 XDMA)
SPI_BUS0 ARM11 IRQ 56h ARM11 CDMA 0Fh
SPI_BUS1 ARM11 IRQ 57h ARM11 CDMA 10h
SPI_BUS2 ARM11 IRQ 24h ARM11 CDMA 11h
Config registers
CFG11_SPI_CNT - mode select for SPI_BUS0,1,2 (Manual or Fifo)
CFG9_CARD_CTL - mode select for SPI_CARD (Manual or Fifo or NTRCARD)
--> 3DS Config - CONFIG11 Registers
--> 3DS Config - CONFIG9 Registers
10xxx000h - SPI_MANUAL_CNT
10xxx002h - SPI_MANUAL_DATA
Manual access mode works same as on DSi. Max transfer rate is 8MHz, 1bit mode
only, and the manual byte-by-byte transfer adds some software overload to the
transfer time.
--> DS Serial Peripheral Interface Bus (SPI)
One advantage is that the manual mode supports true bi-directional SPI
transfers (which aren't really needed because most SPI chips use only one
direction at a time, with dummy data in opposite direction).
Cartridge SPI
Cartridge SPI can be wired to FLASH savedata (or theoretically anything else).
This can use 4bit SPI mode (if the chip is 4bit compatible, and if 4bit related
signals are wired up accordingly, and if the specific commands support 4bit
transfers).
Page Selection
TSC[xxh:00h]=page ;Page (each TSC SPI bus probably has own page+index?)
I2C Registers
Address Width Old3DS Name
10161000h 1 Yes I2C_BUS0_DATA ;\
10161001h 1 Yes I2C_BUS0_CNT ; BUS 0 (old DSi devices) (1.8V)
10161002h 2 Yes I2C_BUS0_CNTEX ;
10161004h 2 Yes I2C_BUS0_SCL ;/
10144000h 1 Yes I2C_BUS1_DATA ;\
10144001h 1 Yes I2C_BUS1_CNT ; BUS 1 (extra 3DS devices) (1.8V)
10144002h 2 Yes I2C_BUS1_CNTEX ;
10144004h 2 Yes I2C_BUS1_SCL ;/
10148000h 1 Yes I2C_BUS2_DATA ;\
10148001h 1 Yes I2C_BUS2_CNT ; BUS 2 (extra 3DS gimmicks) (3.3V)
10148002h 2 Yes I2C_BUS2_CNTEX ;
10148004h 2 Yes I2C_BUS2_SCL ;/
10161000h - I2C_BUS0_DATA
10144000h - I2C_BUS1_DATA
10148000h - I2C_BUS2_DATA
Unknown. Supposedly data.
10161001h - I2C_BUS0_CNT
10144001h - I2C_BUS1_CNT
10148001h - I2C_BUS2_CNT
0 Stop (0=No, 1=Stop/last byte)
1 Start (0=No, 1=Start/first byte)
2 Pause (0=Transfer Data, 1=Pause after Error, used with/after Stop)
3 unknown/unspecified
4 Ack Flag (0=Error, 1=Okay) (For DataRead: W, for DataWrite: R)
5 Data Direction (0=Write, 1=Read)
6 Interrupt Enable (0=Disable, 1=Enable)
7 Start/busy (0=Ready, 1=Start/busy)
10161002h - I2C_BUS0_CNTEX
10144002h - I2C_BUS1_CNTEX
10148002h - I2C_BUS2_CNTEX
0 Current SCL pin state (0=Low, 1=High/idle) (R)
1 Wait if SCL held low (0=No/fixed delay, 1=Yes, wait if SCL=low) (R/W)
3-14 Unused (0)
15 Unknown (BUS0: can be set, alongsides bit1 becomes read-only?) (?)
Bit1=0 appends a short fixed delay after each byte. Bit1=1 will automatically
wait if the SCL clock pin is held low: If the peripheral doesn't do that then
it can be even slightly faster than the fixed delay, if the peripheral does
hold SCL low then the 3DS will wait as long as needed (eg. required for
3DS/New3DS MCU and New3DS C-Stick).
10161004h - I2C_BUS0_SCL
10144004h - I2C_BUS1_SCL
10148004h - I2C_BUS2_SCL
0-5 Duration for SCL=Low (0..3Fh, 0=Fastest) ;default=0
6-7 Unused (0)
8-12 Duration for SCL=High (0..1Fh, 0=Fastest) ;default=5
13-15 Unused (0)
The fastest setting (0000h) is about 380kHz (about 41Kbyte/s).
The slowest setting (1F3Fh) is about 84kHz (about 9Kbyte/s)
Hmmm, or maybe the raw bitrate is faster, but with short pause between bytes?
I2C Devices
id bus:dev service Device description
0 0:4Ah "i2c::MCU" BPTWL (aka MCU registers for DSi mode) ;\same
1 0:7Ah "i2c::CAM" Camera0 (internal camera, self-facing) ; as DSi
2 0:78h "i2c::CAM" Camera1 (external camera, right eye) ;/
3 1:4Ah "i2c::MCU" MCU (aka MCU registers for 3DS mode)
4 1:78h "i2c::CAM" Camera2 (external camera, left eye)
5 1:2Ch "i2c::LCD" Upper LCD screen (lcd0)
6 1:2Eh "i2c::LCD" Lower LCD screen (lcd1)
7 1:40h "i2c::DEB" Reserved for Debug?
8 1:44h "i2c::DEB" Reserved for Debug?
9 2:A6h/D6h"i2c::HID" Debug?? addr changed from A6h to D6h in 8.0.0-18
10 2:D0h "i2c::HID" Gyroscope (old version) <-- read = FFh's ?
11 2:D2h "i2c::HID" Gyroscope (new version) <-- EXISTS in New3DS
12 2:A4h "i2c::HID" Reserved for DebugPad
13 2:9Ah "i2c::IR" Infrared Transmitter/Receiver (IrDA)
14 2:A0h "i2c::EEP" Reserved for DebugEeprom?
15 1:EEh "i2c::NFC" New3DS-only NFC (Near-field communication)
16 0:40h "i2c::QTM" New3DS-only QTM (head tracking?) IO Expander!
17 2:54h "i2c::IR" New3DS-only C-stick and ZL/ZR.. 44pin chip??
- none(?) - New3DS-only Hasn't co-packaged EEPROM in NFC chip?
- 0:A0h - Reserved for Unknown DSi camera0 (Ext)
- 0:E0h - Reserved for Unknown DSi camera1 (Self)
- 0:40h - Reserved for Unknown DSi Debug stuff? and QTM
- 0:90h - Reserved for Unknown DSi Debug stuff?
- 0:00h-0Eh Mirrors to BPTWL for whatever reason
- 0:F0h-FEh Mirrors to BPTWL for whatever reason
- 0:5Ah Internal dummy addr used by BPTWL when busy?
- 2:00h Unknown, something responds here with ACK and FFh's
Notice: These device addresses are used for writing to the respective device,
for reading bit0 must be set (see I2C protocol).
MCU Registers
00h R Version high (bit0-3) and hardware.type? (bit4-7) ;\Firm
01h R Version low (8bit) ;/
02h R/W Reset Event flags ;-Stat
03h R/W LCD Top Screen VCOM "flicker" ;\
04h R/W LCD Bottom Screen VCOM "flicker" ;/
05h-07h R/W MCU Firmware update unlock sequence ;ARRAY[4003h] ;-Firm
08h R Raw 3D slider position ;\
09h R Volume slider state (00h..3Fh) (as MCUHWC:GetSoundVolume) ;
0Ah R Battery PCB Temperature Celsius (signed) ; Stat
0Bh R Fuel Gauge Battery Percentage, msb (percent, 0..64h) ;
0Ch R Fuel Gauge Battery Percentage, lsb (percent/256, 0..FFh) ;
0Dh R Fuel Gauge Battery Voltage (in 20mV units) ;
0Eh R Sub-Device Access Flags? (bit0,1,2-3,4) ;
0Fh R Power Status Flags ;/
10h-13h R MCU Interrupt Flags, bit0-31 (1=IRQ, cleared after read) ;\
14h R Unused (cleared after reading, like above IRQ flags) ;
15h-17h R/W Unused ; IRQs
18h-1Bh R/W MCU Interrupt Mask, bit0-31 (0=Enable, 1=Disable) ;
1Ch-1Fh R/W Unused ;/
20h W System Power Control (bits are 0=No change, 1=Trigger) ;\
21h W DSi Power Button Status register BPTWL[10h] change ;
22h W LCD Power Control (bits are 0=No change, 1=Trigger) ; PWR
23h - Unused (has a dummy write handler, but does nothing) ;
24h R/W Forced Power Off delay (0=Never, 1=Fastest, 5Dh=Insane) ;/
25h R/W Unused (0)
26h R/W Unused (initiallly 0, but, ARM sets MCU[26h]=10h!)
27h R/W Volume slider raw ADC value ;-Stat
28h R/W Brightness of Wifi/Power/3D LEDs ;\
29h * R/W Power LED state + Power LED blink pattern ;ARRAY[5] ;
2Ah R/W Wifi LED state, 4 bits wide ; LEDs
2Bh R/W Camera LED state, 4bits wide ;
2Ch R/W 3D LED state, 4 bits wide ;
2Dh * W Notification LED Array (4+3x20h bytes) ;ARRAY[64h] ;
2Eh R Notification LED Status when read (1=new cycle started) ;/
2Fh - Unused (has a dummy write handler, but does nothing)
30h R/W RTC Time second (7bit) (BCD, 00h..59h) ;\
31h R/W RTC Time minute (7bit) (BCD, 00h..59h) ;
32h R/W RTC Time hour (6bit) (BCD, 00h..23h) ;
33h R/W RTC Time day of week? (3bit) (?..?, ?=Monday) ;
(renesas calls this "Week 0=Sunday") ; RTC
(unknown what Nintendo is using here) ;
34h R/W RTC Time day (6bit) (BCD, 01h..31h) ;
35h R/W RTC Time month (5bit) (BCD, 01h..12h) ;
36h R/W RTC Time year (8bit) (BCD, 00h..99h) ;
37h R/W RTC Watch Error Correction (SUBCUD) ;NOT leap year ;
38h R/W RTC Alarm minute (7bit) (BCD, 00h..59h) ;
39h R/W RTC Alarm hour (6bit) (BCD, 00h..23h) ;
3Ah R/W RTC Alarm day (6bit) (BCD, 01h..31h) ;\maybe 0=off? ;
3Bh R/W RTC Alarm month (5bit) (BCD, 01h..12h) ;/ ;
3Ch R/W RTC Alarm year (8bit) (BCD, 00h..99h) ;
3Dh R RTC RSUBC.lsb (in 32768Hz units) ;\range 0..7FFFh ;
3Eh R RTC RSUBC.msb (latched when reading lsb) ;/(or 0..80xxh) ;
3Fh W RTC Flags (bit0=ScreenBlack?, bit1=DisableRtc32KHzOutput) ;/
40h R/W Accelerometer Mode (bit0=AccelerometerOn, bit1=PedometerOn) ;\
41h R/W Accelerometer Index for Manual I2C Read via MCU[44h] ;
42h R/W Unused (0) ;
43h R/W Accelerometer Index for Manual I2C Write via MCU[44h] ;
44h R/W Accelerometer Data from/to Read/Write via MCU[41h/43h] ;
45h,46h R Accelerometer Output X (lsb,msb) ;resting=+/-00xxh ;
47h,48h R Accelerometer Output Y (lsb,msb) ;resting=+/-00xxh ;
49h,4Ah R Accelerometer Output Z (lsb,msb) ;resting=-41xxh (gravity) ;
4Bh R/W Pedometer Step Count, bit0-7 ;\(for the current day) ;
4Ch R/W Pedometer Step Count, bit8-15 ; (uh, how/which day?) ;
4Dh R/W Pedometer Step Count, bit16-23 ;/(rather total count?) ;
4Eh R/W Pedometer Flags (Wr.bit0=ClearArray?, Rd.bit4=ArrayFull?) ;
4Fh * R Pedometer Timestamp[6] and StepCounts[2*A8h] ;ARRAY[6+2*A8h] ;
50h,51h R/W Pedometer Minute,Second compare values (?) ;/
52h-57h R/W Unused, except some bytes are set to fixed values once and then
58h R/W Volume slider calibration point for 0% (default=36h)
59h R/W Volume slider calibration point for 100% (default=C9h)
5Ah R/RW Invalid, do not use!
on newer MCU_FIRM versions this is set to FFh once and then
on older MCU_FIRM versions this is a read-only counter
5Bh-5Fh - N/A (write=ignored, read=FFh)
60h * R/W Battery-backed RAM Index ;\
61h * R/W Battery-backed RAM Data (200 bytes) ;ARRAY[C8h] ; Misc
62h-7Eh - N/A (write=ignored, read=FFh) ;
7Fh * R Various system state information ;ARRAY[09h/13h] ;/
80h-FFh - N/A (write=ignored, read=FFh)
Blurb
On old versions of MCU_FIRM none of the invalid registers are masked away by
the read handler function, but are still read-only. Newer MCU_FIRM versions
return the hardcoded value FF instead.
Reportedly register 3Bh (RTC Alarm month) "could be used on very old MCU_FIRM
versions to upload MCU firmware if some conditions (?) are met", uh?.
Firmware Image/Dumping
A copy of the firmware-image can be found in the System Modules folder,
3ds:\title\00040130\00001f02\content\000000vv.app ;MCU
3ds:\title\00040130\20001f02\content\000000vv.app ;MCU New3DS
3ds:\title\00040130\00001f03\content\000000vv.app ;MCU Safe mode
3ds:\title\00040130\20001f03\content\000000vv.app ;MCU Safe mode New3DS
The .app file contains a .code file with ARM11 code (and the MCU firmware
somewhere inside of that .code file, usually at file offset A078h or A07Ch;
starting with the 3-byte unlock code ("jhl"), followed by the 4000h-byte
firmware image).
Dumping the firmware directly from FLASH memory isn't supported. However, one
could patch the firmware, and then dump the backup of the old version (that
will destroy the backup of the yet older version though).
MCU[27h] - Volume slider raw ADC value (R/W, but better treat as R)
0-7 Volume slider raw ADC value (00h..FFh)
MCU[20h] - System Power Control (bits here are 0=No change, 1=Trigger) (W)
0 Power off
1 Reboot (unused?)
2 Reboot (used by mcu sysmodule and LgyBg)
3 Used by LgyBg to power off, causes hangs in 3DS-mode
4 NewMCU: looks like power-off type (real power off, or sleep state...?)
"an mcu::RTC command uses this, seems to do something with the
watchdog: Bit 4 sets a bit at a RAM address which seems to control
the watchdog timer state, then this bit is immediately unmasked.
This field has a bitmask of 0x0F."
4 OldMCU: Both backlights off ;\this is probably very
5 OldMCU: Both backlights on ; old prototype stuff?
6 OldMCU: LCD "push" Power Supplies off ; (normally use MCU[22h])
7 OldMCU: LCD "push" Power Supplies on ;/
Unknown how to fully power-off. Writing 01h does somewhat power-off, but the
battery still runs empty after 10-20 hours. Some people execute a
Wait-for-Interrupt opcode after the I2C write; not tested if that does help
(and if that opcode is needed on all ARM11 CPU core(s) and ARM9 side).
MCU[22h] - LCD Power Control (bits here are 0=No change, 1=Trigger) (W)
0 NewMCU: LCD "push" Power Supplies and Backlights off
1 NewMCU: LCD "push" Power Supplies on
2 NewMCU: Bottom Screen Backlight off ;\For 2DS: Both screens
3 NewMCU: Bottom Screen Backlight on ;/
4 NewMCU: Top Screen Backlight off ;\For 2DS: No effect
5 NewMCU: Top Screen Backlight on ;/
6-7 Not used
Setting bit0 does disable most or all LCD related power supplies: VCOM, AVDD,
10V (probably also +5V and -5V), and backlights. Setting bit1 enables those
supplies (except backlights, which require bit3/bit5). The 1.8V supply for the
LCD I2C controllers is always on. The backlight PWM level is controlled via ARM
LCD registers.
MCU[29h] - Power LED state + Power LED blink pattern ;ARRAY[5] (R/W)
1st byte (Power LED mode):
00h = Fade to brightness MCU[28h] with battery check
01h = Fade to brightness MCU[28h]
02h = Pulsating fade on/off with battery check
03h = Fade to brightness 00h
04h = Instantly set brightness 00h
05h = Instantly set brightness FFh
06h = Blinking RED (affects Power+Notification LEDs)
Other = Invalid (same as 00h)
2nd..5th bytes (optional, if any written):
Power LED Blink pattern (default is 55h,55h,55h,55h)
MCU[2Eh] - Notification LED Status when read (1=new cycle started) (R)
0 Flag
1-7 Not used
MCU[37h] - RTC Watch Error Correction (SUBCUD) (R/W) ;NOT leap year
0-6 Signed offset (-40h..+3Fh, see below for details)
7 Add offset when... (0=Every 20 seconds, 1=Every 60 seconds)
The offsets are a bit weird:
+00h Range 0..(7FFFh) ;error correction disabled
+01h..3Fh Range 0..(7FFFh+(0..124)) ;add (N-1)*2
-01h..3Fh Range 0..(7FFFh-(0..124)) ;add (N+1)*2 or so?
-40h Range 0..(7FFFh) ;error correction disabled
After battery loss, the register is 00h, the 3DS firmware changes it to the RTC
Correction value from "config" or HWCAL files.
MCU Registers
40h R/W Accelerometer Mode (bit0=AccelerometerOn, bit1=PedometerOn) ;\
41h R/W Accelerometer Index for Manual I2C Read via MCU[44h] ;
42h R/W Unused ;
43h R/W Accelerometer Index for Manual I2C Write via MCU[44h] ;
44h R/W Accelerometer Data from/to Read/Write via MCU[41h/43h] ;
45h,46h R Accelerometer Output X (lsb,msb) ;resting=+/-00xxh ;
47h,48h R Accelerometer Output Y (lsb,msb) ;resting=+/-00xxh ;
49h,4Ah R Accelerometer Output Z (lsb,msb) ;resting=-41xxh (gravity) ;
4Bh R/W Pedometer Step Count, bit0-7 ;\(for the current day) ;
4Ch R/W Pedometer Step Count, bit8-15 ; (uh, how/which day?) ;
4Dh R/W Pedometer Step Count, bit16-23 ;/(rather total count?) ;
An up/down movement (on whichever axis that corresponds ;
to gravity direction) is treated as step; however, the ;
first step isn't counted, so 5 continous steps would ;
increment the counter by 4. ;
4Eh R/W Pedometer Flags (Wr.bit0=ClearArray?, Rd.bit4=ArrayFull?) ;
4Fh * R Pedometer Timestamp[6] and StepCounts[2*A8h] ;ARRAY[6+2*A8h] ;
50h,51h R/W Pedometer Minute,Second compare values (?) ;/
Reading the Output X/Y/Z registers would be the normal way to get the
accelerometer data (if enabled in the mode register).
Accelerometer Chip
On Old3DS it is marked "2048, 33DH, X1MAQ", which is said to be ST LIS331DLH.
On New3DSXL it is marked "KXTKK, 40860, .3413", which might be a Kionix chip,
resembling KXTIK, but with LIS331DLH-style register map & device address.
Both Old3DS and New3DSXL have the chip on the mainboard, somewhere underneath
of the bottom-screen. That (and the exact location) may be important when
interpreting the accelerometer data (ie. the chip isn't parallel with the
top-screen unless the case is fully unfolded).
The Accelerometer chip is wired to the MCU, so it's I2C registers can be
accessed only indirectly, through the MCU.
HPCF[1:0]. These bits are used to configure high-pass filter cut-off frequency
ft which is given by:
... XXX ...
The equation can be simplified to the following approximated equation:
... XXX ...
Table 24. High-pass filter cut-off frequency configuration
HPcoeff2,1 ft [Hz] ft [Hz] ft [Hz] ft [Hz]
Data rate=50Hz Data rate=100Hz Data rate=400Hz Data rate=1000Hz
00 1 2 8 20
01 0.5 1 4 10
10 0.25 0.5 2 5
11 0.125 0.25 1 2.5
Wifi button
The Wifi button does trigger an MCU interrupt, but doesn't automatically
enable/disable the Wifi LED, Wifi Disable bit, or other Wifi Hardware. Instead,
the ARM software should process the Wifi button IRQ as so:
- Toggle the Wifi Disabled flag in battery backed MCU[61h:00h].bit0
- Enable/disable the Wifi LED in MCU[2Ah] accordingly
- Enable/disable the overall Wifi hardware accordingly
The Wifi button exists only in Old3DS (but New3DS does reportedly have a
similar option... in System Settings or so?).
New3DS
New2DS
Unknown.
Wiring Programmer (PC Parallel Port, GPIO, UART, whatever) to 3DS MCU
TP74 /RESET ----------------|>|-------------- PC.Data1.Reset
TP77 TOOL0 ------------o---|>|-------------- PC.Data0.TX
| BAT85 .------- PC.Busy.RX
TP75 FLMD0 -----. | |/ B
| '--[33K]---| C
TP79 PVDD18 -----' |\ E
BC547 v--.
TP78 GND ----------------------------o---- PC.Ground
The 3DS MCU programming signals are 1.8V, two BAT85 Schottky diodes can be used
as one-directional level changer (with replies ignored/skipped via hardcoded
delays), an additional 10K-65K resistor and BC547 transistor can be used for
bi-directional transfers.
Command Summary
00h Reset (aka enter flash mode)
13h Verify/compare
14h --Undocumented-- verify/compare first 4 bytes of flash, if [000C3h].bit1
19h --Undocumented-- resembles "internal verify" from write command
20h Chip Erase
22h Block Erase
32h Block Blank check
40h Write
9Ah Set Baud Rate
A0h Set Security
B0h Get Checksum
C0h Get Silicon Signature
C5h Get Version
The relevant commands are Reset, Block Erase, and Write.
Write Command
Requires prior Erase command, max length for erase/write commands seems to be
1000h bytes. To quit flash mode & resume normal operation, it seems to be
required to unplug battery supply for a moment after having written all data.
Command (to chip):
00h 3 Start/Len/Command (01h,07h,40h)
03h 3 Start address (MSB,MID,LSB) ;lower 8bit=00h ;\100h byte boundary
06h 3 End address (MSB,MID,LSB) ;lower 8bit=FFh ;/
09h 2 Checksum/End (CHK,03h)
Response (from chip, after command):
00h 2 Start/Len (02h,01h)
02h 1 Status/Error code (command reception result)
03h 2 Checksum/End (CHK,03h)
Data (to chip):
00h 2 Start/Len (02h,LEN) ;LEN=1..255 bytes, or 0=256 bytes
02h LEN Data (usually 256 bytes)
xxh 2 Checksum/End (CHK,03h/17h) ;03h=Last, 17h=Nonlast
Response (from chip, circa 60ms after each data block):
00h 2 Start/Len (02h,02h)
02h 1 Status/Error code (data reception result)
02h 1 Status/Error code (write result)
04h 2 Checksum/End (CHK,03h)
Response (from chip, extra response, about 1.5 seconds after LAST data block):
00h 2 Start/Len (02h,01h)
02h 1 Status/Error code (internal verify result)
03h 2 Checksum/End (CHK,03h)
Note: The ugly 1.5 seconds verify delay can be avoided by issuing a chip reset
instead of waiting for the final response.
Verify/Compare Command
Command (to chip):
00h 3 Start/Len/Command (01h,07h,13h)
03h 3 Start address (MSB,MID,LSB) ;lower 8bit=00h ;\100h byte boundary
06h 3 End address (MSB,MID,LSB) ;lower 8bit=FFh ;/
09h 2 Checksum/End (CHK,03h)
Response (from chip, after command):
00h 2 Start/Len (02h,01h)
02h 1 Status/Error code (command reception result)
03h 2 Checksum/End (CHK,03h)
Data (to chip):
00h 2 Start/Len (02h,LEN) ;LEN must be N*4 bytes (usually (1)00h bytes)
02h LEN Data
xxh 2 Checksum/End (CHK,03h/17h) ;03h=Last, 17h=Nonlast
Response (from chip, after each data block):
00h 2 Start/Len (02h,02h)
02h 1 Status/Error code (data reception result)
02h 1 Status/Error code (verify result) (always ACK/okay for Nonlast?)
04h 2 Checksum/End (CHK,03h)
With data LEN=4, this seems to allow dump the chip content via brute-force (but
requires to send/receive trillions of bits to dump 4 bytes, and gets slower
towards end of 100h-byte snippets).
Notes
The above protocol is documented in the "78K0R/Kx3-L Flash Memory Programming"
application note.
Unknown if verify/checksum could be tweaked to dump the current flash content.
There is also an undocumented anti-dumping feature related to bytes at 000C4h
(that's probably related to TOOL1 debug pin, not to TOOL0 serial flash pin).
Move Byte
09/29/49 MOV A, [nnnn+B]/[nnnn+C]/[nnnn+BC]
88/89/8A/8B/8C MOV A, [nn+SP]/[DE]/[nn+DE]/[HL]/[nn+HL]
8D/8E/8F MOV A, [saddr]/[sfr]/[nnnn]
61C9/61E9 MOV A, [HL+B]/[HL+C]
60/--/62/63/64/65/66/67 MOV A, X/-/C/B/E/D/L/H
70/--/72/73/74/75/76/77 MOV X/-/C/B/E/D/L/H, A
50/51/52/53/54/55/56/57 MOV X/A/C/B/E/D/L/H, imm8
D8/--/F8/E8 MOV X/-/C/B, [saddr]
D9/--/F9/E9 MOV X/-/C/B, [nnnn]
E0/E1/E2/E3/E4/E5 MOV X/A/C/B/[saddr]/[nnnn], 1 ;native: ONEB
F0/F1/F2/F3/F4/F5 MOV X/A/C/B/[saddr]/[nnnn], 0 ;native: CLRB
41/61B8 MOV ES, imm8/[saddr]
18/28/48 MOV [nnnn+B]/[nnnn+C]/[nnnn+BC], A
98/99/9A/9B/9C MOV [nn+SP]/[DE]/[nn+DE]/[HL]/[nn+HL], A
9D/9E/9F MOV [saddr]/[sfr]/[nnnn], A
61D9/61F9 MOV [HL+B]/[HL+C], A
19/38/39 MOV [nnnn+B]/[nnnn+C]/[nnnn+BC], imm8
C8/CA/CC MOV [nn+SP]/[nn+DE]/[nn+HL], imm8
CD/CE/CF MOV [saddr]/[sfr]/[nnnn], imm8
08/--/618A/618B/618C/618D/618E/618F XCH A, X/-/C/B/E/D/L/H
61AC/61AD/61B9/61A9 XCH A, [HL]/[HL+byte]/[HL+B]/[HL+C]
61AE/61AF XCH A, [DE]/[DE+byte]
61AB/61A8/61AA XCH A, [sfr]/[saddr]/[nnnn]
Move Word
13/15/17/30 MOVW AX, BC/DE/HL/imm16
59/69/79 MOVW AX, [nnnn+B]/[nnnn+C]/[nnnn+BC]
A8/A9/AA/AB/AC MOVW AX, [nn+SP]/[DE]/[nn+DE]/[HL]/[nn+HL]
AD/AE/AF MOVW AX, [saddrp]/[sfrp]/[nnnn]
E6/E7 MOVW AX/BC,1 ;native: ONEW AX/BC
F6/F7 MOVW AX/BC,0 ;native: CLRW AX/BC
12/32/DA/DB MOVW BC, AX/#imm16/[saddrp]/[nnnn]
14/34/EA/EB MOVW DE, AX/#imm16/[saddrp]/[nnnn]
16/36/FA/FB MOVW HL, AX/#imm16/[saddrp]/[nnnn]
58/68/78 MOVW [nnnn+B]/[nnnn+C]/[nnnn+BC], AX
B8/B9/BA/BB/BC MOVW [nn+SP]/[DE]/[nn+DE]/[HL]/[nn+HL], AX
BD/BE/BF MOVW [saddrp]/[sfrp]/[nnnn], AX
C9/CB MOVW [saddrp]/[sfrp], imm16
C0/C2/C4/C6/61CD POP AX/BC/DE/HL/PSW
C1/C3/C5/C7/61DD PUSH AX/BC/DE/HL/PSW
33/35/37 XCHW AX, BC/DE/HL
ALU Byte
6100/6101/6102/6103/6104/6105/6106/6107 ADD X/A/C/B/E/D/L/H, A
6110/6111/6112/6113/6114/6115/6116/6117 ADDC X/A/C/B/E/D/L/H, A
6120/6121/6122/6123/6124/6125/6126/6127 SUB X/A/C/B/E/D/L/H, A
6130/6131/6132/6133/6134/6135/6136/6137 SUBC X/A/C/B/E/D/L/H, A
6140/6141/6142/6143/6144/6145/6146/6147 CMP X/A/C/B/E/D/L/H, A
6150/6151/6152/6153/6154/6155/6156/6157 AND X/A/C/B/E/D/L/H, A
6160/6161/6162/6163/6164/6165/6166/6167 OR X/A/C/B/E/D/L/H, A
6170/6171/6172/6173/6174/6175/6176/6177 XOR X/A/C/B/E/D/L/H, A
6108/----/610A/610B/610C/610D/610E/610F ADD A, X/-/C/B/E/D/L/H
6118/----/611A/611B/611C/611D/611E/611F ADDC A, X/-/C/B/E/D/L/H
6128/----/612A/612B/612C/612D/612E/612F SUB A, X/-/C/B/E/D/L/H
6138/----/613A/613B/613C/613D/613E/613F SUBC A, X/-/C/B/E/D/L/H
6148/----/614A/614B/614C/614D/614E/614F CMP A, X/-/C/B/E/D/L/H
6158/----/615A/615B/615C/615D/615E/615F AND A, X/-/C/B/E/D/L/H
6168/----/616A/616B/616C/616D/616E/616F OR A, X/-/C/B/E/D/L/H
6178/----/617A/617B/617C/617D/617E/617F XOR A, X/-/C/B/E/D/L/H
0B/0C/0D/0E/0F ADD A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
1B/1C/1D/1E/1F ADDC A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
2B/2C/2D/2E/2F SUB A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
3B/3C/3D/3E/3F SUBC A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
4B/4C/4D/4E/4F CMP A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
5B/5C/5D/5E/5F AND A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
6B/6C/6D/6E/6F OR A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
7B/7C/7D/7E/7F XOR A,[saddr]/#byte/[HL]/[HL+byte]/[nnnn]
0A ADD [saddr],#byte
1A ADDC [saddr],#byte
2A SUB [saddr],#byte
3A SUBC [saddr],#byte
4A/40 CMP [saddr]/[nnnn],#byte
5A AND [saddr],#byte
6A OR [saddr],#byte
7A XOR [saddr],#byte
D0/D1/D2/D3/D4/D5 CMP X/A/C/B/[saddr]/[nnnn],0 ;native: CMP0
80/81/82/83/84/85/86/87/A0/A4/6159 INC X/A/C/B/E/D/L/H/[nnnn]/[saddr]/[HL+nn]
90/91/92/93/94/95/96/97/B0/B4/6169 DEC X/A/C/B/E/D/L/H/[nnnn]/[saddr]/[HL+nn]
ALU Word
01/03/05/07 ADDW AX, AX/BC/DE/HL
--/23/25/27 SUBW AX, --/BC/DE/HL
--/43/45/47 CMPW AX, --/BC/DE/HL
04/02/06/6109/10 ADDW AX, nnnn/[nnnn]/[saddrp]/[HL+nn] / ADDW SP,00nn
24/22/26/6129/20 SUBW AX, nnnn/[nnnn]/[saddrp]/[HL+nn] / SUBW SP,00nn
44/42/46/6149/-- CMPW AX, nnnn/[nnnn]/[saddrp]/[HL+nn] / CMPW --
A1/A3/A5/A7/A2/A6/6179 INCW AX/BC/DE/HL/[nnnn]/[saddrp]/[HL+nn]
B1/B3/B5/B7/B2/B6/6189 DECW AX/BC/DE/HL/[nnnn]/[saddrp]/[HL+nn]
Rotate/Shift
61DB ROR A, 1
61EB ROL A, 1
61FB RCR A, 1 ;native: RORC A,1
61DC RCL A, 1 ;native: ROLC A,1
3109/3108/3107+n*10 SHL A/B/C, 1..7
310A+n*10 SHR A, 1..7
310B+n*10 SAR A, 1..7
61EE/61FE RCLW AX/BC, 1 ;native: ROLWC AX/BC,1
310D/310C+n*10 SHLW AX/BC, 1..15
310E+n*10 SHRW AX, 1..15
310F+n*10 SARW AX, 1..15
Jump/Call
61CB JMP AX ;native: BR AX ;CS:
ECnnnn0n JMP absolute far addr ;native: BR !!addr20
EDnnnn JMP absolute addr ;native: BR !addr16
EEnnnn JMP relative addr ;native: BR $!addr20
EFnn JMP relative short addr ;native: BR $addr20
61CA/61DA/61EA/61FA CALL AX/BC/DE/HL ;native: CALL AX/BC/DE/HL ;CS:
FCnnnn0n CALL absolute far addr ;native: CALL !!addr20
FDnnnn CALL absolute addr ;native: CALL !addr16
FEnnnn CALL relative addr ;native: CALL $!addr20
61nn CALL [000xx] ;native: CALLT [xx]
Bit Manipulation
7101/7109/7181/7189+n*10 MOV1 [saddr]/[sfr]/[HL]/A.n, CY
7104/710C/7184/718C+n*10 MOV1 CY, [saddr]/[sfr]/[HL]/A.n
7105/710D/7185/718D+n*10 AND1 CY, [saddr]/[sfr]/[HL]/A.n
7106/710E/7186/718E+n*10 OR1 CY, [saddr]/[sfr]/[HL]/A.n
7107/710F/7187/718F+n*10 XOR1 CY, [saddr]/[sfr]/[HL]/A.n
7180/7100/7102/710A/7182/718A+n*10 SET1 CY/[nnnn]/[saddr]/[sfr]/[HL]/A.n
7188/7108/7103/710B/7183/718B+n*10 CLR1 CY/[nnnn]/[saddr]/[sfr]/[HL]/A.n
71C0 NOT1 CY
Misc
00 NOP
61CC/61ED/61FD BRK/HALT/STOP
D7/61EC/61FC RET/RETB/RETI
FF TRAP ;pseudo invalid.reset
717AFA/717BFA EI/DI ;pseudo set/clr.sfr.bit
61C8/61D8/61E8/61F8/61E3/61F3 SKC/SKNC/SKZ/SKNZ/SKH/SKNH ;conditional skip
61CE MOVS [HL+byte],X
61DE CMPS X,[HL+byte]
61CF/61DF/61EF/61FF SEL RB0/1/2/3
D6 MULU X ;unsigned multiply AX=A*X
11 prefix for [ES:addr] ;native: ES:addr[reg]
40 50 60 70
40 CMP !addr16,#byte MOV X,#byte MOV A,X MOV X,A
41 MOV ES,#byte MOV A,#byte 2nd MAP !!! 3rd MAP !!!
42 CMPW AX,!addr16 MOV C,#byte MOV A,C MOV C,A
43 CMPW AX,BC MOV B,#byte MOV A,B MOV B,A
44 CMPW AX,#word MOV E,#byte MOV A,E MOV E,A
45 CMPW AX,DE MOV D,#byte MOV A,D MOV D,A
46 CMPW AX,saddrp MOV L,#byte MOV A,L MOV L,A
47 CMPW AX,HL MOV H,#byte MOV A,H MOV H,A
48 MOV word[BC],A MOVW word[B],AX MOVW word[C],AX MOVW word[BC],AX
49 MOV A,word[BC] MOVW AX,word[B] MOVW AX,word[C] MOVW AX,word[BC]
4A CMP saddr,#byte AND saddr,#byte OR saddr,#byte XOR saddr,#byte
4B CMP A,saddr AND A,saddr OR A,saddr XOR A,saddr
4C CMP A,#byte AND A,#byte OR A,#byte XOR A,#byte
4D CMP A,[HL] AND A,[HL] OR A,[HL] XOR A,[HL]
4E CMP A,[HL+byte] AND A,[HL+byte] OR A,[HL+byte] XOR A,[HL+byte]
4F CMP A,!addr16 AND A,!addr16 OR A,!addr16 XOR A,!addr16
80 90 A0 B0
80 INC X DEC X INC !addr16 DEC !addr16
81 INC A DEC A INCW AX DECW AX
82 INC C DEC C INCW !addr16 DECW !addr16
83 INC B DEC B INCW BC DECW BC
84 INC E DEC E INC saddr DEC saddr
85 INC D DEC D INCW DE DECW DE
86 INC L DEC L INCW saddrp DECW saddrp
87 INC H DEC H INCW HL DECW HL
88 MOV A,[SP+byte] MOV [SP+byte],A MOVW AX,[SP+byte] MOVW [SP+byte],AX
89 MOV A,[DE] MOV [DE],A MOVW AX,[DE] MOVW [DE],AX
8A MOV A,[DE+byte] MOV [DE+byte],A MOVW AX,[DE+byte] MOVW [DE+byte],AX
8B MOV A,[HL] MOV [HL],A MOVW AX,[HL] MOVW [HL],AX
8C MOV A,[HL+byte] MOV [HL+byte],A MOVW AX,[HL+byte] MOVW [HL+byte],AX
8D MOV A,saddr MOV saddr,A MOVW AX,saddrp MOVW saddrp,AX
8E MOV A,sfr MOV sfr,A MOVW AX,sfrp MOVW sfrp,AX
8F MOV A,!addr16 MOV !addr16,A MOVW AX,!addr16 MOVW !addr16,AX
C0 D0 E0 F0
C0 POP AX CMP0 X ONEB X CLRB X
C1 PUSH AX CMP0 A ONEB A CLRB A
C2 POP BC CMP0 C ONEB C CLRB C
C3 PUSH BC CMP0 B ONEB B CLRB B
C4 POP DE CMP0 saddr ONEB saddr CLRB saddr
C5 PUSH DE CMP0 !addr16 ONEB !addr16 CLRB !addr16
C6 POP HL MULU X ;(AX=A*X) ONEW AX CLRW AX
C7 PUSH HL RET ONEW BC CLRW BC
C8 MOV [SP+byte],#byte MOV X,saddr MOV B,saddr MOV C,saddr
C9 MOVW saddrp,#word MOV X,!addr16 MOV B,!addr16 MOV C,!addr16
CA MOV [DE+byte],#byte MOVW BC,saddrp MOVW DE,saddrp MOVW HL,saddrp
CB MOVW sfrp,#word MOVW BC,!addr16 MOVW DE,!addr16 MOVW HL,!addr16
CC MOV [HL+byte],#byte BC $addr20 BR !!addr20 CALL !!addr20
CD MOV saddr,#byte BZ $addr20 BR !addr16 CALL !addr16
CE MOV sfr,#byte BNC $addr20 BR $!addr20 CALL $!addr20
CF MOV !addr16,#byte BNZ $addr20 BR $addr20 - (TRAP)
Opcode FFh = TRAP (illegal opcode, used by 3DS MCU, triggers Reset vector).
Uh, other/prefixed illegal opcodes do not act as TRAP?
Pseudo Opcodes
EI 71 7A FA ;SET1 SFR(FAh).7 (PSW.bit7 enable interrupts)
DI 71 7B FA ;CLR1 SFR(FAh).7 (PSW.bit7 disable interrupts)
TRAP FF ;invalid opcode FF (triggers Reset vector)
Extra MUL opcodes (unknown if these are supported on 3DS):
MULHU CE FB 01 ;MOV SFR(FBh),#01h Note
MULH CE FB 02 ;MOV SFR(FBh),#02h Note
DIVHU CE FB 03 ;MOV SFR(FBh),#03h Note
DIVWU CE FB 0B ;MOV SFR(FBh),#0Bh Note
MACHU CE FB 05 ;MOV SFR(FBh),#05h Note
MACH CE FB 06 ;MOV SFR(FBh),#06h Note
Others:
"saddr.#" and "sfr.#" with #=8..15 could be implemented as "addr+1.#-8".
"callt [nn]" can be seen as 2-byte alias for "call nnnn" (via the ROM table)
Registers
PC 20bit Program Counter
PSW 8bit Program Status Word (flags)
SP 16bit Stack Pointer (bit0=always 0, bit1-15=used)
AX 16bit aka A:X ;\these can be used as 16bit (eg. AX) or two 8bit
BC 16bit aka B:C ; registers (eg. A and X).
DE 16bit aka D:E ; all of these registers exist in 4 banks (the
HL 16bit aka H:L ;/active bank is selected via "SEL RBn" opcode)
ES 4bit Data Bank ;-used only for PREFIX'ed opcode, otherwise bank=0Fh
CS 4bit Code Bank ;-MSBs of destination for JMP/CALL AX/BC/DE/HL
Note: All registers (except PC) are mapped to the SFR register area, and can be
also used by accessing that memory. In case of the banked AX/BC/DE/HL
registers, observe that direct memory access won't recurse the current "bank"
selection (that weird feature/problem is same as for 8051 CPUs).
Stack
PUSH/POP rp/PSW --> 2 bytes
CALL/CALLT/RET --> 4 bytes
Interrupt/RETI --> 4 bytes
BRK/RETB --> 4 bytes
3DS I2C MCU - RL78 SFR Registers (Special Function Registers) (I/O ports)
-------------------------------------------------------------------------
Datasheets
SFRs are documented in RL78 Hardware Manuals. However, the SFRs aren't 100%
same for all RL78 chips. The "78K0R/KC3-L, 78K0R/KE3-L" datasheet appears to be
pretty close to the 3DS hardware (aside from the F0500h-F07FFh area).
SFR List
Addr Access Reset Symbol Special Function Register (SFR)
FFF00h R/W 1B- 00h P0 Port data 0
FFF01h R/W 1B- 00h P1 Port data 1
FFF02h R/W 1B- 00h P2 Port data 2
FFF03h R/W 1B- 00h P3 Port data 3
FFF04h R/W 1B- 00h P4 Port data 4
FFF05h R/W 1B- 00h P5 Port data 5
FFF06h R/W 1B- 00h P6 Port data 6
FFF07h R/W 1B- 00h P7 Port data 7
FFF08h R/W 1B- 00h P8 Port data 8 (N/A)
FFF09h R/W 1B- 00h P9 Port data 9 (N/A)
FFF0Ah R/W 1B- 00h P10 Port data 10 (N/A)
FFF0Bh R/W 1B- 00h P11 Port data 11 (78K0R/K E3-L)
FFF0Ch R/W 1B- Undef P12 Port data 12
FFF0Dh R/W 1B- 00h P13 Port data 13 (78K0R/K E3-L)
FFF0Eh R/W 1B- 00h P14 Port data 14
FFF0Fh R/W 1B- 00h P15 Port data 15 (N/A)
FFF10h R/W -BW 0000h SDR00 Serial data 00 (TXD0/SIO00)
FFF12h R/W -BW 0000h SDR01 Serial data 01 (RXD0/SIO01)
FFF14h R/W -BW 0000h SDR12 Serial data 12 (TXD3/SIO30)
FFF16h R/W -BW 0000h SDR13 Serial data 13 (RXD3/SIO31)
FFF18h R/W --W 0000h TDR00 Timer data 00
FFF1Ah R/W -BW 0000h TDR01(L/H) Timer data 01 (NOT L/H)
FFF1Eh R --W 0000h ADCR 10-bit A/D conversion result
FFF1Fh R -B- 00h ADCRH 8-bit A/D conversion result
FFF20h R/W 1B- FFh PM0 Port mode 0
FFF21h R/W 1B- FFh PM1 Port mode 1
FFF22h R/W 1B- FFh PM2 Port mode 2
FFF23h R/W 1B- FFh PM3 Port mode 3
FFF24h R/W 1B- FFh PM4 Port mode 4
FFF25h R/W 1B- FFh PM5 Port mode 5
FFF26h R/W 1B- FFh PM6 Port mode 6
FFF27h R/W 1B- FFh PM7 Port mode 7
FFF28h R/W 1B- FFh PM8 Port mode 8 (N/A)
FFF29h R/W 1B- FFh PM9 Port mode 9 (N/A)
FFF2Ah R/W 1B- FFh PM10 Port mode 10 (N/A)
FFF2Bh R/W 1B- FFh PM11 Port mode 11 (78K0R/K E3-L)
FFF2Ch R/W 1B- FFh PM12 Port mode 12
FFF2Dh - --- - PM13 Port mode 13 (N/A)
FFF2Eh R/W 1B- FFh PM14 Port mode 14
FFF2Fh R/W 1B- FFh PM15 Port mode 15 (N/A) (3DS)
FFF30h R/W 1B- 00h ADM0 A/D converter mode 0
FFF31h R/W 1B- 00h ADS Analog input channel specification
FFF32h R/W 1B- 00h ADM1 A/D converter mode 1 (N/A)
FFF37h R/W 1B- 00h KRM Key return mode
FFF38h R/W 1B- 00h EGP0 External interrupt rising edge enable 0
FFF39h R/W 1B- 00h EGN0 External interrupt falling edge enable 0
FFF3Ah R/W 1B- 00h EGP1 External int rising edge enable 1 (E3-L)
FFF3Bh R/W 1B- 00h EGN1 External int falling edge enable 1 (E3-L)
FFF3Ch R/W 1B- 00h ISC Input switch control register (!)
FFF3Eh R/W 1B- 00h TIS0 Timer input select register 0 (!)
FFF44h R/W -BW 0000h SDR02 Serial data 02 (TXD1/SIO10)
FFF46h R/W -BW 0000h SDR03 Serial data 03 (RXD1/SIO11)
FFF48h R/W -BW 0000h SDR10 Serial data 10 (TXD2/SIO20) (78K0R/K E3-L)
FFF4Ah R/W -BW 0000h SDR11 Serial data 11 (RXD2/SIO21) (78K0R/K E3-L)
FFF50h R/W -B- 00h IICA0 I2C IICA shift 0
FFF51h R 1B- 00h IICS0 I2C IICA status 0
FFF52h R/W 1B- 00h IICF0 I2C IICA flag 0
;FFF54h R/W -B- 00h IICA1 I2C IICA shift 1 (N/A)
;FFF55h R 1B- 00h IICS1 I2C IICA status 1 (N/A)
;FFF56h R/W 1B- 00h IICF1 I2C IICA flag 1 (N/A)
FFF64h R/W --W 0000h TDR02 Timer data 02
FFF66h R/W -BW 0000h TDR03(L/H) Timer data 03 (NOT L/H)
FFF68h R/W --W 0000h TDR04 Timer data 04
FFF6Ah R/W --W 0000h TDR05 Timer data 05
FFF6Ch R/W --W 0000h TDR06 Timer data 06
FFF6Eh R/W --W 0000h TDR07 Timer data 07
FFF70h R/W --W 0000h TDR10 Timer data 10 (N/A)
FFF72h R/W -BW 0000h TDR11(L/H) Timer data 11 (N/A)
FFF74h R/W --W 0000h TDR12 Timer data 12 (N/A)
FFF76h R/W -BW 0000h TDR13(L/H) Timer data 13 (N/A)
FFF78h R/W --W 0000h TDR14 Timer data 14 (N/A)
FFF7Ah R/W --W 0000h TDR15 Timer data 15 (N/A)
FFF7Ch R/W --W 0000h TDR16 Timer data 16 (N/A)
FFF7Eh R/W --W 0000h TDR17 Timer data 17 (N/A)
FFF80h Undoc:
FFF81h Undoc:
FFF82h Undoc:
FFF83h Undoc:
FFF84h Undoc:
FFF85h Undoc:
FFF86h Undoc:
FFF87h Undoc:
FFF88h Undoc:
FFF89h Undoc: something?
FFF8Ah Undoc: something?
FFF8Bh Undoc: Serial TOOL0 stat/ack
FFF8Ch Undoc: Serial TOOL0 control
FFF8Dh Undoc: Serial TOOL0 bauds.lsb
FFF8Eh Undoc: Serial TOOL0 bauds.msb
FFF8Fh Undoc: Serial TOOL0 data
FFF90h R/W --W 0000h RSUBC Sub-count register (!) (3DS) ;\either
(FFF90h)R/W --W 0FFFh ITMC Interval timer control (N/A) ;/or
FFF92h R/W -B- 00h SEC Second count
FFF93h R/W -B- 00h MIN Minute count
FFF94h R/W -B- 12h HOUR Hour count (12 AM upon reset)
FFF95h R/W -B- 00h WEEK Week count (uh, week??????)
FFF96h R/W -B- 01h DAY Day count
FFF97h R/W -B- 01h MONTH Month count
FFF98h R/W -B- 00h YEAR Year count
FFF99h R/W -B- 00h SUBCUD Watch error correction
FFF9Ah R/W -B- 00h ALARMWM Alarm minute
FFF9Bh R/W -B- 12h ALARMWH Alarm hour
FFF9Ch R/W -B- 00h ALARMWW Alarm week
FFF9Dh R/W 1B- 00h RTCC0 Real-time clock control 0
FFF9Eh R/W 1B- 00h RTCC1 Real-time clock control 1
FFF9Fh R/W 1B- 00h RTCC2 Real-time clock control 2 (!)
FFFA0h R/W -B- 00h CMC Clock operation mode control
FFFA1h R/W 1B- C0h CSC Clock operation status control
FFFA2h R 1B- 00h OSTC Osc stabilization time counter status
FFFA3h R/W -B- 07h OSTS Osc stabilization time select
FFFA4h R/W 1B- 00h CKC System clock control
FFFA5h R/W 1B- 00h CKS0 Clock output select 0
FFFA6h R/W 1B- 00h CKS1 Clock output select 1 (N/A) (Old3DS)
FFFA8h R -B- Undef RESF Reset control flag
FFFA9h R/W 1B- 00h LVIM Low-Voltage detection
FFFAAh R/W 1B- var LVIS Low-Voltage detection level (reset=xxh)
FFFABh R/W -B- var WDTE Watchdog timer enable (reset=1Ah/9Ah)
FFFACh R/W -B- 00h CRCIN CRC input (N/A)
FFFB0h R/W -B- 00h DSA0 DMA SFR address 0
FFFB1h R/W -B- 00h DSA1 DMA SFR address 1
FFFB2h R/W -BW 0000h DRA0(L/H) DMA RAM address 0
FFFB4h R/W -BW 0000h DRA1(L/H) DMA RAM address 1
FFFB6h R/W -BW 0000h DBC0(L/H) DMA byte count 0
FFFB8h R/W -BW 0000h DBC1(L/H) DMA byte count 1
FFFBAh R/W 1B- 00h DMC0 DMA mode control 0
FFFBBh R/W 1B- 00h DMC1 DMA mode control 1
FFFBCh R/W 1B- 00h DRC0 DMA operation control 0
FFFBDh R/W 1B- 00h DRC1 DMA operation control 1
FFFBEh R/W 1B- 00h BECTL Background event control register (!)
FFFBFh 1 Undoc:
FFFC0h - --- Undef PFCMD (used in the self programming library) (!)
FFFC1h 1B Undoc:
FFFC2h - --- 00h PFS (used in the self programming library) (!)
FFFC4h - --- 00h FLPMC (used in the self programming library) (!)
FFFC5h 1 Undoc:
FFFC6h B Undoc:
FFFC7h B Undoc:
FFFC8h W Undoc:
FFFCAh B Undoc:
FFFCBh B Undoc:
FFFCCh W Undoc:
FFFCEh W Undoc:
FFFD0h R/W 1BW 0000h IF2(L/H) Interrupt request flag 2
FFFD2h R/W 1BW 00h IF3(L) Interrupt request flag 3L (N/A)
FFFD4h R/W 1BW FFFFh MK2(L/H) Interrupt mask flag 2
FFFD6h R/W 1BW FFh MK3(L) Interrupt mask flag 3L (N/A)
FFFD8h R/W 1BW FFFFh PR02(L/H) Priority specification flag 02
FFFDAh R/W 1BW FFh PR03(L) Priority specification flag 03L (N/A)
FFFDCh R/W 1BW FFFFh PR12(L/H) Priority specification flag 12
FFFDEh R/W 1BW FFh PR13(L) Priority specification flag 13L (N/A)
FFFE0h R/W 1BW 0000h IF0(L/H) Interrupt request flag 0
FFFE2h R/W 1BW 0000h IF1(L/H) Interrupt request flag 1
FFFE4h R/W 1BW FFFFh MK0(L/H) Interrupt mask flag 0
FFFE6h R/W 1BW FFFFh MK1(L/H) Interrupt mask flag 1
FFFE8h R/W 1BW FFFFh PR00(L/H) Priority specification flag 00
FFFEAh R/W 1BW FFFFh PR01(L/H) Priority specification flag 01
FFFECh R/W 1BW FFFFh PR10(L/H) Priority specification flag 10
FFFEEh R/W 1BW FFFFh PR11(L/H) Priority specification flag 11
FFFF0h R/W --W 0000h MDAL Multiplication/division data A (L) (MULA)
FFFF2h R/W --W 0000h MDAH Multiplication/division data A (H) (MULB)
FFFF4h R/W --W 0000h MDBH Multiplication/division data B (H) (MULOH)
FFFF6h R/W --W 0000h MDBL Multiplication/division data B (L) (MULOL)
FFFF8h ??? ??? ????h SP(L/H) CPU Stack Pointer ;\
FFFFAh R/W ??? ??h PSW CPU Program Status Word ;
FFFFBh W -B- -- - CPU Reserve (for MUL/DIV opcodes) ; Fixed
FFFFCh ??? ??? 00h CS CPU Program Counter Bank ; SFRs
FFFFDh ??? ??? ??h ES CPU Data Bank ;
FFFFEh R/W 1B- 00h PMC CPU Processor mode control ;
FFFFFh ??? ??? ??h MEM CPU ... whatever? ;/
F0060h R/W 1B- 00h NFEN0 Noise filter enable 0 (!) ;\(!)
F0061h R/W 1B- 00h NFEN1 Noise filter enable 1 (!) ;/
F00C0h B Undoc:
F00C1h B Undoc:
F00C2h W Undoc:
F00C4h W Undoc:
F00C8h W Undoc:
Overlapping
ADDW AX,saddrp can also be used for first some SFR's FFF00..FFF1F
CLRB saddr can also be used for first some SFR's FFF00..FFF1F
addr16 can be used for further SFRs FFF20..FFFFF
SFR_SP/PSW/ES can be used as alias for SP/PSW/ES
SFR_AX/BC/DE/HL can be used as alias for AX/BC/DE/HL - but banked!
SFR_CS ... can be manually changed BEFORE JMP/CALL AX to make FAR-JMP... ?
Nocash Syntax
Native Nocash
CLRB/CLRW/CMP0 op MOV/MOVW/CMP op,0
ONEB/ONEW op MOV/MOVW op,1
ADDC/SUBC/ROLC/RORC/ROLWC ADC/SBC/RCL/RCR/RCRW/RCLW
BR/BF/BT/Bcond/BTCLR JMP/JZ/JNZ/Jcond/JNZCLR
CALLT CALL
MULU X MULU AX,A,X ;optional alias
Identifier Description
? [HL + byte], [DE + byte], [SP + byte] (only the space from F0000H
to FFFFFH is specifiable)
? word[B], word[C] (only the space from F0000H to FFFFFH is specifiable)
? word[BC] (only the space from F0000H to FFFFFH is specifiable)
? ES:[HL + byte], ES:[DE + byte] (higher 4-bit addresses are specified by
the ES register)
? ES:word[B], ES:word[C] (higher 4-bit addresses are specified by
the ES register)
? ES:word[BC] (higher 4-bit addresses are specified by the ES register)
MCU-FIRM
00001F02 MCU v0, v1026, v2048, v3072, v4102, v5122, v6145, v7168, v8192
20001F02 New_3DS MCU v8192, v9216(New2DSXL)
00001F03 SAFE_MODE MCU v0
20001F03 New_3DS SAFE_MODE MCU v9217
Register Description
The register space allows single-byte reads and writes, as well as burst reads
and writes. When performing burst reads or writes, the memory pointer will
increment until reading or writing is terminated by the master, or until the
memory pointer reaches "certain reserved registers between 21h and 3Ch" (uh,
that would include GYRO_ZOUT at 21h and/or 22h?).
Note that any bit that is not defined should be set to zero.
GYRO[16h] - DLPF_FS - Low Pass Filter and Full Scale Config (R/W)
0-2 DLPF_CFG Digital low pass filter bandwidth & internal sample rate
3-4 FS_SEL Full scale selection for gyro sensor data
5-7 Reserved (should be 0)
FS_SEL Gyro Full-Scale Range:
0 Reserved (despite of being power-up default)
1 Reserved
2 Reserved
3 +/-2000�/sec (this should be used)
DLPF_CFG, Low Pass Filter Bandwidth, Internal Sample Rate:
0 Internal Sample Rate=8kHz, Low Pass Filter Bandwidth=256Hz
1 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=188Hz
2 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=98Hz
3 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=42Hz
4 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=20Hz
5 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=10Hz
6 Internal Sample Rate=1kHz, Low Pass Filter Bandwidth=5Hz
7 Reserved
NEW_GYRO[00h..0Dh] - Reserved/Undocumented
Reading these fourteen registers returns following weird values:
BD DB D1 29 9C 1D 20 67 F4 1A 8C 08 B1 71
There should be 10bit temperature calibration values, but 9C1Dh,67F4h,8C08h
exceed 10bit range.
The first two bytes (BDh,DBh) seem to resemble the 1st/2nd bytes of older RS232
gyroscope protocols.
NXP SC16IS750
Single UART with I2C-bus/SPI interface, 64 bytes of transmit and receive FIFOs,
IrDA SIR built-in support - Rev. 06 - 13 May 2008 Product data sheet
I2C Device 2:9Ah
Infrared Signals
The SC16IS750 UART/IrDA SIR datasheet does mainly describe the UART part, and
barely mentions infrared at all (apart from saying that the chip is IrDA SIR
compatible, and that IrDA can be enabled in MCR.bit6).
Going by other sources, IrDA SIR works like "UART over infrared". In lack of
further details, here are some guesses on how it might work (and how far it is
(or isn't) compatible with regular cable-based UARTs):
- RX/TX are probably using pulsed signals instead of constant LOW/HIGH levels?
- RTS/CTS/DTR/DSR are probably not implemented at all?
- Simultaneous RX+TX might work in opposite light-direction, if no reflection?
- Infrared interruptions and noise may require additional error checking?
- Infrared at less than 10mm (as in Circle Pad Pro) may work 100% error-free?
Infrared Protocol
Specifications for the IrDA standard aren't available for free, and there's
little known about the protocol:
- IrDA protocol supports file transfers from one device to another
- IrDA protocol must include some sort of packet headers and checksums
- And probably much stuff
However, it's unknown if Nintendo did bother to follow the IrDA standard in
their Circle Pad Pro and NFC add-ons. It's also possible that they have just
used a custom UART-like transfer protocol for that hardware.
Infrared Range
IrDA is supposed for short-range transfers (about 20cm - 100cm) in binary
format. As such, it isn't intended to use the hardware for things like classic
TV remote controls (although... maybe it could be tweaked to output TV remote
signals on TX pin... possibly in UART mode with IrDA disabled?).
I2C Access
I2C writing works as for most other I2C chips:
I2cWriteCmd (Device+0, Index, Data)
However, I2C reading works uncommon:
I2cWriteCmd (Device+0, 40h, ReadIndex)
I2cReadCmd (Device+1, ReadIndex, Data)
Ie. the LCD chips distinguish between WriteIndex and ReadIndex, with the
ReadIndex being set by writing to register 40h. The ReadIndex value in the
response can be ignored (or verified to be same as the written ReadIndex
value).
I2C Registers
00h Zero (-)
01h Display on/off (10h=Display on, 11h=Display black) ;bit0,4 is R/W
02h Usually 01h, but bit0 is R/W
03h Usually 00h, but bit0-7 is R/W
04h..10h Zero (-)
11h Whatever (set to 10h during init, maybe bit4=reset?)
12h..3Fh Zero (-)
40h Read Index for I2C read (00h..FFh)
41h..4Fh Zero (-)
50h Bit0 is R/W (set to 1 for top-screen; left 0 on bottom-screen)
51h..53h Zero (-)
54h Usually 00h, but bit0 is R/W
55h Usually 00h, but bit0-1 is R/W
56h..5Fh Zero (-)
60h Whatever (set to 00h during init) ;bit0 is R/W ?
61h Status (initially B4h=Top Screen, F8h=Bottom Screen) (R?)
62h Status (01h=Ready) (except, broken top screen reads 00h?) (R?)
63h Zero (-)
64h Whatever/Fixed 03h (R)
65h..AEh Zero (-)
AFh Usually 00h, but bit0-7 is R/W
B0h..D3h Zero (-)
D4h Usually 00h, but lower 4bit are R/W
D5h Usually 00h, but bit0-7 is R/W
D6h..FDh Zero (-)
FEh Usually 00h, but bit0-7 is R/W
FFh Maybe Chip ID (10h=Top Screen, C7h=Bottom Screen) (R)
Odd effect observed during testing: Setting LCD[AFh]=AAh causes MANY more
registers to become nonzero; this doesn't happen for other values like
LCD[AFh]=0Fh,F0h,FFh.
MIPI DSI
// LCD_I2C_REG_POWER - 01h
#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 - 11h
#define LCD_REG_UNK11_UNK10 (0x10u) // Written on init.
The command response payload is usually at least 1-byte, where that byte
appears to be normally 00h. For command requests the payload data is the
command parameters.
For command requests sent to the NFC tag itself, Cmd[1]=0x0 and CmdID=0x0. The
command request payload data here is the actual command request data for the
NFC tag, starting with the CmdID u8 at payload+0.
During NFC module startup, a certain command (?) is sent to the controller
which eventually (after various cmd-reply headers etc) returns the following
after the first byte in the payload:
000000: 44 65 63 20 32 32 20 32 30 31 32 31 34 3a 35 33 Dec 22 201214:53
000010: 3a 35 30 01 05 0d 46 05 1b 79 20 07 32 30 37 39 :50...F..y .2079
000020: 31 42 35 1B5
Or that is: "Dec 22 201214:53:50<binary>20791B5". Therefore, this appears to
return the part-number of the NFC controller (other command request(s) /
response(s) use this part-number value too).
Actually, 20791B5 seems to be NFC certification number for an unspecified
Broadcom product (or possibly 20791B5 is the product name itself... yes,
apparently it's Broadcom BCM20791).
Protocol = NFC Forum NFC Controller Interface (NCI) for host interface
Power-up
After power-up, the NFC chip automatically sends these bytes upon I2C reads:
10 60 00 02 00 01 ;followed by endless FF bytes
That seems to be a 4-byte header, with 2-byte data, as indicated in hdr[3]=02h.
NFC Interrupt
Triggers when there is data available for reading. Unknown if there is also a
way for determining if the thing is ready for writing a new command... maybe
one should simply wait for a response packet after sending any command packets?
Old3DS Version
The Old3DS did have an external NFC Adapter add-on, accessed via IrDA.
--> 3DS NFC Adapter
The 3DS OS is supposedly having backwards/forwards compatible NFC functions,
but the underlying transfer protocol seems to be completely different (relying
on IrDA to communicate with the adpater firmare, instead of directly accessing
the BCM20791 chip).
The Nintendo NFC adapter, formally Nintendo NFC Reader/Writer and codenamed
Fangate, is an external device which adds NFC capabilities for amiibos to old
Nintendo 3DS and Nintendo 2DS consoles, using the infrared port on the back of
the console.
It launched simultaneously with Animal Crossing Happy Home Designer, with which
it's optionally bundled; it can also be bought standalone at a nominal(?) price
of 21 EUR.
Technical details
Based on analysis of the fangate_updater.bin file, which is part of the old
Nintendo 3DS operating system since 9.3.0-21 and contains the firmware running
on the external adapter; and analysis of the NFC Services running on old 3DS.
SOC inside the adapter: Broadcom BCM20791B1
or ST proprietary "MCU-FGT/rev.A/GH24S VQ"
uh, either or? or rather both?
is that guessed from fangate_updater.bin,
or seen on photos of the actual pcb/hardware?
CPU: ARM Cortex M0
Memory map:
Address Size Description
08008000h 256KB? Firmware (fangate_updater.bin)
20000000h 128KB? RAM
40023C00h 1Ch FLASH ROM control
E000ED00h 104h ARM Cortex system control block
Layer 2 - "ircom"
ircom is a simple stateful point-to-point master-slave communication protocol
built on top of IR layer 1.
00h 4 Random (makes the whole packet look random after XOR encryption)
04h 1 bit4-7:RFU?, bit0-3:Protocol version (01h)
05h 1 Connection ID of master (3DS), value determined by master
06h 1 Connection ID of slave (NFC adapter), value determined by slave
07h 1 bit4-7:???, bit0-3: Operation code
08h N-8 Payload (if any)
Operation codes:
Code Name Has payload Direction
00h = Layer 3 command Yes Master to slave
01h = ???
02h = ???
03h = ???
04h = ???
05h = ???
06h = ???
07h = ???
08h = ???
09h = ???
0Ah = Disconnect request No Master to slave
0Bh = Disconnection acknowledgment No Slave to master
0Ch = Handshake No Master to slave
0Dh = Handshake acknowledgement No Slave to master
0Eh = ???
0Fh = ???
NFC adapter will ignore packets whose protocol version is not 1. It will not
even reply.
Connection identifier is a random byte the 3DS assigns to identify the
connection should there be several connections in range at once. Slave devices
must save this value from the initial handshake packet and use it for replies.
The 3DS will also save the connection identifier byte of the slave which is
also random. The 3DS must also ignore packets whose connection ID does not
match.
Layer 3
Layer 3 is the payload of layer 2. A lot is unknown of this layer and thus a
lot of assumptions were made in the following tables.
0000h
Acknowledgement message always send by slave. Payload always contains
000000AAh.
0004h
Payload contains firmware version and battery level of NFC adapter. Payload has
a size of 6 bytes.
00h Upper or lower byte of version number, newest firmware is 01h
01h Upper or lower byte of version number, newest firmware is 06h
02h Padding byte? Always 00h
03h Padding byte? Always 00h
04h Battery level (03h=Full, 00h=Empty)
05h Padding byte? Always 00h
NFC reader LED already turns red when the battery level byte is 02h, this will
also trigger a low battery level warning on the 3DS.
0100h
The purpose of this request by the master is unknown. Slave always responds
with ACK. Payload of this request is always 0003E8AAh.
0205h
Payload contains data regarding NFC communication. The first byte of the
payload means the following:
Code Description
00h = NFC communication is stopped as result of a 0202h request from master
01h = No NFC tag on top of the reader
02h = Busy dumping NFC tag
03h = NFC tag dump after write by master
04h = NFC tag fully dumped
05h = NFC tag dump after write by master
07h = NFC tag not a NTAG215 or contains no Amiibo compatible data
08h = NFC tag removed from reader
After the tag is written by the master and dumped again, the first few dumps
start with 03h, this changes to 05h after a few dumps. The reason for this is
unknown.
0206h
Request from master to start NFC communication. Payload always contains 19 00h
padding bytes, followed by C80300393A737486000001h and another 26 00h padding
bytes.
0207h
Request from master to write to NFC tag. The request packet already contains
the desired data to be written to the tag. Payload start with two 00h padding
bytes followed by the 7 ID bytes of the tag. These ID bytes are used by the NFC
adapter to check if same Amiibo is placed on the NFC adapter again.
Samples
NFC handshake beacons:
Layer 1 packet Layer 2 packet Layer 3 packet
A5 00 08 73 FE A5 C4 A4 2C A4 20 F5 9A 9D D6 3A 01 E8 00 0C ?
A5 00 08 D1 3E B7 7B B6 91 B6 9D 87 38 5D 66 45 01 EA 00 0C ?
A5 00 08 09 58 23 36 22 DA 22 D6 AE E0 3B 2A 6E 01 EC 00 0C ?
A5 00 08 5E DD A4 A0 A5 4E A5 42 A8 B7 BE FA 7D 01 EE 00 0C ?
A5 00 08 BC 19 C6 37 C7 C7 C7 CB 8B 55 7A 7A 2E 01 F0 00 0C ?
A5 00 08 C9 15 F6 63 F7 91 F7 9D B2 20 76 3F 76 01 F2 00 0C ?
A5 00 08 6E 48 47 1A 46 EE 46 E2 C7 87 2B 29 52 01 F4 00 0C ?
A5 00 08 A2 8C E5 C3 E4 35 E4 39 74 4B EF 47 4F 01 F6 00 0C ?
A5 00 08 26 1C 07 10 06 E8 06 E4 64 CF 7F 21 0C 01 F8 00 0C ?
A5 00 08 7E 73 A2 3F A3 C5 A3 C9 FD 97 10 DC 4C 01 FA 00 0C ?
A5 00 08 75 00 F3 B8 F2 44 F2 48 63 9C 63 86 B8 01 FC 00 0C ?
A5 00 08 8D AC 0F D5 0E 2B 0E 27 72 64 CF 82 79 01 FE 00 0C ?
A5 00 08 A3 55 7C 53 7D 52 7D 5E B2 4A 36 DF 06 01 01 00 0C ?
A5 00 08 15 06 43 C0 42 C3 42 CF 85 FC 65 56 C6 01 03 00 0C ?
A5 00 08 66 E0 9A 17 9B 12 9B 1E A0 8F 83 FC F7 01 05 00 0C ?
A5 00 08 A4 35 09 97 08 90 08 9C 25 4D 56 AD A2 01 07 00 0C ?
A5 00 08 73 E2 BD AF BC A6 BC AA 60 9A 81 CE 4D 01 09 00 0C ?
A5 00 08 02 57 D7 B0 D6 BB D6 B7 28 EB 34 D5 E7 01 0B 00 0C ?
A5 00 08 0D 79 01 AA 00 A7 00 AB 22 E4 1A 0C D3 01 0D 00 0C ?
A5 00 08 14 91 04 B9 05 B6 05 BA B2 FD F2 10 28 01 0F 00 0C ?
A5 00 08 2C 86 B1 49 B0 58 B0 54 C0 C5 E5 9D CF 01 11 00 0C ?
A5 00 08 D5 1D DE DB DF C8 DF C4 F9 3C 7E 0B C6 01 13 00 0C ?
A5 00 08 AF 75 DE 5C DF 49 DF 45 9C 46 16 71 29 01 15 00 0C ?
A5 00 08 C8 E2 5B C6 5A D1 5A DD B5 21 81 93 24 01 17 00 0C ?
A5 00 08 9B 51 68 2D 69 34 69 38 41 72 32 F3 7C 01 19 00 0C ?
A5 00 08 13 7B 9F EF 9E F4 9E F8 32 FA 18 8C 94 01 1B 00 0C ?
A5 00 08 A7 62 02 9C 03 81 03 8D BD 4E 01 A5 FE 01 1D 00 0C ?
A5 00 08 39 06 94 36 95 29 95 25 09 D0 65 AD 30 01 1F 00 0C ?
A5 00 08 32 4C D7 C0 D6 E1 D6 ED 92 DB 2F E5 8C 01 21 00 0C ?
A5 00 08 83 BE F2 8F F3 AC F3 A0 B1 6A DD 71 31 01 23 00 0C ?
A5 00 08 83 5E A0 57 A1 72 A1 7E F0 6A 3D 23 09 01 25 00 0C ?
A5 00 08 6E C8 AD 69 AC 4E AC 42 D1 87 AB C3 A1 01 27 00 0C ?
A5 00 08 C7 33 A1 2C A0 05 A0 09 FC 2E 50 66 1F 01 29 00 0C ?
External links
BCM2079x brief on Broadcom's website
Python scripts to sniff and spoof IR communication between the NFC reader and
3DS using an IrDA adapter
I2C Read(Device+1,Byte0,Byte1,Byte2,Byte3,...)
Reading returns some kind of array, always starting with the status value in
byte0, there is no need to write an index value before reading.
The array has useful info stored in first 4-7 bytes; and internal/garbage when
reading further bytes, up to including something that looks like a CPU stack).
The array entries are...
00h Status byte (80h..83h, or FFh) (power-up default=80h)
01h Button byte (00h=None, bit2=ZL, ?=ZR)
02h Analog X (00h=Center, -1xh=Left, +1xh=Right) ;\if enabled
03h Analog Y (00h=Center, -1xh=Down, +1xh=Up) ;/
Following bytes aren't needed, except for better 8bit X/Y resolution...
04h Fixed FFh
05h Analog X (00h=Center, -7xh=Left, +7xh=Right) ;\hires
06h Analog Y (00h=Center, -7xh=Down, +7xh=Up) ;/
Following bytes aren't actually useful...
07h Fixed 00h
08h Analog X (7xh=Center, FEh=Left, 00h=Right) ;\unsigned/uncentered
09h Analog Y (7xh=Center, FEh=Down, 00h=Up) ;/
0Ah Fixed 00h
0Bh Analog X (7xh=Center, FEh=Left, 00h=Right) ;\same as [08h,09h]
0Ch Analog Y (7xh=Center, FEh=Down, 00h=Up) ;/
0Dh Fixed 00h
0Eh Center X (7xh) ;\auto-calibrating, with minor changes
0Fh Center Y (7xh) ;/every some seconds
10h Fixed 00h
11h..15h Analog stuff
16h Flag (00h=Idle, 80h=Analog is/was recently touched)
17h Analog stuff
18h Flag (01h=Idle, 02h=Analog is/was recently left or down)
19h Analog stuff
Following bytes can crash the chip upon reading (see below for details):
1Ah Flag (01h=Idle, 00h/02h=Analog is/was recently somehow moved)
1Bh Fixed 01h
1Ch Fixed 11h
1Dh Historic X (7xh) ;\updated every some seconds
1Eh Historic Y (7xh) ;/(same as center when idle)
1Fh..27h Fixed 00h-filled
28h..2Ch Fixed 07h,06h,06h,03h,01h
2Dh..3Bh Fixed 00h-filled
3Ch Fixed 01h
3Dh..46h Fixed 00h-filled
47h..4Bh Fixed 04h,C0h,00h,00h,03h
4Ch Whatever, changes
4Dh Flag (00h=Idle, 01h=Analog is/was recently moved)
4Eh..54h Fixed 01h,00h,06h,01h,A5h,00h,00h
55h Initially random xxh, becomes 00h/01h after button/analog
56h Flag 00h/10h/20h
57h Analog X (00h=Center, -1xh=Left, +1xh=Right) ;\same as [02h,03h]
58h Analog Y (00h=Center, -1xh=Down, +1xh=Up) ;/
59h Analog
5Ah Analog
5Bh..65h Fixed 07h,00h,08h,04h,00h,00h,00h,09h,22h,71h,00h
66h Fast Timer (00h..1xh or so)
67h Fixed 15h ;maybe update period in ms, maybe limit for above timer?
68h Slow Timer (00h..08h, increasing)
69h..6Ch Fixed 09h,03h,00h,00h ;maybe 09h is limit for above timer?
6Dh Up/down Timer (00h=Idle, increases-then-decreases upon analog move)
6Eh..6Fh Fixed 00h,00h
70h Button byte (00h=None, bit4=ZL, ?=ZR)
71h Usually 00h (sometimes shortly 10h or so)
72h..74h Fixed 00h-filled
75h Fixed FFh
76h..7Bh Fixed 00h-filled
7Ch..82h Fixed 7Fh,15h,09h,03h,54h,28h,10h
83h..BDh Fixed 00h-filled
Following bytes might be CPU stack, first some bytes maybe random/garbage?
BEh 7Ah,02h,1Dh,D9h,C7h,93h,31h,CCh,7Eh,A9h,BEh,86h,B3h,93h,6Dh,07h
CEh C7h,82h,E7h,00h,10h,00h,00h,10h,00h,10h,00h,10h,xxh,xxh,xxh,xxh
DEh xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh,xxh
Following bytes seem to be used...
EEh..xxxx Fixed FFh-filled (somewhat endless repeating)
Caution: The chip hangs after some seconds when reading more than 1Ah bytes; at
that point all values get frozen (except, the "stack" at DDh..EDh does keep
changing).
I2C Write(Device,Mode)
Writing does set a mode value, eg. write(Device,Mode). There is no need to
write anything, the analog input and irq are automatically enabled on power-up.
Effects for different mode values are:
None Default is Status=80h at power-up
00h..51h Set Status=80h
52h..F4h Set Status=81h
F5h Set Status=82h
F6h..F9h Set Status=83h
FAh..FBh Set Status=81h
FCh..FDh Set Status=FFh
FEh Set Status=80h with long 1 second I2C-clk-hold delay?
FFh Set Status=80h
Unknown what those mode/status values are meaning exactly. Maybe some can
change polling interval or enable/disable interrupts, or maybe even do
dangerous stuff like reflashing the firmware?
Some of the mode values disable the Analog bytes at index 02h/03h (causing that
bytes to become always 00h, or maybe actually divide them by a large value,
causing them to be always NEAR 00h?)
Trying to write more bytes (eg. write(Device,xx,yy) seems to apply the last
written byte as mode value.
Operating System
The 3DS OS does access the C-stick via IR:RST service (probably for backwards
compatibility with Circle Pad Pro, which was accessed via infrared).
The OS can reportedly change the update period in range of 10..21ms (aka
0Ah..15h), maybe via whatever I2C write.
The OS does reportedly return analog values in range -9Ch..+9Ch, maybe that are
the I2C values scaled for Circle Pad Pro compatibility, or maybe a sum of
multiple I2C values?
Interrupt Pin
The IO Expander can trigger interrupts on any changes on any input pins.
Unknown if the Interrupt signal is connected in New3DS.
Bus/device 2:00h - Unknown, something responds here with ACK and FFh's
This is a special broadcast address (defined in I2C protocol). One (or more) of
the devices on I2C Bus 2 do apparently respond to it... and perhaps even
support some broadcast commands?
3DS Video
---------
LCD Registers
These registers are used to configure the LCD screens.
--> 3DS Video LCD Registers
Moreover, each screen is having an I2C-bus controller for further
configuration.
--> 3DS I2C LCD Screen Controllers
And, the MCU has enable flags for LCD Power Supplies and LCD Backlights.
GPU External Registers (for memory transfers, and framebuf to LCD output)
--> 3DS GPU External Registers - Memory Control/Status Registers
--> 3DS GPU External Registers - Top/Bottom Screen and Framebuffer Setup
--> 3DS GPU External Registers - Memfill and Memcopy
Sample Code
--> 3DS GPU Triangle Drawing Sample Code
This seems to be an interface between GPU video output and actual LCD screens.
The registers allow to control backlight brightness and to set a forced blank
color. Some other registers seem to be also affect backlight brightness (or
pixel brightness?); and maybe some do affect internal voltages or internal
backlight PWM timings?
The bootrom error screen initializes only a few of these registers (and leaves
the others at their power-up defaults). Many of the uninitialized registers
seem to have no effect on the visible picture, even when setting/clearing all
bits; some of them affect the brightness of the pixels or backlight (but only
if CtrlFlags.bit0=1).
The 3DS bootrom error screen initializes only 10400004h and 10400030h (VRAM
control/power). The 3DS OS does reportedly also initialize 10400050h and
10400054h (timings?).
Note: The values in the H/V registers are 12bit wide, 0..FFFh (the upper
4bit/20bit of the 16bit/32bit registers are unused, always zero).
Wrong H/V values may cause various effects - which may differ depending on the
display type. New3DS bottom screen tends to output a stable image (with fading
upper/right areas if it is too small), or no picture at all (with whole screen
fading). However, other screens are said to lose sync or misalign lines and
such stuff.
Framebuffers
These LCD framebuffers normally contain the last rendered frames from the GPU.
The framebuffers are drawn from left-to-right, instead of top-to-bottom. Thus
the beginning of the framebuffer is drawn starting at the left side of the
screen.
Further Registers
Apart from above GPU registers, the screens do also need initialization of the
"LCD" registers,
--> 3DS Video LCD Registers
plus, initialization of I2C registers for each screen. Plus some MCU/I2C
registers for backlight or so.
Notes...
"The DisplayTransfer registers are only used if FLAGS.bit3=0 and ignored
otherwise. The TextureCopy registers are "likewise" only used if FLAGS.bit3=1,
and ignored otherwise."
TextureCopy
When FLAGS.bit3=1, the hardware performs a TextureCopy-mode transfer. In this
mode, all other bits of that register are ignored (except for FLAGS.bit2, which
still needs to be set correctly?), and no format conversions are done.
Instead, it performs a raw data copy from the source to the destination, but
with a configurable gap between lines. The total amount of bytes to copy is
specified in the size register, and the hardware loops reading lines from the
input and writing them to the output until this amount is copied. The "gap"
specified in the input/output dimension register is the number of chunks to
skip after each "width" chunks of the input/output, and is NOT counted towards
the total size of the transfer.
By correctly calculating the input and output gap sizes it is possible to use
this functionality to copy arbitrary sub-rectangles between differently-sized
framebuffers or textures, which is one of its main uses over a regular
no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's
important to remember that the contents of a tile are laid out sequentially in
memory, and so this should be taken into account when calculating the transfer
parameters.
Specifying invalid/junk values for the TextureCopy dimensions can result in the
GPU hanging while attempting to process this TextureCopy.
Aliases
It is possible for multiple register (sequential) IDs to correspond to the same
register. This is done to leverage the consecutive writing mode for GPU
commands, which makes it possible for a single command to write data to
multiple sequential register IDs. For example, register IDs 02C1 through 02C8
all correspond to GPUREG_VSH_FLOATUNIFORM_DATAi so that a consecutively writing
command based at 02C0 will write its first parameter to
GPUREG_VSH_FLOATUNIFORM_INDEX and ever subsequent ones to
GPUREG_VSH_FLOATUNIFORM_DATAi
Data Types
signed Signed integer
unsigned Unsigned integer
floatX.Y.Z Floating-point number with X sign bits, Y exponent bits,
and Z mantissa bits
fixedX.Y.Z Fixed-point number with X sign bits, Y integer bits,
and Z fractional bits
float1.5.10 (16bit)
float1.7.12 (20bit) (uncommon, for light attentuation)
float1.7.16 (24bit)
float1.8.23 (32bit)
float1.7.24 (32bit) (uncommon, for viewport)
Commands (aka GPU registers writes) can be done by manually writing parameters
to register 10401000h-10401FFFh, or by using command lists.
With the command lists, the GPU does automatically read parameters and command
numbers from memory (and automatically pauses reading when it is busy).
Unknown why there are two command lists, supposedly they cannot execute
simultaneously... maybe the second list is automatically started at the end of
the other list?
Notes
Nintendo uses the IRQ registers to trigger a "FINALIZE" interrupt at end of
command list, done as so:
GPUREG_IRQ_MASK_LOW=FFFFFFF0h set upon GPU init ;\enable first four IRQs
GPUREG_IRQ_MASK_HIGH=FFFFFFFFh set upon GPU init ;/
GPUREG_IRQ_AUTOSTOP=1 ;-autostop cmdlist upon IRQ
GPUREG_IRQ_CMP(0)=12345678h set upon GPU init ;-first four compare values
GPUREG_IRQ_ACK(0)=00000000h set upon GPU init and before cmdlist
GPUREG_IRQ_REQ(0)=12345678h set via PICA(0010h) FINALIZE at end of cmdlist
Due to the 32bit writes, that will actually trigger four byte-matches at once.
Caution:
The GPU command list can write to GPUREG_IRQ_REQ(n), but all other registers in
range PICA(0000h..003Fh) are writeable by CPU only, not via command lists.
ATTR_BUF arrays contain vertex attributes (such like coordinates and colors).
The GPU can automatically transfer data from these arrays to the shader unit
(which does then forward the data to the drawing hardware).
There are up to 12 arrays for up to 12 attributes (one can either store
multiple attributes in one single array, or store different attributes in
separate arrays).
There are four shader units, each having its own set of I/O registers:
10401A00h - PICA(0280h..) - Shader 0 (Geometry Shader, aka GSH)
10401AC0h - PICA(02B0h..) - Shader 1 (Vertex Shader, aka VSH)
10401B80h - PICA(02E0h..) - Shader 2 (Unknown purpose)
10401C40h - PICA(0310h..) - Shader 3 (Unknown purpose)
The vertex shader can reportedly use three shader units at once (or all four
units, when not using the geometry shader). Even when using multiple units as
vertex shader, one does only need to initialize the Shader 1 registers.
Unknown if the Shader 2 and 3 registers are having any special purpose for yet
unknown special effects (maybe for the undescribed "reserved geometry shader
subdivision" feature, or maybe for the "procedural texture" unit, or maybe they
are just dummy registers).
Uniform registers can contain general purpose constants. That is, they are
usually kept set to constant values throughout sending multiple vertices
(unlike position/texture coordinates or other vertex attributes that differ on
each vertex).
Early Depth is something about drawing only depth values (without computing and
drawing colors/textures) for pre-checking if the polygon is visible... if so,
something is probably required to actually draw the color/texture part...?
Overview
Procedural texture generation has four stages:
Noise Module (outputs u',v')
Repeat Module (outputs u'',v'')
Base Shape (also notated as G(u'',v''), output g)
F(g) and Lookup Table
Noise Module
This stage applies noise on the input coordinates. Little is known about this
other than that there are three noise parameters: Amplitude, Frequency, and
Phase.
Repeat Module
This stage performs basic texture coordinate wrapping on the noised
coordinates. It supports symmetric and mirrored wrapping. They don't seem to be
configurable beyond that.
Base Shape
The U'' and V'' coordinates are used to generate a scalar value in the range
[0;1] from the wrapped coordinates using one of six functions.
The output of this function is named "g".
_______________________
Overview
A compiled shader binary is comprised of two parts: the main instruction
sequence and the operand descriptor table. These are both sent to the GPU
around the same time but using separate GPU Commands. Instructions (such as
format 1 instruction) may reference operand descriptors. When such is the case,
the operand descriptor ID is the offset, in words, of the descriptor within the
table. Both instructions and descriptors are coded in little endian. Basic
implementations of the following specification can be found at [1] and [2]. The
instruction set seems to have been heavily inspired by Microsoft's vs_3_0 [3]
and the Direct3D shader code [4]. Please note that this page is being written
as the instruction set is reverse engineered; as such it may very well contain
mistakes.
Nomenclature
- opcode names with I appended to them are the same as their non-I version,
except they use the inverted instruction format, giving 7 bits to SRC2
(and access to uniforms) and 5 bits to SRC1
- opcode names with U appended to them are the same as their non-U version,
except they are executed conditionally based on the value of a uniform
boolean.
- opcode names with C appended to them are the same as their non-C version,
except they are executed conditionally based on a logical expression
specified in the instruction.
Instruction formats
Offset Size (bits) Description
Format 1: (used for register operations)
0x0 0-6 0x7 Operand descriptor ID (DESC)
0x7 7-11 0x5 Source 2 register (SRC2)
0xC 12-18 0x7 Source 1 register (SRC1)
0x13 19-20 0x2 Address register index for SRC1 (IDX_1)
0x15 21-25 0x5 Destination register (DST)
0x1A 26-31 0x6 Opcode
Format 1i: (used for register operations)
0x0 0-6 0x7 Operand descriptor ID (DESC)
0x7 7-13 0x7 Source 2 register (SRC2)
0xE 14-18 0x5 Source 1 register (SRC1)
0x13 19-20 0x2 Address register index for SRC2 (IDX_2)
0x15 21-25 0x5 Destination register (DST)
0x1A 26-31 0x6 Opcode
Format 1u: (used for unary register operations)
0x0 0-6 0x7 Operand descriptor ID (DESC)
7 7-11 5 ?
0xC 12-18 0x7 Source 1 register (SRC1)
0x13 19-20 0x2 Address register index for SRC1 (IDX_1)
0x15 21-25 0x5 Destination register (DST)
0x1A 26-31 0x6 Opcode
Format 1c: (used for comparison operations)
0x0 0-6 0x7 Operand descriptor ID (DESC)
0x7 7-11 0x5 Source 2 register (SRC2)
0xC 12-18 0x7 Source 1 register (SRC1)
0x13 19-20 0x2 Address register index for SRC1 (IDX_1)
0x15 21-23 0x3 Comparison operator for Y (CMPY)
0x18 24-26 0x3 Comparison operator for X (CMPX)
0x1B 27-31 0x5 Opcode (5bit only)
Format 2: (used for flow control instructions)
0x0 0-7 0x8 Number of instructions (NUM)
8 8-9 ? ?
0xA 10-21 0xC Destination offset (in words) (DST)
0x16 22-23 0x2 Condition boolean operator (CONDOP)
0x18 24 0x1 Y reference bit (REFY)
0x19 25 0x1 X reference bit (REFX)
0x1A 26-31 0x6 Opcode
Format 3: (used for uniform-based conditional flow control instructions)
0x0 0-7 0x8 Number of instructions ? (NUM)
8 8-9 ? ?
0xA 10-21 0xC Destination offset (in words) (DST)
0x16 22-25 0x4 Uniform ID (BOOL/INT)
0x1A 26-31 0x6 Opcode
Format 4: (used for SETEMIT)
0 0-21 ? ?
0x16 22 0x1 Winding flag (FLAG_WINDING)
0x17 23 0x1 Primitive emit flag (FLAG_PRIMEMIT)
0x18 24-25 0x2 Vertex ID (VTXID)
0x1A 26-31 0x6 Opcode
Format 5: (used for MAD)
0x0 0-4 0x5 Operand descriptor ID (DESC)
0x5 5-9 0x5 Source 3 register (SRC3)
0xA 10-16 0x7 Source 2 register (SRC2)
0x11 17-21 0x5 Source 1 register (SRC1)
0x16 22-23 0x2 Address register index for SRC2 (IDX_2)
0x18 24-28 0x5 Destination register (DST)
0x1D 29-31 0x3 Opcode (3bit only)
Format 5i: (used for MADI)
0x0 0-4 0x5 Operand descriptor ID (DESC)
0x5 5-11 0x7 Source 3 register (SRC3)
0xC 12-16 0x5 Source 2 register (SRC2)
0x11 17-21 0x5 Source 1 register (SRC1)
0x16 22-23 0x2 Address register index for SRC3 (IDX_3)
0x18 24-28 0x5 Destination register (DST)
0x1D 29-31 0x3 Opcode (3bit only)
Instructions
Unless noted otherwise, SRC1 and SRC2 refer to their respectively indexed
float[4] registers (after swizzling). Similarly, DST refers to its indexed
register modulo destination component masking, i.e. an expression like DST=SRC1
might actually just set DST.y to SRC1.y.
Opcode Format Name Description
00h 1 ADD Adds two vectors component by component
DST[i] = SRC1[i]+SRC2[i] for all i
01h 1 DP3 Computes dot product on 3-component vectors
DST = SRC1.SRC2
02h 1 DP4 Computes dot product on 4-component vectors
DST = SRC1.SRC2
03h 1 DPH Computes dot product on a 3-component vector
with 1.0 appended to it and a 4-component vector
DST = SRC1.SRC2 (with SRC1 homogenous)
04h 1 DST Equivalent to Microsoft's dst instruction
DST = {1, SRC1[1]*SRC2[1], SRC1[2], SRC2[3]}
05h 1u EX2 Computes SRC1's first component exponent with base 2
DST[i] = EXP2(SRC1[0]) for all i
06h 1u LG2 Computes SRC1's first component logarithm with base 2
DST[i] = LOG2(SRC1[0]) for all i
07h 1u LITP Appears to be related to Microsoft's lit instruction
DST = clamp(SRC1, min={0, -127.9961, 0, 0},
max={inf, 127.9961, 0, inf})
;note: 127.9961 = 0x7FFF / 0x100
08h 1 MUL Multiplies two vectors component by component
DST[i] = SRC1[i].SRC2[i] for all i
09h 1 SGE Sets output if SRC1 is greater than or equal to SRC2
DST[i] = (SRC1[i] >= SRC2[i]) ? 1.0 : 0.0
"for all i" ;uh, who/what is "all i"?
0Ah 1 SLT Sets output if SRC1 is strictly less than SRC2
DST[i] = (SRC1[i] < SRC2[i]) ? 1.0 : 0.0
"for all i"
0Bh 1u FLR Computes SRC1's floor component by component
DST[i] = FLOOR(SRC1[i])
"for all i"
0Ch 1 MAX Takes the max of two vectors, component by component
DST[i] = MAX(SRC1[i], SRC2[i])
"for all i"
0Dh 1 MIN Takes the min of two vectors, component by component
DST[i] = MIN(SRC1[i], SRC2[i])
"for all i"
0Eh 1u RCP Computes the reciprocal of the vector's 1st component
DST[i] = 1/SRC1[0]
"for all i"
0Fh 1u RSQ Computes the reciprocal of the square root of the
vector's first component;
DST[i] = 1/sqrt(SRC1[0])
"for all i"
10h-11h ? ??? ?
12h 1u MOVA Move to address register; Casts the float uniform
given by SRC1 to an integer (truncating the fractional
part) and assigns the result to (a0.x, a0.y, _, _),
respecting the destination component mask.
13h 1u MOV Moves value from one register to another
DST = SRC1
14h-17h ? ??? ?
18h 1i DPHI Computes dot product on a 3-component vector
with 1.0 appended to it and a 4-component vector;
DST = SRC1.SRC2 (with SRC1 homogenous)
19h 1i DSTI DST with sources swapped
1Ah 1i SGEI Sets output if SRC1 is greater than or equal to SRC2
DST[i] = (SRC1[i] >= SRC2[i]) ? 1.0 : 0.0
"for all i"
1Bh 1i SLTI Sets output if SRC1 is strictly less than SRC2
DST[i] = (SRC1[i] < SRC2[i]) ? 1.0 : 0.0
"for all i"
1Ch-1Fh ? ??? ?
20h 0 BREAK Breaks out of LOOP block; do not use while in
nested IF/CALL block inside LOOP block.
21h 0 NOP Does literally nothing.
22h 0 END Signals the shader unit that processing for this
vertex/primitive is done.
23h 2 BREAKC If condition (see below for details) is true, then
breaks out of LOOP block.
24h 2 CALL Jumps to DST and executes instructions until it
reaches DST+NUM instructions
25h 2 CALLC If condition (see below for details) is true, then
jumps to DST and executes instructions until it
reaches DST+NUM instructions, else does nothing.
26h 3 CALLU Jumps to DST and executes instructions until it
reaches DST+NUM instructions if BOOL is true
27h 3 IFU If condition BOOL is true, then executes instructions
until DST, then jumps to DST+NUM; else, jumps to DST.
28h 2 IFC If condition (see below for details) is true, then
executes instructions until DST, then jumps
to DST+NUM; else, jumps to DST
29h 3 LOOP Loops over the code between itself and DST
(inclusive), performing INT.x+1 iterations in total.
First, aL is initialized to INT.y. After each
iteration, aL is incremented by INT.z.
2Ah 0 EMIT (geometry shader only) Emits a vertex (and primitive
if FLAG_PRIMEMIT was set in the corresponding
SETEMIT). SETEMIT must be called before this.
2Bh 4 SETEMIT (geometry shader only) Sets VTXID, FLAG_WINDING and
FLAG_PRIMEMIT for the next EMIT instruction. VTXID
is the ID of the vertex about to be emitted within
the primitive, while FLAG_PRIMEMIT is zero if we are
just emitting a single vertex and non-zero if are
emitting a vertex and primitive simultaneously.
FLAG_WINDING controls the output primitive's winding.
Note that the output vertex buffer (which holds 4
vertices) is not cleared when the primitive is
emitted, meaning that vertices from the previous
primitive can be reused for the current one. (this
is still a working hypothesis and unconfirmed)
2Ch 2 JMPC If condition (see below for details) is true, then
jumps to DST, else does nothing.
2Dh 3 JMPU If condition BOOL is true, then jumps to DST, else
does nothing. Having bit 0 of NUM = 1 will invert the
test, jumping if BOOL is false instead.
2Eh-2Fh 1c CMP Sets booleans cmp.x and cmp.y based on the operand's
x and y components and the CMPX and CMPY comparison
operators respectively. See below for details about
operators. It's unknown whether CMP respects the
destination component mask or not.
30h-37h 5i MADI Multiplies two vectors and adds a third one
component by component;
DST[i] = SRC3[i] + SRC2[i].SRC1[i]
"for all i"
"this is not an FMA, the intermediate result is
rounded"
38h-3Fh 5 MAD Multiplies two vectors and adds a third one
component by component;
DST[i] = SRC3[i] + SRC2[i].SRC1[i]
"for all i"
"this is not an FMA, the intermediate result
is rounded"
Relative addressing
IDX Address offset
00h +0 ;-no offset
01h +a0.x ;\X or Y component of address register (see MOVA)
02h +a0.y ;/
03h +lp ;-loop counter (see LOOP)
There are 3 address registers: a0.x, a0.y and aL (loop counter). For format 1
instructions, when IDX != 0, the value of the corresponding address register is
added to SRC1's value. For example, if IDX = 2, a0.y = 3 and SRC1 = c8, then
instead SRC1+a0.y = c11 will be used for the instruction. It is only possible
to use address registers with vector uniform registers, attempting to use them
with input attribute or temporary registers results in the address register
being ignored (i.e. read as zero).
a0.x and a0.y are set manually through the MOVA instruction by rounding a float
value to integer precision. Hence, they may take negative values.
Comparison operator
CMPX/CMPY raw value Operator name Expression
00h EQ src1 == src2
01h NE src1 != src2
02h LT src1 < src2
03h LE src1 <= src2
04h GT src1 > src2
05h GE src1 >= src2
06h ?? seems to always return true
07h ?? seems to always return true
Conditions
A number of format 2 instructions are executed conditionally. These conditions
are based on two boolean registers which can be set with CMP: cmp.x and cmp.y.
Conditional instructions include 3 parameters: CONDOP, REFX and REFY. REFX and
REFY are reference values which are tested for equality against cmp.x and
cmp.y, respectively. CONDOP describes how the final truth value is constructed
from the results of the two tests. There are four conditional expression
formats:
CONDOP raw value Expression Description
00h cmp.x == REFX || cmp.y == REFY OR
01h cmp.x == REFX && cmp.y == REFY AND
02h cmp.x == REFX X
03h cmp.y == REFY Y
Registers
Input attribute registers (v0-v7?) store the per-vertex data given by the CPU
and hence are read-only.
Output attribute registers (o0-o6) hold the data to be passed to the later GPU
stages and are write-only. Each of the output attribute register components is
assigned a semantic by setting the corresponding GPU_Internal_Registers.
Uniform registers hold user-specified data which is constant throughout all
processed vertices. There are 96 float[4] uniform registers (c0-c95),
eight(???) boolean registers (b0-b7), and four int[4] registers (i0-i3).
Temporary registers (r0-r15) can be used for intermediate calculations and can
both be read and written.
Many shader instructions which take float arguments have only 5 bits available
for the second argument. They may hence only refer to input attributes or
temporary registers. In particular, it's not possible to pass two float[4]
uniforms to these instructions.
It appears that writing twice to the same output register can cause problems
(eg. GPU hangs).
DST mapping:
DST raw value Register name Description
00h-06h? o0-o6? Output registers (aka output FIFO) (W)
10h-1Fh r0-r15 Temporary registers (R/W)
SRC1/SRC2/SRC3 mapping:
SRC raw value Register name Description
00h-07h? v0-v7? Input vertex/attribute (aka input FIFO) (R)
10h-1Fh r0-r15 Temporary registers
20h-7Fh c0-c95 Vector uniform registers (only for 7bit SRC)
Control Flow
Control flow is implemented using four independent stacks:
4-deep CALL stack
8-deep IF stack
4-deep LOOP stack
All stacks are initially empty. After every instruction but before JMP takes
effect, the PC is incremented and a copy is sent to each stack. Each stack is
checked against its copy of the PC. If an entry is popped from the stack, the
copied PC is updated and used for the next check of this stack, although the
IF/LOOP stacks can each only pop one entry per instruction, whereas the CALL
stack is checked again until it doesn't match or the stack is empty. The
updated PC copy with the highest priority wins: LOOP (highest), IF, CALL, JMP,
original PC (lowest).
Each set of writes to the 3 data registers specifies one attribute and all
attributes (as configured in GPUREG_VSH_NUM_ATTR) need to be written, in order,
to specify a vertex. Drawing happens automatically as vertices are specified.
After finishing specifying vertices, follow with the same writes used after a
draw arrays/elements.
Fragment lighting is a DMP extension to the standard OpenGL pipeline with which
applications can calculate object lighting for each rendered pixel instead of
just per vertex. The fragment lighting algorithm furthermore supports the
shading models Blinn-Phong, Cook-Terrance, Ward, and microfacet-based
BRDF-models. While the lighting calculations take place in a very localized
position of the pixel processing pipeline, the feature interacts with different
other pipeline stages.
Overview
In general, lighting is calculated at a particular point in space X by
determining the angles (i.e. dot products) between different vectors:
- The face normal vector N, which points from X to the direction
perpendicular to the lighted object
- The tangent vector T, which points from X to a direction which is
tangential to the lighted object
- The bitangent vector B, which points to a tangential direction such
that it is orthogonal to both N and T
- The view vector V, which points from X "into the camera"
- The light vector L, which points from X to the light source (note that
lighting is always evaluated separately for each light source; the
results for multiple light sources can simply be added to each other)
For example, in the Blinn-Phong shading model the dot product of L and N
determined the intensity of a lighting type called diffuse lighting. More
generally, the dot products between these vectors (from now on simply referred
to as "dot products") are combined to a lighting equation, which is evaluated
once per light source at each considered point in space.
Before pixel shaders were common, the lighting equation was only considered at
each vertex, and the output color was then interpolated across the triangle. To
achieve higher visual quality, pixel shaders can be used nowadays to evaluate
the lighting equation at each pixel. The PICA200 does not have a programmable
pixel shader, but has a fixed-function pipeline stage to achieve the same
quality.
In any case, per-pixel lighting requires to somehow obtain a normal vector for
each pixel. Theoretically, the vertex shader could output one normal vector per
vertex, and per-pixel normals could then be obtained by interpolating these
vectors in a specific way. This, however, is very inefficient, which is why
vertex shaders on the PICA200 instead output mathematical objects called
quaternions: Quaternions can be computed from normal/tangent vectors, and vice
versa, so no information is lost by doing so. However, quaternion interpolation
is a lot faster (see the "Kuijk and Blake" source below), and so the GPU can
compute per-pixel normals simply using the interpolated quaternion. This is
just the general idea, and the dirty mathematical details are explained below.
In any case: There is no vertex output attribute semantic for normal or tangent
vectors. To use fragment lighting, the shader must actually output an attribute
with the quaternion semantic. So some sort of conversion needs to happen from
normal and tangent vectors to quaternions. This can be done using the
surface-local matrix.
Quaternion Interpolation
Quaternion interpolation needs to happen to obtain a per-fragment quaternion,
from which in turn per-fragment normals and tangent vectors can be computed. It
is unknown how quaternions are interpolated on the PICA200. The architecture
suggests that plain linear interpolation is used, but there are also more
sophisticated algorithms like Slerp and Nlerp.
The Fresnel LUT can be used to, for example, blend two colours according to how
oblique the view angle is, or to simply additively blend white onto fragments
with an exponential falloff, resulting in rim lighting.
Resources
There is public literature available which describes the fragment lighting
feature in more detail:
- Everitt - "Per-Pixel Lighting": A presentation given at the Game
Developers Conference 2001 about per-pixel lighting. It doesn't have
anything to do with the PICA200 algorithm, but explains the core ideas
very well (especially the concepts of surface-local space and how it
relates to other coordinate systems).
- Kazakov and Ohbuchi - "Primitive Processing and Advanced Shading
Architecture for Embedded Space": Provides a general overview over the
fragment lighting algorithm used by the PICA200 and provides explicit
formulas for the primary and secondary lighting output. NOTE: There exist
both a scientific publication and a short presentation with this title.
Both are useful, but the former goes into much greater detail.
- Ohbuchi and Unno - "A Real-Time Configurable Shader Based on Lookup
Tables": Provides a very detailed explanantion of the fragment lighting
implementation
- Kuijk and Blake - "Faster Phong Shading via Angular Interpolation":
Explains in greater detail how quaternions can be used to encode
information about normals and tangents (and how quaternions are easier to
interpolate than vectors).
The 3DS seems to have four "shaders", each with there own I/O ports. However,
the vertex shaders seem to be used in parallel (to process 3 or 4 vertices at
once... so it's unknown if one needs to initialize all sets of I/O ports
separately; 3dbrew seems to have only two shaders documented (GSH and VSH),
without even being aware of the VSH2 and VSH3 registers.
Primitive Engine
Primitive Engine (PE) is one of the PICA200's four vertex processor units and
provides some unique features which are used to implement a geometry shader
stage and variable-size primitive rendering.
The full functionality of PE is not yet understood and remains to be
reverse-engineered.
Variable-size primitives are implemented by prefixing each per-primitive
sequence of indices in an index array with a primitive size. This is used for
various effects, for example Catmull-Clark subdivision and Loop subdivision. It
is unknown how this feature is enabled specifically.
gpu_clear_colorbuf:
[GPUREG_RENDERBUFFER_INVALIDATE]=1 ;forget cache
[GPU_MEMFILL_DST_ADDR0]=(MEMORG_COLORBUF+0)/10h*2
[GPU_MEMFILL_DST_END0]=(MEMORG_COLORBUF+320*240*4)/10h*2
[GPU_MEMFILL_DATA0]=11441100h
[GPU_MEMFILL_CNT0]=00000201h
wait until [GPU_MEMFILL_CNT0].bit0=0
ret
gpu_copy_colorbuf_to_lcd_framebuf:
DummyRead=[GPUREG_STAT_NUM_TRIANGLES_DISPLAYED] ;waits until rendering done
[GPUREG_RENDERBUFFER_FLUSH]=1 ;cache writeback
[GPU_MEMCOPY_SRC_ADDR]=MEMORG_COLORBUF/10h*2
[GPU_MEMCOPY_DST_ADDR]=MEMORG_SCREEN1/10h*2
[GPU_MEMCOPY_DISPLAY_SIZE]=(240 shl 0)+(320 shl 16)
[GPU_MEMCOPY_REMAIN_IRQ]=3FFFh ;want IRQ flag when done
[GPU_MEMCOPY_FLAGS]=0
[GPU_MEMCOPY_CNT]=1
;caution: polling GPU_MEMCOPY_CNT can HANG the CPU at transfer end!
;instead: poll GPU_STAT_IRQ_FLAGS...
wait until: [GPU_STAT_IRQ_FLAGS].bit30=1
ret
gpu_init_framebuf:
;[GPUREG_RENDERBUFFER_INVALIDATE]=1 ;forget cache
[GPUREG_FACECULLING_CONFIG]=0 ;show front+back
[GPUREG_RENDERBUFFER_DIM_0]=(1 shl 24)+(320-1)*1000h+240
;[GPUREG_RENDERBUFFER_DIM_1]=(1 shl 24)+(320-1)*1000h+240
[GPUREG_DEPTHBUFFER_LOC]=MEMORG_DEPTHBUF/40h*8
[GPUREG_COLORBUFFER_LOC]=MEMORG_COLORBUF/40h*8
[GPUREG_VIEWPORT_V_SCALE]=0045E000h ;240/2 ;.float24 120.0 // db 00h
[GPUREG_VIEWPORT_H_SCALE]=00464000h ;320/2 ;.float24 160.0 // db 00h
[GPUREG_VIEWPORT_V_STEP]=38111100h ;2/240 ;db 00h // .float24 0.008333333
[GPUREG_VIEWPORT_H_STEP]=37999900h ;2/320 ;db 00h // .float24 0.006250000
[GPUREG_VIEWPORT_XY]=(0 shl 16)+0
[GPUREG_SCISSORTEST_MODE]=0
;[GPUREG_SCISSORTEST_POS1]=((0+20) shl 16)+(0+20)
;[GPUREG_SCISSORTEST_POS2]=((320-1-20) shl 16)+(240-1-20)
[GPUREG_COLOR_OPERATION]=00e40100h
[GPUREG_BLEND_FUNC]=06020000h ;raw drawing
;[GPUREG_BLEND_FUNC]=76760000h ;alpha blending
;[GPUREG_LOGIC_OP]=00h
[GPUREG_FRAGOP_ALPHA_TEST]=00h
[GPUREG_STENCIL_TEST]=00h
[GPUREG_DEPTH_COLOR_MASK]=1F00h
[GPUREG_COLORBUFFER_READING]=0Fh
[GPUREG_COLORBUFFER_WRITING]=0Fh
[GPUREG_DEPTHBUFFER_READING]=03h
[GPUREG_DEPTHBUFFER_WRITING]=03h
[GPUREG_DEPTHBUFFER_FORMAT]=03h
[GPUREG_COLORBUFFER_FORMAT]=02h
[GPUREG_RENDERBUFFER_BLOCK32]=0
;[GPUREG_EARLYDEPTH_TEST1]=0
;[GPUREG_EARLYDEPTH_TEST2]=0
[GPUREG_DEPTHMAP_ENABLE]=1
[GPUREG_DEPTHMAP_SCALE]=00bf0000h ;far z (-1.0)
[GPUREG_DEPTHMAP_OFFSET]=00000000h ;near z (0.0)
ret
gpu_init_vertex_shader:
@@numattr equ 2 ;configure for two attributes (coordinate and color)
[GPUREG_SH_OUTMAP_TOTAL]=@@numattr ;vertex+color
[GPUREG_SH_OUTMAP_O+0*4]=03020100h ;vertex.xyzw
[GPUREG_SH_OUTMAP_O+1*4]=0b0a0908h ;color.rgba
[GPUREG_SH_OUTATTR_CLOCK]=3 ;bit0=blah?, bit1=needed for colors
[GPUREG_VSH_COM_MODE]=00h ;GSH/VSH?
[GPUREG_VSH_NUM_ATTR]=@@numattr-1 ;needed
[GPUREG_VSH_OUTMAP_TOTAL1]=@@numattr-1 ;needed
;[GPUREG_VSH_OUTMAP_TOTAL2]=@@numattr-1 ;not needed
[GPUREG_START_DRAW_FUNC0]=1 ;needed
[GPUREG_VSH_INPUTBUFFER_CONFIG]=(0a0h shl 24)+@@numattr-1
[GPUREG_PRIMITIVE_CONFIG]=(1 shl 8)+@@numattr-1
[GPUREG_RESTART_PRIMITIVE]=0 ;required for strips (even BEFORE first strip)
[GPUREG_VSH_ATTR_PERMUTATION_LOW]=076543210h ;\input
[GPUREG_VSH_ATTR_PERMUTATION_HIGH]=0fedcba98h ;/
[GPUREG_VSH_OUTMAP_MASK]=(1 shl @@numattr)-1 ;-output enable's
[GPUREG_VSH_CODETRANSFER_INDEX]=000h/4
[GPUREG_VSH_CODETRANSFER_DATA+0]=4C000000h ;MOV o0,v0 ;used for coord xyzw
[GPUREG_VSH_CODETRANSFER_DATA+0]=4C201000h ;MOV o1,v1 ;used for color rgba
[GPUREG_VSH_CODETRANSFER_DATA+0]=88000000h ;END
[GPUREG_VSH_CODETRANSFER_END]=0
[GPUREG_VSH_OPDESCS_INDEX]=000h
[GPUREG_VSH_OPDESCS_DATA+0]=0000036Fh ;dst=xyzw, src1=xyzw (or rgba)
[GPUREG_VSH_ENTRYPOINT]=7fff0000h+(000h/4)
ret
10120000h - CAM0 (external Right-Eye & internal Self-Facing camera) (as DSi)
10121000h - CAM1 (external Left-Eye camera) (extra 3DS camera)
1012x000h 4 R/W mask: 0000ef1ch ;CAM_CNT alike DSi cameras
1012x004h 2 R mask: 8500h ;CAM_STAT unlike DSi (lsbs=0..500h)
1012x006h 2 R/W mask: 003fh ;CAM_???
1012x010h 4 R/W mask: 01ff03feh ;CAM_SOFS alike DSi cameras
1012x014h 4 R/W mask: 01ff03feh ;CAM_EOFS alike DSi cameras
1032x000h 80h R ;CAM_DAT fifo (20h-word window)
The ARM registers are similar (but not identical) as for DSi cameras,
--> DSi Cameras
The I2C bus camera init does work same as on DSi (for Aptina cameras),
--> DSi I2C Bus
Cameras must be enabled in CFG11_CAMERA_CNT (Port 10141224h).
Camera Notes
The "camera in-use" LED for external camera is controlled via MCU (but the LED
exists on DSi/3DS only, New3DS doesn't have that LED installed).
The three 3DS/New3DS cameras have the same Chip IDs (2280h) as found in the two
DSi's Aptina MT9V113 cameras.
However, New3DS is said to have improved picture quality. Unknown what that
means, maybe the I2C registers are simply initialized with better gain settings
at software side, or maybe the camera hardware is actually improved despite of
having the same chip id.
New3DS is also said to support eye-tracking, whatever that means, it is
probably done using the internal camera. And New3DS is said to have an IR-LED
next to the internal camera to assist eye-tracking (yet unknown if/how the
YUV/RGB camera could see IR-light at all).
10102004h/10132004h - Y2R_WIDTH
0-2 Unused (0)
3-9 Width, in 8-pixel units (01h..7Fh=8..1016 pix, or 00h=?)
10-15 Unused (0)
10102006h/10132006h - Y2R_HEIGHT
3-9 Height in 1-pixel units (001h..3FFh=1..1023 pix, or 000h=?)
10-15 Unused (0)
Unknown. New3DS only. MVD might be short for Movie Decoder or so?
Unknown if there are any FIFOs and CDMA peripheral IDs... there are none known
yet... maybe the thing does have it's own "DMA" hardware for direct memory
access without needing CDMA?
The LGYFB units are for forwarding GBA/NDS/DSi video to 3DS screens with
optional scaling. The input comes directly from the GBA/NDS video controller,
the output must be DMAed to memory.
That is, ARM11 must handle that memory transfers in background while running
GBA/NDS/DSi software on ARM7/ARM9 side.
Texture Swizzling
Morton Swizzling, or Z-order Swizzling is done by reading source pixels from a
scanline based bitmap in "Z-shaped" read-direction, and then storing that
pixels at continous VRAM addresses.
In the drawing below, each "Z" represents 2x2 pixels (arranged as a "Z" shape,
ie. upper-left, upper-right, lower-left, lower-right). On a larger scale, each
2x2 Z's are also forming a larger Z, and so on.
Z/Z /Z/Z
.-' / .-'
Z/Z/ Z/Z
..--'
.--'
Z/Z /Z/Z
.-' / .-'
Z/Z/ Z/Z
This can improve cache hits for adjacent pixels. In a large bitmap, pixels in
adjacent scanlines are always located in separate cache entries. With the
swizzling, there is a better chance that they are in the same cache entry.
Addressing
The swizzling does interleave the x/y address bits. On the 3DS hardware, data
is processed in units of 8 scanlines, so the interleave occurs on lower three
x/y bits only. For example, for 256x256 pixel data:
Scanline-based bitmap --> YyyyyyyyXxxxxxxx
Swizzled texture --> YyyyyXxxxxyxyxyx
Swizzling Hardware
The 3DS has some hardware for converting scanlines to swizzled textures:
Y2R Registers (YUV-to-RGBA)
L2B Registers (RGB-to-RGBA) (New3DS only)
LGYFB Registers (GBA/NDS/DSi-to-3DS-Framebuffer)
Swizzling Examples
Examples for scanline pixels before/after swizzling:
Linear scanlines, 16x8 pixels: Linear lines, 8x8 pixels:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 01 02 03 04 05 06 07
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 08 09 0A 0B 0C 0D 0E 0F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 10 11 12 13 14 15 16 17
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 18 19 1A 1B 1C 1D 1E 1F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 20 21 22 23 24 25 26 27
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 28 29 2A 2B 2C 2D 2E 2F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 30 31 32 33 34 35 36 37
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 38 39 3A 3B 3C 3D 3E 3F
Swizzled texture, 2 tiles: Swizzled texture, 1 tile:
00 01 10 11 02 03 12 13 ;\ 00 01 08 09 02 03 0A 0B
20 21 30 31 22 23 32 33 ; 10 11 18 19 12 13 1A 1B
04 05 14 15 06 07 16 17 ; 04 05 0C 0D 06 07 0E 0F
24 25 34 35 26 27 36 37 ; left tile 14 15 1C 1D 16 17 1E 1F
40 41 50 51 42 43 52 53 ; 20 21 28 29 22 23 2A 2B
60 61 70 71 62 63 72 73 : 30 31 38 39 32 33 3A 3B
44 45 54 55 46 47 56 57 ; 24 25 2C 2D 26 27 2E 2F
64 65 74 75 66 67 76 77 ;/ 34 35 3C 3D 36 37 3E 3F
08 09 18 19 0A 0B 1A 1B ;\
28 29 38 39 2A 2B 3A 3B ;
0C 0D 1C 1D 0E 0F 1E 1F ;
2C 2D 3C 3D 2E 2F 3E 3F ; right tile
48 49 58 59 4A 4B 5A 5B ;
68 69 78 79 6A 6B 7A 7B :
4C 4D 5C 5D 4E 4F 5E 5F ;
6C 6D 7C 7D 6E 6F 7E 7F ;/
Note: Z-order refers to the shape of the letter "Z", not to be confused with
Z-axis, and not to be confused with the zigzag-order that is used in JPEGs.
The sound hardware works very similar to NDS sound, see there for details about
PCM, IMA-ADPCM and PSG formats.
--> DS Sound
Differences are twice as many sound channels, some moved control bits, and
simplified volume control (without sound/panning/master volumes).
Unknown if/where BIAS exists on 3DS?
MIC Registers
10162000h 2 REG_MIC_CNT Microphone Control
10162004h 4 REG_MIC_DATA Microphone Data
These are about same as for DSi.
--> DSi Microphone and SoundExt
The microphone must be unmuted in touchscreen TSC registers.
The microphone must be enabled in Port 10145000h.
Microphone triggers CDMA 00h (requires Port 1014010Ch, CFG11_CDMA_CNT.bit0=1).
The PROM is used for online games, it contains a 16-byte hex number (followed
by 30h-byte FFh-filled area).
Some cards do also have writeable NAND instead of ROM. The NAND is also
accessed via CTRCARD0 registers (not CTRCARD1), the NAND commands are still
unknown.
10004000h/10005000h - CTRCARD_CNT
0-4 Timeout (0-16=1ms,2ms,4ms,8ms,..,64s; 17-31=64s, too; def=12=4s) (R/W)
5 Timeout Error (0=Okay, 1=Error) (write 0 to ack) (R/ack)
6 Timeout Enable (0=Disable, 1=Enable) (R/W)
7 Unused (0)
8 CRC Error (0=Okay, 1=Error) (write 0 to ack) (R/ack)
9 CRC Enable (0=Disable, 1=Enable) (works for cmd 82h/BFh) (R/W)
10-14 Unused (0)
15 DMA Enable (0=Disable, 1=Enable DMA DRQs, each 8 words) (R/W)
16-19 Data Block size (0-8=0,4,16,64,512,1K,2K,4K,8K; 9-15=8K, too) (R/W)
20-23 Unused (0)
24-26 Transfer Clock (0-5=67MHz div 4,5,6,8,10,16; 6-7=div16, too) (R/W)
27 Data-Word status (0=Busy, 1=Ready/DRQ) (R)
28 Reset Pin (0=Low/Reset, 1=High/Release) (SET-ONCE) (R/W)
29 Transfer Direction (0=Read, 1=Write) (R/W)
30 Interrupt Enable (0=Disable, 1=Enable) (ARM9 IF.bit23/24) (R/W)
31 Start (0=Idle, 1=Start/Busy) (R/W)
With the above Transfer Clock settings, the clock (per byte) can range from
16.7MHz downto 4.2MHz.
Once reset pin is set high, it cannot be changed until controller is reset
(which can be done CFG9_CARD_POWER). Setting bit28 does work only when writing
bit31=0.
ARM9
--> 3DS ARM9 Interrupts
--> 3DS ARM9 Timers
ARM11
--> 3DS ARM11 Interrupts
--> ARM11 MPCore Private Memory Region Register Summary
--> ARM11 MPCore - Snoop Control Unit (SCU)
--> ARM11 MPCore - Timer and Watchdog
--> ARM11 MPCore - Interrupt Configuration
--> ARM11 MPCore - Interrupt Handling
--> ARM11 MPCore Distributed Interrupt Controller (Blurb)
Hardware Interrupts (can be used for all CPUs that are selected as Target)
20h - Unused? ;\maybe
21h - Unused? But [17E01D00h].bit33 is set ; related to
22h - Unused? ; first two
23h - Unused? But [17E01D00h].bit35 is set ;/CPU cores?
24h spi? SPI_BUS2 (unused) (Port 10143000h)
25h-27h - Unused?
28h gsp, TwlBg PSC0 (GPU_MEMFILL 0) (Port 10400010h)
29h gsp, TwlBg PSC1 (GPU_MEMFILL 1) (Port 10400020h)
2Ah gsp, TwlBg PDC0 (GPU H/V-IRQ for top screen) (Port 10400400h)
2Bh gsp, TwlBg PDC1 (GPU H/V-IRQ for bottom screen) (Port 10400500h)
2Ch gsp, TwlBg PPF (GPU_MEMCOPY) (Port 10400C00h)
2Dh gsp, TwlBg P3D (GPUREG_IRQ_CMP/REQ) (Port 10401040h)
2Eh-2Fh - Unused?
30h-38h Kernel Old CDMA Event 0..8 (nine events with separate IRQs)
39h Kernel Old CDMA Faulting (eg. CCR=0, or event>15)
3Ah Kernel New CDMA Event 0..31 (32 events sharing one IRQ) ;\New3DS
3Bh Kernel New CDMA Faulting (eg. CCR=0) ;/
3Ch - Unused? ;\maybe alike
3Dh - Unused? But New3DS [17E01D00h].bit61 is set ; IRQ 20h-23h
3Eh - Unused? ; for extra
3Fh - Unused? But New3DS [17E01D00h].bit63 is set ;/CPU cores?
40h nwm WIFI SDIO Controller (Port 10122000h)
41h nwm WIFI SDIO IRQ Pin
42h nwm_dev? Alternate SD/MMC Slot controller (Port 10100000h?)
43h - Unused? Or maybe Card IRQ Pin for above?
44h - NTRCARD (Port 10164000h)
45h mvd L2B_0 (First RGB-to-RGBA Converter) (10130000h) ;\New3DS
46h mvd L2B_1 (Second RGB-to-RGBA Converter) (10131000h) ;/
47h - Unused?
48h camera Camera Bus 0 (DSi cameras) (Port 10120000h)
49h camera Camera Bus 1 (left-eye) (Port 10121000h)
4Ah dsp ...probably Teak DSP... ? (maybe 10203000h)
4Bh camera Y2R_0 (First YUV-to-RGBA Converter) (10102000h)
4Ch TwlBg LGYFB_0 Legacy GBA/NDS Video (Port 10110000h)
4Dh TwlBg LGYFB_1 Legacy GBA/NDS Video (Port 10111000h)
4Eh mvd Y2R_1 (Second YUV-to-RGBA Converter) (10132000h) ;\New3DS
4Fh mvd MVD Registers (Port 10207000h) ;/
50h pxi, TwlBg PXI_SYNC.bit29 from ARM9 (commonly used)
51h pxi, TwlBg PXI_SYNC.bit30 from ARM9 (rarely used)
52h pxi, TwlBg PXI Send Fifo Empty
53h pxi, TwlBg PXI Receive Fifo Not Empty
54h i2c, TwlBg I2C_BUS0 (DSi devices) (Port 10161000h)
55h i2c, TwlBg I2C_BUS1 (3DS devices) (Port 10144000h)
56h spi, TwlBg SPI_BUS0 (Pwrman,WifiFlash,Tsc) (Port 10160000h)
57h spi, TwlBg SPI_BUS1 (Tsc) (Port 10142000h)
58h Kernel CFG11_MPCORE_CLKCNT (clk change)(Port 10141300h) ;-New3DS
59h TwlBg CFG11_TWLMODE_SLEEP (Port 10141104h)
5Ah mic Microphone maybe? (maybe 10162000h)
5Bh - HID PAD Controller Buttons (Port 10146000h)
5Ch i2c, TwlBg I2C_BUS2 (3DS extra gimmicks) (Port 10148000h)
5Dh-5Eh - Unused?
5Fh - NDS-Wifi Registers (aka MP) (Port 10170000h)
60h gpio, TwlBg GPIO_DATA0.bit2? Shell opened
61h - Unused?
62h gpio, TwlBg GPIO_DATA0.bit2? Shell closed
63h gpio, TwlBg GPIO_DATA0.bit1 Touchscreen Pen Down (if enabled)
64h gpio, TwlBg GPIO_DATA1.bit0 Headphone jack plugged in/out
65h - Unused?
66h gpio, TwlBg GPIO_DATA1.bit1 ?
67h - Unused?
68h gpio, TwlBg GPIO_DATA3.bit0 C-stick Interrupt (New3DS)
69h gpio, TwlBg GPIO_DATA3.bit1 IrDA Interrupt
6Ah gpio, TwlBg GPIO_DATA3.bit2 Gyro Interrupt
6Bh gpio, TwlBg GPIO_DATA3.bit3 ?
6Ch gpio, TwlBg GPIO_DATA3.bit4 IrDA TX-RC (manual out)
6Dh gpio, TwlBg GPIO_DATA3.bit5 IrDA RXD (manual in)
6Eh gpio, TwlBg GPIO_DATA3.bit6 ?
6Fh gpio, TwlBg GPIO_DATA3.bit7 ?
70h gpio, TwlBg GPIO_DATA3.bit8 TSC[67h:2Bh] (Headphone connect)
71h gpio, TwlBg GPIO_DATA3.bit9 MCU Interrupt (MCU[10h-1Fh])
72h gpio, TwlBg GPIO_DATA3.bit10 NFC Interrupt (New3DS)
73h TwlBg GPIO_DATA3.bit11 ??
74h ? CGC Gamecard power off (CFG9_CARD_PWROFF_DELAY)
75h ? CGC Gamecard insert switch (CFG9_CARD_INSERT_DELAY)
76h - L2C Level 2 Cache Controller (Port 17E10000h) New3DS
77h - Unused?
78h Kernel CPU0 cp15 Performance monitor count (any) overflow
79h Kernel CPU1 cp15 Performance monitor count (any) overflow
7Ah Kernel CPU2 cp15 Performance monitor count (any) overflow New3DS
7Bh Kernel CPU3 cp15 Performance monitor count (any) overflow New3DS
7Ch-7Fh - Unused?
80h-3FEh Don't exist (3DS/New3DS has only 80h IRQ sources)
3FFh None, no interrupt (or spurious interrupt)
The spurious interrupt (3FFh) might appear in an interrupt handler if the
handler got triggered, but something (eg. another CPU) has cleared the IRQ flag
before the handler got a chance to process it.
10.2 Terminology - From point of view of an MP11 CPU, an interrupt can be:
Inactive: An Inactive interrupt is one that is nonasserted, or which in a
multi-processing environment has been completely processed by that MP11
CPU but can still be either Pending or Active in some of the MP11 CPUs to
which it is targeted, and so might not have been cleared at the interrupt
source.
Pending: A Pending interrupt is one that has been asserted, and for which
processing has not started on that MP11 CPU.
Active: An Active interrupt is one that has been started on that MP11 CPU,
but processing is not complete.
An interrupt can be Pending and Active at the same time. This can happen in the
case of edge triggered interrupts, when the interrupt is asserted while the
MP11 CPU has not finished handling the first occurrence. For level-sensitive
interrupts it can only happen if software triggers it. See Interrupt
Configuration Registers, 0xC00-0xC3C on page 10-17.
Pre-emption: An Active interrupt can be pre-empted when a new interrupt of
higher priority interrupts MP11 CPU interrupt processing. For the purpose
of this document, an Active interrupt can be running if it is actually
being processed, or pre-empted.
The Distributed Interrupt Controller consists of:
Interrupt Distributor:
The Interrupt Distributor handles interrupt detection and interrupt
prioritization.
CPU interrupt interfaces:
There is one CPU interrupt interface per MP11 CPU. The MP11 CPU interrupt
interfaces handle interrupt acknowledgement, interrupt masking, and interrupt
completion acknowledgement.
The CPU Interface returns information to the Distributor when the CPU
acknowledges (Pending to Active transition) or clears an interrupt (Active to
Inactive transition). With the given interrupt ID, the Interrupt Distributor
updates the status of this interrupt according to the information sent by the
CPU Interface.
When an interrupt is triggered by the Software Interrupt Register or the
Set-pending Register, the status of that interrupt for the targeted CPU or CPUs
is set to Pending. This interrupt then has the same behavior as a hardware
interrupt. The distributor does not differentiate between software and hardware
triggered interrupts.
Floating Point
The floating point hardware is called VFPv2 (Vector Floating-point).
ARM DDI 0100I ARM Architecture Reference Manual (for ARMv6 wirh VFPv2)
ARM DDI 0360F ARM11 MPCore r2p0, contains more (mostly useless) VFPv2 info
The Fxxxx floating point opcodes are aliases for CP10/CP11 copressor numbers;
CP10 used for single, and CP11 for double precision instructions.
Multiply Note
When multiplying vector*vector, the hardware does merely multiply the
components (without computing the sum of the multiply results). To get sum, one
could use FMUL and several FADD's with different strides. Or better, for
multiple vector*vector multiplications, use FMUL and several FMAC's with source
data rearranged as so:
FMUL (X,X,X,X,X,X,X,X)*(X,X,X,X,X,X,X,X)
FMAC (Y,Y,Y,Y,Y,Y,Y,Y)*(Y,Y,Y,Y,Y,Y,Y,Y)
FMAC (Z,Z,Z,Z,Z,Z,Z,Z)*(Z,Z,Z,Z,Z,Z,Z,Z)
FMAC (W,W,W,W,W,W,W,W)*(W,W,W,W,W,W,W,W)
Ie. in that case, the 1st "vector" contains the X components from up to eight
(X,Y,Z,W) vectors.
Cond = Condition
L = Load/Store direction for memory/register transfers
Fm:M, Fn:N, Fd:D = Float Registers S0..S31 (or D0..D15, with LSB=0)
Rd, Rn = ARM Registers
PUW, pqrs, CPopc = Opcode bits
CP# = Coprocessor number (0Ah=Single-, 0Bh=Double-Precision)
Offset = Address step, implies number of registers for FLDM/FSTM
Nocash syntax
The useless {S|D} and {DS|SD} suffixes are ommitted. FCVT is renamed to FMOV.
F{UI|SI}TO{UI|SI}{Z} is renamed to FMOV{UI|SI}{Z}, with operand I0..I31 for the
integer register.
Nocash syntax
The useless {S|D} suffixes are ommitted, the weird {X} suffix is kept used to
preserve weirdness.
Fancy {} brackets are omitted, LDM/STM must use square [Rn] brackets, the
register list in LDM/STM is specified as Fx-Fz (rather than Fx,Fy,Fz).
All FMxxxx opcodes are renamed to FMOV{LSW|MSW}.
The 3DS can have up to eight primary NCSD partitions, some of these partitions
point to secondary MBR partition tables, each of those MBRs could have up to
four child partitions (with FAT filesystems).
NAND structure
Offset Size Name _NCSD_partition_ AES Description
FS crypt index key
type type
00000000h 200h NCSD header
00000000h 0B100000h 0x01 0x01 0x00 03h DSi MBR
00004000h 200h? - - - - Some Consoles: Dummy FAT16
00012C00h 200h - - - 11h New3DS FIRM keys
00012E00h 08FB5200h twln 03h DSi FAT16 File System, main
09011A00h 020B6600h twlp 03h DSi FAT12 File System, photo
0B100000h 00030000h 0x04 0x02 0x01 07h AGB_FIRM GBA savegame
0B130000h 00400000h firm0 0x03 0x02 0x02 06h Firmware partition
0B530000h 00400000h firm1 0x03 0x02 0x03 06h Firmware partition (backup)
0B930000h 2F5D0000h 0x01 0x02 0x04 04h Old3DS: MBR
0B95CA00h 2F3E3600h nand 04h Old3DS: FAT16 File System
0B930000h 41ED0000h 0x01 0x03 0x04 05h New3DS: MBR
0B95AE00h 41D2D200h nand 05h New3DS: FAT16 File System
Physical Size
Device eMMC Chip Size
2DS Toshiba ? 3AF00000h ;\943MB ;uh, all unknown
Old3DS Toshiba ? 3AF00000h ;/ ;CID and chip names?
2DS ? 3B000000h ;<-- 3AF00000h and up E3h-filled?
2DS Samsung ? 3BA00000h ;\954MB
Old3DS Samsung ? 3BA00000h ;/
2DS Samsung ? 4D800000h ;\1240MB
New3DS Samsung KLM4G1YE0C-B301 4D800000h ;/
New3DS Samsung ? 74800000h ;-1864MB
2DS Toshiba ? 76000000h ;\1888MB
New3DS Toshiba ? 76000000h ;/
Encryption
The NAND file system is encrypted using AES-CTR. The keyslot used for each
partition is determined by the NCSD partition FS type and encryption type.
NAND sectors which were never written to contain plaintext 00h or FFh bytes.
None of the NAND partitions are normally accessible from the ARM11, except for
twlp. CTR/TWL NAND FS can only be accessed when the exheader access control
descriptor for those are enabled. Normally the CTR/TWL NAND descriptors are
never enabled for retail ARM11 CXI processes. The ARM11 can only access
"nand:/rw/" mounted as the nandrw archive, and "nand:/ro/" mounted as the
nandro archive below.
eMMC 12C00h (aka Sector 96h) (New3DS only) (empty FFh-filled on Old3DS)
000h 10h Used for generating Key X values for keyslot 15h and 18h
010h 10h Used for generating Key X values for keyslot 16h and 19h-1Fh ;v9.6
020h 1E0h Further constants (unused)
This 200h-byte sector contains New3DS keys, this entire sector is encrypted via
AES-ECB with a console-unique keyX+keyY. The keyX+keyY for this is generated by
the New3DS arm9bin-loader. Once the arm9bin-loader finishes decrypting this
data, the keyX+keyY in the keyslot are then cleared, then the memory used for
generating the keydata is disabled (after it finishes using it for TWL key
init).
The decrypted sector is same on all New3DS consoles (except, retail-vs-debug
are different):
Decrypted 200h-bytes on Retail: 07h,29h,44h,38h, ..., 13h,63h,CFh,8Fh
Decrypted 200h-bytes on Dev: Unknown...
NCSD format is used for internal eMMC storage & for 3DS ROM cartridges. The
NCSD can contain up to 8 partitions.
For eMMC, the partitions are:
Part Type Content
0 MBR DSi MBR (with two FAT filesystems, FAT16+FAT12)
1 GBA-SAVE GBA savegame (temporary storage, used on power-off in GBA mode)
2 FIRM Firmware partition (firm0)
3 FIRM Firmware partition (firm1) (backup copy, same as above)
4 MBR 3DS MBR (with one FAT filesystem, FAT16)
5-7 - Unused
For 3DS ROM Cartridges (aka CCI images), the partitions are:
Part Type Content
0 NCCH Executable Content (CXI)
1 NCCH E-Manual (CFA)
2 NCCH Download Play Child container (CFA) (if any)
3-5 - Unused
6 NCCH New3DS System Update Data (CFA) (if any) ;\aka firmware updates
7 NCCH Old3DS System Update Data (CFA) ;/
Blurb
There are two known specialisations of the NCSD container format:
- The CTR Cart Image (CCI) format (CCI is the format of game ROM images)
- The 3DS' raw NAND format
CTR System Update (CSU) is a variant of CCI, where the only difference is in
the file extension (uh, that is the file extension of a ROM-image that needs to
be copied to a dev flashcard or so?). This is used with developer System
Updates and associated Tools.
The format of partitions can be determined from the partition FS flags
(normally these are zero for CCI/CSU NCSD Images) (uh, what/where is "FS
flags"?).
NCSD header
000h 100h RSA-2048 SHA-256 signature of the NCSD header (including MBR!)
100h 4 ID "NCSD"
104h 4 Size of the NCSD image (in media units)
108h 8 ? Media ID
110h 8*1 Partitions Type (0=NCCH or Unused, 1=MBR, 3=FIRM, 4=GBA-SAVE)
118h 8*1 Partitions Crypt (0=NCCH or Unused, 1=DSi, 2=3DS, 3=New3DS)
120h 8*(4+4) Partitions Offset & Size (in media units)
For eMMC:
160h 25h Zerofilled
185h 1 Unknown (04h)
186h 6 Zerofilled
18Ch 1 Unknown (01h)
18Dh 1 Zero
18Eh 1 Media Unit Size (200h SHL N) (usually 00h, aka 200h-bytes)
18Fh 2Fh
Zerofilled (unencrypted, despite of below)
1BEh 42h
Encrypted MBR partition-table, for the two DSi partitions
(key-data used for this keyslot is console-unique).
For ROM carts:
160h 20h Exheader SHA-256 hash (uh, really?) (usually 0)
180h 4 Additional header size (uh, does that mean "Exheader"?) (usually 0)
184h 4 Sector zero offset (whatever, in whatever units, usually 0)
188h .. Partition Flags (uh, why called "flags" and why "partition"?)
188h 1 Backup Write Wait Time (The time to wait to write save to backup
after the card is recognized (0-255 seconds)). NATIVE_FIRM loads
this flag from the gamecard NCSD header starting with 6.0.0-11.
189h 1 unknown, maybe related to below "Save Crypto"?
18Ah 1 unknown, ?
18Bh 1 Media Card Device (1=NOR Flash, 2=None, 3=BT) (SDK 3.X+)
18Ch 1 Media Platform Index (1=CTR)
18Dh 1 Media Type Index (0=InnerDevice, 1=Card1, 2=Card2, 3=ExtendedDevice)
18Eh 1 Media Unit Size (200h SHL N)
18Fh 1 Media Card Device (1=NOR Flash, 2=None, 3=BT) (Only SDK 2.X)
190h 40h Partition ID table (8x8 bytes)
1D0h 20h Reserved
1F0h 0Eh Reserved?
1FEh 1 Support for this was implemented with 9.6.0-X FIRM.
Bit0=1 enables using bits 1-2, it's unknown what these two
bits are actually used for (the value of these two bits get
compared with some other value during NCSD
verification/loading).
This appears to enable a new, likely hardware-based,
antipiracy check on cartridges.
1FFh 1 Support for this was implemented with 9.6.0-X FIRM, see below
regarding save crypto.
NCSD Signature
The RSA pubk used for gamecard NCSD is stored in ITCM (what/wherefrom?).
The RSA pubk used for NAND NCSD is stored in "Process9 .(ro)data instead of
ITCM". Uh, shouldn't that key (also?) be in bootrom?
Partition Flags (In Terms of Save Crypto Determination) (uh, Save what?)
Note: Byte 01h,03h,07h do probably refer to NCSD[189h,18Bh,18Fh].
Note: flag[1,3,7] do probably ALSO refer to NCSD[189h,18Bh,18Fh].
Note: partitionflag[1,3,7] do MAYBE ALSO refer to NCSD[189h,18Bh,18Fh]?
Byte Description
01h Starting with 6.0.0-11 NATIVE_FIRM will use this flag to determine
the gamecard savegame keyY method, when flag[3] is set.
00h = 2.0.0-2 hashed keyY,
01h = new keyY method implemented with 6.0.0-11.
0Ah = implemented with 9.3.0-X. On Old3DS this is identical to
the 2.2.0-4 crypto. On New3DS this is identical to the 2.2.0-4
crypto, except with New3DS-only gamecard savedata keyslots.
Starting with 9.6.0-X FIRM, Process9 now sets <savecrypto_stateval> to
partitionflag[1] + <the u8 value from NCSD+0x1FF>, instead of just setting it
to partitionflag[1].
03h Support for this flag was implemented in NATIVE_FIRM with 2.0.0-2.
When this flag is set the hashed gamecard savegame keyY method is
used, this likely still uses the repeating-CTR however.
With 6.0.0-11 the system will determine the gamecard savegame keyY
method via flag[1], instead of just using the hashed keyY via this
flag.
07h This flag enables using the hashed gamecard savegame keyY method,
support for this flag was implemented in NATIVE_FIRM with 2.2.0-4.
All games with the NCSD image finalized since 2.2.0-4 (and contains
2.2.0-4+ in the system update partition) have this flag set, this
flag also enables using new CTR method as well.
Starting with 9.6.0-X FIRM, Process9 will just write val0 to a state field then
return 0, instead of returning an error when the save crypto type isn't
recognized. This was the *only* actual functionality change in the Old3DS
Process9 function for gamecard savedata crypto init.
Card Info Header - uh, maybe this is the "Exheader" aka "Additional header"?
Offset Size Description
200h 4 CARD2: Writable Address In Media Units (For 'On-Chip' Savedata)
CARD1: Always FFFFFFFFh.
204h 4 Card Info Bitmask
208h 108h? Reserved1
300h 4 Unknown (1DD7AA00h)
... ..
310h 2 Title version
312h 2 Card revision
... ..
320h 8 Title ID for CVer USA (000400db00017202h) (even so in JPN cart)
328h ? Unknown (1022h)
208h?? CEEh? Reserved2
1000h 10h Card seed AES-KeyY (first u64 is Media ID (same as first NCCH
partitionId))
1010h 10h Encrypted card seed (AES-CCM, keyslot 3Bh for retail cards,
see CTRCARD_SECSEED)
1020h 10h Card seed AES-MAC
1030h 0Ch Card seed AES-IV
103Ch C4h Reserved3
1100h 100h Copy of first NCCH header (excluding RSA signature)
Development Card Info Header Extension:
Unknown how to read from 1200h..3FFFh. When trying to do so on retail card:
Encrypted read (cmd BFh) does merely return random garbage at 1200h..3FFFh.
Unencrypted read (cmd 82h) can read from 1000h only (though MAYBE it can
read MULTIPLE blocks from 1000h upwards?)
Below says something about NTR cmd 90h or CTR cmd 90h or A2h, but that
refers to getting the 32bit Chip ID, not to header data at 1200h and up.
1200h 200h CardDeviceReserved1
1400h 10h TitleKey (whatever that is... something alike as in tickets?)
1410h F0h CardDeviceReserved2
Note that a particular(=which?) flashcard vendor puts what many(=who?) refer to
as "private headers"(=what?) here in place of actual development card
information. This(=which?) header is constituted(=whut?) by a cartridge-unique
Id obtained from pxi:ps9::GetRomId(=what?) and the title-unique cart ID
(identical for all carts of the same title; can be retrieved using the NTR
gamecard protocol command 90h or through the CTR protocol commands 90h or A2h)
(uh, actually, that is the Chip ID, not a "title-unique cart ID" thing).
Tools
ctrtool - (CMD) (Windows/Linux) Parsing NCSD files
3DSExplorer - (GUI) (Windows Only) Parsing NCSD files
File format for the 3DS' Firmware, it contains up to four 'sections' of data
comprising the ARM9 and ARM11 kernels, and some fundamental processes.
The firmware sections are not encrypted.
The ARM9 section contains the ARM9 kernel (and loader) and the Process9 NCCH
(which is the only process run in user mode on the ARM9). The ARM11 sections
contain the ARM11 kernel (and loader), and various ARM11 process NCCHs. For
NATIVE_FIRM/SAFE_MODE_FIRM these ARM11 processes are sm, fs, pm, loader, and
pxi. Normally the 4th section is not used. The code loaded from FIRM is
constantly running on the system until another FIRM is launched. The ARM11
kernel is hard-coded to always decompress the ExeFS .code of embedded ARM11
NCCHs without checking the exheader compression bit.
FIRM Header
000h 4 ID "FIRM"
004h 4 Boot priority (0=Normal/Lowest)
008h 4 ARM11 Entrypoint (usually 1FFxxxxxh, aka AXI WRAM.. or DSP?)
00Ch 4 ARM9 Entrypoint (usually 080xxxxxh, aka ARM9-only RAM)
010h 30h Reserved (0)
040h 30h Firmware Section Header 1 (usually several NCCH's with ExeFS)
070h 30h Firmware Section Header 2 (usually ARM11 code)
0A0h 30h Firmware Section Header 3 (usually ARM9 code & Process9 NCCH)
0D0h 30h Firmware Section Header 4 (often unused, zerofilled)
100h 100h RSA-2048 SHA-256 signature of the FIRM header
The RSA signature is checked when bootrom/Process9 are doing FIRM-launch (with
the public key being hardcoded in each). The signature is not checked when
installing FIRM to the NAND firm0/firm1 partitions.
FIRMs are more or less unencrypted, except that they are stored in encrypted
memory:
- FIRM bootcode is stored in an encrypted partition (with the usual eMMC
encryption; using a different keyslot than FAT partitions though)
- FIRMs for GBA/DSi/SafeMode are stored in NCCHs files (with the eMMC
filesystem encryption; and usually with NCCH[18Fh].bit2=0, ie. with
further encryption in NCCH ExeFS)
Apart from that, FIRMs are having a RSA signature (which can be broken via
sighax).
Terror
Caution: The FIRM key init description on 3dbrew FIRM page is incomplete,
confusing, irrelevant, and simply mind blowing (the description won't make any
sense at all without simultaneously looking at the disassembled firmware code;
or perhaps looking at above pseudo code).
New3DS Process9
The following is all of the differences for Old3DS/New3DS Process9 with
9.3.0-X:
The FIRM-launch code called at the end of the New3DS proc9 main() has different
mem-range checks.
In the New3DS proc9, the v6.0/v7.0 keyinit function at the very beginning
(before the original code) had additional code added for setting CTRNAND
keyslot 0x5, with keydata from .data. After setting the keyY, the keyY in .data
is cleared.
In New3DS proc9, the functions for getting the gamecard crypto keyslots / NCCH
keyslot can return New3DS keyslots when New3DS flags (NCSD/NCCH) are set.
The code/data for the binary near the end of arm9mem is slightly different,
because of memory-region sizes.
The only difference in .data (besides the above code binary) is that the New3DS
proc9 has an additional 0x10-byte block for the keyslot 0x5 keyY, see above.
Variations
There exists different official firmwares for the 3DS: The default one
(NATIVE_FIRM) is used to run all 3DS content and boots by default, while
backwards compatibility is handled by TWL_FIRM and AGB_FIRM. There furthermore
is a rescue mode provided by SAFE_MODE_FIRM.
NATIVE_FIRM
NATIVE_FIRM is the FIRM which is installed to the NAND firm partitions, which
is loaded by bootrom.
Version history:
System
version old 3DS
title version old 3DS
/ hex title
/ contentID Kernel/FIRM
/ ________/ version (old
/ / ______________ 3DS/new 3DS) FIRM
/ / / ________________________ ARM11-sysmodule
/ / / / Product Code
Factory v0 00 2.3-0 - ;Factory FIRM, titleID 00040001-00000002
Pre-1.0 - - 2.23-X - ;Referenced in v1.0 Home Menu NCCH hdr
1.0.0-0 v432 00 2.27-0 - ? ? 2011?
1.1.0- v1472 02 2.28-0 - - - 2011?
2.0.0- v2516 09 2.29-7 - - - 2011?
2.1.0-3 v3553 0B 2.30-18 0608builder ? ? 2011?
2.2.0-X ? v4595 0F 2.31-40 0909builder ? ? 2011?
3.0.0- v5647 18 2.32-15 1128builder - - 2011?
4.0.0-7 v6677 1D 2.33-4 0406builder ? ? 2012
4.1.0- v7712 1F 2.34-0 0508builder - - 2012?
5.0.0-11 v8758 25 2.35-6 0228builder ? ? 2013
5.1.0-11 v9792 26 2.36-0 0401builder ? ? 2013
6.0.0-11 v10833 29 2.37-0 0520builder 17 Jun 2013 ;Non-US: -12
6.1.0-11 v11872 2A 2.38-0 0625builder 27 Jun 2013 ;Non-US: -12
7.0.0-13 v12916 2E 2.39-4 1125builder 09 Dec 2013
7.2.0-17 v13956 30 2.40-0 0404builder 12 May 2014
8.0.0-18 v15047 37 2.44-6 0701builder 07 Jul 2014
8.1.0-0 ? - - 2.45-5 - 26 Sep 2014 ;New3DS Launch
9.0.0-20 v17120 38 2.46-0 0828builder 06 Oct 2014
9.3.0-21 v18182 3F 2.48-3 1125builder 08 Dec 2014
9.5.0-22 v19216 40 2.49-0 0126builder 02 Feb 2015
9.6.0-24 v20262 49 2.50-1 0311builder 23 Mar 2015
10.0.0-27 v21288 4B 2.50-7 0812builder 08 Sep 2015
10.2.0-28 v22313 4C 2.50-9 1009builder 19 Oct 2015
10.4.0-29 v23341 50 2.50-11 1224builder 18 Jan 2016
11.0.0-33 v24368 52 2.51-0 0406builder 09 May 2016
11.1.0-34 v25396 56 2.51-2 0805builder 13 Sep 2016
11.2.0-35 v26432 58 2.52-0 1015builder 24 Oct 2016
11.3.0-36 v27476 5C 2.53-0 0126builder 06 Feb 2017
11.4.0-37 v28512 5E 2.54-0 0314builder 10 Apr 2017
11.8.0-41 v29557 64 2.55-0 0710pseg-ciuser 30 Jul 2018
11.12.0-44 v30593 66 2.56-0 1021pseg-ciuser 04 Nov 2019
11.13.0-45 ? ? ? ? 02 Dec 2019
Note: The above "builder" strings seem to be the actual Month/Day built-date.
SAFE_MODE_FIRM
SAFE_MODE is used for running the System Updater. SAFE_MODE_FIRM and
NATIVE_FIRM for the initial versions are exactly the same, except for the
system core version fields.
TWL_FIRM
TWL_FIRM handles DS(i) backwards compatibility.
The 3DS-mode ARM9 core seems to switch into DSi-mode (for running DSi-mode ARM9
code) by writing to a PDN register (this changes the memory layout to DSi-mode
/ etc, therefore this register poke *must* be executed from ITCM). This is the
final 3DS-mode register poke before the ARM9 switches into DSi-mode. DS(i)-mode
ARM7 code is run on the internal ARM7 core, which is started up during TWL_FIRM
boot. Trying to read from the exception-vector region (address 0x0) under this
DSi-mode ARM7 seems to only return 0x00/0xFF data. Also note that this DSi-mode
ARM7 runs code (stored in TWL_FIRM) which pokes some DSi-mode registers that on
the DSi were used for disabling access to the DSi bootROMs, however these
registers do not affect the 3DS DSi-mode ARM9/ARM7 "bootrom" region
(exceptionvector region + 0x8000) at all.
For shutting down the system, TWL_FIRM writes MCU[20h]=08h. For returning to
3DS-mode, TWL_FIRM writes to MCU[20h]=04h to trigger a hardware system reboot.
The TWL_FIRM ARM11-process includes a TWL bootloader, see here(?) and here(?)
for details.
TWL_FIRM verifies all TWL RSA padding with the following. This is different
from the DSi "BIOS" code.
The first byte must be 0x0.
The second byte must be 0x1 or 0x2.
Executes a while(<value of byte at current pos in RSA message>). When the
second_byte in the message is 0x1, the byte at curpos must be 0xFF (otherwise
the non-zero value of the byte at curpos doesn't matter). This loop must find a
zero byte before offset 0x7F in the message otherwise an error is returned.
Returns an address for msg_curpos+1.
AGB_FIRM
AGB_FIRM handles running GBA VC titles. The ARM9 FIRM section for TWL_FIRM and
AGB_FIRM are exactly the same (for TWL_FIRM and AGB_FIRM versions which were
updated with the same system-update).
NCCH Header
000h 100h RSA-2048 SHA-256 signature of the NCCH header
100h 4 ID "NCCH"
104h 4 Content size, in media units (1 media unit = 200h bytes)
108h 8 Partition ID (usually same as Program ID, or weird stuff...?)
110h 2 Maker code (3030h)
112h 2 Version (0000h=Normal/Data?, 0001h=Weird?, 0002h=Normal/Code?)
114h 4 SEEDDB Checksum (see NCCH Encryption chapter) (firmware 9.6.0)
118h 8 Program ID (aka Title ID)
120h 10h Reserved
130h 20h Logo Region SHA-256 hash (5.0.0-11 and up)
150h 10h Product code ("CTR-x-xxxx") (for CFA: always "CTR-P-CTAP"?)
160h 20h Extended header SHA-256 hash (SHA256 of 2x Alignment Size... uh?)
180h 4 Extended header size minus 400h, in bytes (usually 400h) (0=None)
184h 4 Reserved
188h .. "Flags" (see below) (aka "ncchflag[0..7]")
188h 3 Unknown (zero)
18Bh 1 Crypto 2nd Keyslot (00h=None, 01h=Key25h, 0Ah=Key18h, 0Bh=Key1Bh)
18Ch 1 Content Platform (01h=CTR=3DS, 02h=Snake=New3DS)
18Dh 1 Content Type Bit-masks: Data=0x1, Executable=0x2, SystemUpdate=0x4,
Manual=0x8, Child=(0x4|0x8), Trial=0x10.
When 'Data' is set, but not 'Executable', NCCH is a CFA.
Otherwise when 'Executable' is set, NCCH is a CXI.
18Eh 1 Content Unit Size (200h SHL N) ;uh, NOT? same as "media units"?
18Fh 1 Flags Bit0=FixedKey, Bit1=NoMountRomFs, Bit2=NoCrypto, Bit5=NewKeyY
190h 4 Plain region offset, in media units
194h 4 Plain region size, in media units
198h 4 Logo Region offset, in media units ;\For applications built with
19Ch 4 Logo Region size, in media units ;/SDK 5+ (5.0.0-11 and up)
1A0h 4 ExeFS offset, in media units
1A4h 4 ExeFS total size, in media units
1A8h 4 ExeFS header size, in media units (for SHA256 at [1C0h])
1ACh 4 Reserved
1B0h 4 RomFS offset, in media units
1B4h 4 RomFS total size, in media units
1B8h 4 RomFS header size, in media units (for SHA256 at [1E0h])
1BCh 4 Reserved
1C0h 20h ExeFS superblock SHA-256 hash
1E0h 20h RomFS superblock SHA-256 hash
All of the hashes stored in this NCCH header are over the cleartext data.
Given offsets are based on the start of the file.
Extended header
The extended header contains additional information regarding/restricting
access control.
--> 3DS Files - NCCH Extended Header
Logo
--> 3DS Files - NCCH Logo
Region Locking
The region-locking info checked by home menu is stored in the "icon" file in
ExeFS.
RSA
CFAs NCCH header signature uses a fixed RSA public key.
CXIs NCCH header signature uses the RSA public key stored in the Exheader
(whereof, that part of the Exheader is signed via another RSA key).
Tools
ctrtool - (CMD) (Windows/Linux) Parsing and decrypting (debug only) NCCH files
The NCCH Exheader contains information for the .code file in the ExeFS (the
.code file itself has no file header, and contains only raw code/data).
The Exheader exists only if NCCH[180h]>0. That is, it does exist for NCCH's
with ExeFS .code file. For some reason ExeFS .firm does also have Exheader (but
unknown if it's used for anything). Whilst E-Manuals have only RomFS, without
ExeFS, and without Exheader.
NCCH Extended Header (Exheader, at offset 200h and up)
200h 200h SCI, System Control Info
400h 200h ACI, Access Control Info 1
600h 100h RSA-SHA256 Signature across [900h..BFFh] (using key from bootrom)
700h 100h RSA Public Key for NCCH Header at [000h..1FFh]
800h 200h ACI, Access Control Info 2 (for limitation of first ACI)
When loading the exheader, Process9 compares the exheader data with the data in
the AccessDesc (note that not everything is compared here). When these don't
match, an error is returned. The Process9 code handling this validation was
updated with v6.0; the only change in this function seems to be the check for
the "Ideal processor" field.
Flag0
Bits Description
0-1 Ideal processor
2-3 Affinity mask
4-7 Old3DS system mode:
0 = Prod (64MB of usable application memory)
1 = Undefined (unusable)
2 = Dev1 (96MB of usable application memory)
3 = Dev2 (80MB of usable application memory)
4 = Dev3 (72MB of usable application memory)
5 = Dev4 (32MB of usable application memory)
6-7 = Undefined Same as Prod?
8-15 = unknown/unspecified
In the exheader data, the ideal processor field is a bit-index, while in the
AccessDesc (the 2nd ACI at A00h and up) the ideal processor field is a bitmask.
When the bit specified by the exheader field is not set in the AccessDesc
field, an error is returned.
if((1 << exheaderval) & accessdescval == 0) return error
Flag1
Bits Description
0 EnableL2Cache (Unknown what this actually does, New3DS-only presumably)
1 cpuspeed_804MHz (Default "cpuspeed" when not set)
2-7 Unused
In order for the exheader to have any of the above new bits set, the AccessDesc
must have the corresponding bit set, otherwise the invalid-exheader error is
returned.
Homebrew which runs under a title which has the above cpuspeed flag set, runs
much faster on New3DS. It's unknown how exactly the system handles these flags.
Flag2
Bit Description
0-3 New3DS system mode:
0 = Legacy (use Old3DS system mode)
1 = Prod (124MB of usable application memory)
2 = Dev1 (178MB of usable application memory)
3 = Dev2 (124MB of usable application memory)
4-7 = Undefined Same as Prod?
8-15 = unknown/unspecified
4-7 Unused
When in Legacy mode, the actual memory layout is the same as in New3DS Prod,
except the available application memory as reported to the application is
reduced to the Old3DS size.
The exheader value for the New3DS system mode value must be equal to the
AccessDesc value, otherwise the invalid-exheader error is returned.
File headers
There are a maximum of 10 file headers in the ExeFS format (the maximum number
of file headers is disputable, with makerom indicating a maximum of 8 sections
and makecia indicating a maximum of 10 (uh, are homebrew tools?). From a
non-SDK point of view, the ExeFS header format can hold no more than 10 file
headers within the currently define size of 200h bytes). The file headers have
the following structure:
00h 8 File name (ASCII, zeropadded) (all 00h for unused entries)
08h 4 File offset in bytes (0=Right after the 200h-byte ExeFS Header)
0Ch 4 File size in bytes
File offsets are non-inclusive of the header's size (200h bytes). Also, file
headers which are not used are filled with all zeros.
The file offsets should be 200h-byte aligned. The file size is usually 4-byte
aligned (unknown if that is actually required).
ExeFS Files
ExeFS or Executable Filesystem contains information related to the executable
program, and is the part of the CXI format.
The ExeFS usually contains one or more of the following files:
.code Contains ARM11 code, which can be optionally
reverse-LZSS compressed via an exheader flag.
.firm Contains FIRM with ARM9/ARM11 code (usually plus some NCCH's)
logo Contains distribution licensing Binary data
banner Contains the banner which homemenu uses for this CXI
icon Contains the icon which homemenu displays for this CXI
--> 3DS Files - NCCH Logo
.code (ARM11)
The .code file does simply contain plain code/data without any file header
(instead, the .code file's load addresses and compression flag are located in
the NCCH Exheader).
For the LZrev decompression function, see:
--> LZ Decompression Functions
The (decompressed) filesize should be a multiple of 1000h bytes (and the
code/const/data sections should be on 1000h-byte page boundaries, as specified
in the NCCH Exheader).
.code (GBA)
The .code files for GBA games do reportedly contain the GBA ROM-image, with an
extra GBA Footer (with info on cartridge type and preferred LCD color scheme).
For details:
--> 3DS Config - ARM7 Registers (GBA/NDS/DSi Mode)
Unknown if GBA games have specific entries in NCCH header/exheader.
The extended header, the ExeFS, and the RomFS are encrypted using AES-CTR.
Special Cases
if NCCH[18Fh].bit2=1 ;\NoCrypto flag (eg. in NCCH's
Exit ;not encrypted ;/located inside of FIRM files)
if NCCH[118h..11Fh]=NCCH[400h..407h] ;\
SkipDecrypt (or NeedEncrypt) ; Program ID in Header vs Exheader
;above can be checked only if Exheader ; currently/already decrypted
;does exist, ie. if NCCH[180h]<>0 ;/
if NCCH[18Fh].bit0=1 ;FixedCryptoKey flag ;\
if (ProgramID.MSW AND FFFFC010h)=00040010h ; debug only, not retail:
NormalKey=FixedSystemKey (52h,7Ch,E6h,30h,..) ; instead of First/Second
else ; KeyX+KeyY
NormalKey=Zerofilled (00h's) ;/
Encryption IV
if NCCH[112h]=01h ;NCCH version (weird, is/was that version really used?)
Force MediaUnitSize=1 (or 200h?) ;fixed? (instead of 200h SHL N bytes?)
IV[00h..07h] = NCCH[108h..10Fh] ;NCCH Partition ID (forwards!)
IV[08h..0Bh] = Zero
IV[0Ch..0Fh] = BigEndianAddr (200h=Exheader, [1A0h]=ExeFS, [1B0h]=RomFS)
if NCCH[112h]=02h (or =00h, too?) ;NCCH version
IV[00h..07h] = NCCH[10Fh..108h] ;NCCH Partition ID (backwards!)
IV[08h] = Type (01h=Exheader, 2=ExeFS, 3=RomFS)
IV[09h..0Fh] = Zero (plus offset/10h within Exheader/ExeFS/RomFS area)
When starting elsewhere than BEGIN of Exheader/ExeFS/RomFS, add offset/10h to
the IV value (whereas, mind that IV is big-endian in the above description; it
may be easier to set the IV in little-endian mode though).
The logo was originally stored as file "logo" (in the encrypted ExeFS). Newer
files have the logo stored in separate unencrypted data block (see NCCH header
entries [130h,198h,19Ch]). Even in newer firmwares, the old location in "logo"
file is still used by Safe Mode files (at least so on Old3DS). Unknown if the
new logo block can also exist in absence of ExeFS.
Logo Compression
Reportedly "contains distribution licensing Binary data".
"The size of this logo is always 2000h-bytes."
The logo seems to be LZ11 compressed, see:
--> LZ Decompression Functions
This file is a LZ11 compressed DARC. The last 20h bytes of the decompressed
data is a HMAC SHA256 hash over the actual DARC.
The HMAC key(s) used for the SHA256-HMAC is unknown.
The below AES-CMACs (including the last 0x10-bytes of the header) are only used
for SD titles, for NAND download-play titles, and non-system DSiWare titles.
For other titles, these MACs are set to all-zero.
000h 4 .cmd ContentID, for the .cmd filename. This is the beginning
of the header ;uh, which header? what for?
004h 4 Number of AES-CMACs and Content IDs in the first list (X).
The method to determine this is explained below.
008h 4 Number of Content IDs in the second list (Y)
00Ch 4 Unknown, usually (always?) 1.
010h 10h AES-CMAC over first 0x10
020h 4*X List of installed Content IDs in order of Content Index, with
missing contents replaced with 0xFFFFFFFF
020h+4*X 4*Y List of installed Content IDs in order of ID name
020h+4*(X+Y) 10h*X AES-CMACs for each content in the first list, generated
using the process below
The number of AES-CMACs depends on the highest Content Index installed. For
example, a title with 5 contents, but only 1 and 3 are installed, will still
result in 3 AES-CMACs, with the 2nd one being unused.
For TWLNAND contents, the same process is used (even for SRL contents) with the
keyslot for NAND dbs.
Signature Type
Value Signature Method Signature Size Padding Size
0x010000 RSA_4096 SHA1 (Unused for 3DS) 0x200 0x3C
0x010001 RSA_2048 SHA1 (Unused for 3DS) 0x100 0x3C
0x010002 Elliptic Curve with SHA1 (Unused for 3DS) 0x3C 0x40
0x010003 RSA_4096 SHA256 0x200 0x3C
0x010004 RSA_2048 SHA256 0x100 0x3C
0x010005 ECDSA with SHA256 0x3C 0x40
The hash for the signature, is calculated over the header of the TMD.
TMD Format
000h 4 Signature Type (00h,01h,00h,04h) (100h-byte RSA-SHA256)
004h 100h Signature RSA-SHA256 across 140h..203h
104h 3Ch Signature padding/alignment (zerofilled)
140h 40h Signature Name "Root-CA00000003-CP0000000b", 00h-padded
180h 1 TMD Version (always 1 on 3DS, unlike DSi)
181h 1 ca_crl_version (0)
182h 1 signer_crl_version (0)
183h 1 Zero (padding/align 4h)
184h 8 System Version (0)
18Ch 8 Title ID
194h 4 Title Type (40h, big-endian)
198h 2 Group ID (0)
19Ah 4 SD/MMC "public.sav" filesize in bytes (3DS: savedata size)
19Eh 4 SD/MMC "private.sav" filesize in bytes (3DS: 0=none)
1A2h 4 Zero
1A6h 1 SRL Flag (00h=3DS, but also 0=DSiware, uh?)
1A7h 3 Zero
1AAh 10h Zerofilled (DSi: Parental Control Age Ratings)
1BAh 1Eh Zerofilled
1D8h 4 Access Rights (0)
1DCh 2 Title Version
1DEh 2 Content Count (number of entries at B04h)
1E0h 2 Boot Content
1E2h 2 Padding
1E4h 20h SHA256 across Content Info Records at [204h..B03h]
204h 900h Content Info Records (40h entries, with 24h-bytes each)
B04h 30h*N Content Chunk Records (N entries, with 30h-bytes each)
Content Info Records (useless, can be ignored, except for error checking)
There are 64 of these records, usually only the first is used.
000h 2 Content index offset (I)
002h 2 Content command count (N)
004h 20h SHA256 across TMD[B04h+I*30h+(0..N*30h-1) ;(?)
Certificate Chain
If the TMD file is obtained from Nintendo's CDN, then it will have two
certificates appended at the end of the file:
CERTIFICATE SIG.TYPE RETAIL CERT DEBUG CERT DESCRIPTION
TMD RSA-2048 CP0000000b CP0000000a to verify the TMD signature
CA RSA-4096 CA00000003 CA00000004 to verify the TMD Certificate
The CA certificate is issued by 'Root', the public key for which is stored in
NATIVE_FIRM.
Tickets are a format used to store an encrypted titlekey (using AES-CBC). With
3DS, the Ticket format was updated (now v1) from Wii/DSi format (v0).
--> DSi SD/MMC DSiware Tickets and Title metadata
Ticket format
Pre 4 One (1) (unknown purpose) ;\little endian ;\in ticket.db
Pre 4 Size of below ticket (350h) ;/ ;/(not in .cia's)
000h 4 Signature Type (00h,01h,00h,04h) (100h-byte RSA-SHA256)
004h 100h Signature RSA-SHA256 across 140h..34Fh ?
104h 3Ch Signature padding/alignment (zerofilled)
140h 40h Signature Name "Root-CA00000003-XS0000000c", 00h-padded
180h 3Ch ECC Public Key (uh, what for?) (can be zero/none)
1BCh 1 Ticket Version (always 1 on 3DS) (unlike DSi/Wii)
1BDh 1 CaCrl Version
1BEh 1 SignerCrl Version
1BFh 10h TitleKey (normal-key encrypted using one of the common keyYs)
1CFh 1 Zero
1D0h 8 Ticket ID (00,04,xx,xx,xx,xx,xx,xx) ? (...or random 64bit)
1D8h 4 Console ID (Decrypted OTP[04h..07h], in reverse byte-order)
1DCh 8 Title ID (00,04,xx,xx,xx,xx,xx,xx) (same as ticket filename)
1E4h 2 Zero
1E6h 2 Title Version
1E8h 4 Zero
1ECh 4 Zero
1F0h 1 License Type
1F1h 1 Common keyY number for [1BFh] (0..5) (1 for retail system titles)
1F2h 2Ah Zero
21Ch 4 eShop Account ID? (zero in many system files)
220h 1 Zero
221h 1 Audit (whatever, usually 01h) (can be 00h, for debug/whatever?)
222h 20h 00h-filled (Wii: Content access permissions, 1 bit per content)
242h 20h 00h-filled (Wii: Content access permissions, 1 bit per content)
262h 2 Zero
264h 40h Limits
2A4h ACh Content Index (*) (uh, but WHAT is a Content Index ??)
350h .. Certificates (included in e-Shop downloads, not stored in files)
* The Content Index of a ticket has its own size defined within itself (usually
ACh), with seemingly a minimal of 20 bytes.
Signature Type
Value Signature Method Signature Size Padding Size
0x010000 RSA_4096 SHA1 (Unused for 3DS) 0x200 0x3C
0x010001 RSA_2048 SHA1 (Unused for 3DS) 0x100 0x3C
0x010002 Elliptic Curve with SHA1 (Unused for 3DS) 0x3C 0x40
0x010003 RSA_4096 SHA256 0x200 0x3C
0x010004 RSA_2048 SHA256 0x100 0x3C
0x010005 ECDSA with SHA256 0x3C 0x40
The hash for the signature is calculated over the Ticket Data.
The Ticket Title Version is generally the same as the title version stored in
the Title Metadata. Although it doesn't have to match the TMD version to be
valid.
Limits
In demos, the first u32 in the "Limits" section is 0x4, then the second u32 is
the max-playcount.
Certificate Chain
Tickets retrieved from CDN/SOAP have a certificate chain appended at the end of
the file. There are two certificates in this chain:
CERTIFICATE SIG.TYPE RETAIL CERT DEBUG CERT DESCRIPTION
Ticket RSA-2048 XS0000000c XS00000009 to verify Ticket signature
CA RSA-4096 CA00000003 CA00000004 to verify Ticket Certificate
The CA certificate is issued by 'Root', the public key for which is stored in
NATIVE_FIRM.
Notes
CommonETicket (for short, cetk) is the name given to tickets for titles which
are not available on the eShop, like system titles. As the name suggests, they
are not unique tickets, the same ticket is common to each 3ds which has
installed that title. This is in contrast to tickets for eShop content, which
are generated prior to initial download, and are unique to 3ds it was generated
for.
CETK can be fetched through HTTP using the link to default update server, using
the title's TMD URL where "cetk" is used instead of "tmd" for the URL. The 3DS
NIM module retrieves system tickets via SOAP request GetSystemCommonETicket
instead of directly downloading the cetks with HTTPS. The cetks are also
accessible via HTTP (even though the 3DS never accesses them like that).
3ds:\dbs\import.db
sd:\Nintendo 3DS\<ID0>\<ID1>\dbs\import.db
Import Databases, containing entries for titles (or versions of titles) not yet
installed, ready for transferring to the title.db. ("Automatic Update uses
this, so completing the update takes seconds." uh, why does that take so much
time?)
3ds:\dbs\tmp_t.db
Temporary Title database containing one entry for the currently installed
Download Play Child.
3ds:\dbs\tmp_i.db
Similar to import.db, except it's used in conjunction with tmp_t.db, for
installing Download Play Children.
The inner content of the container consists of a pre-header with size of 0x80
identifying the Database Type, followed by a BDRI container. The offsets in the
BDRI header are usually relative to the offset to the start of the BDRI header
(0x80 in the file)
Pre Header
000h 8 ID (eg. "NANDTDB",00h) (see below)
008h 78h Reserved
080h ... BDRI filesystem (with 80h-byte files containing Title Info)
The 8-byte ID can be:
ID="NANDIDB",00h --> 3ds:\dbs\import.db
ID="NANDTDB",00h --> 3ds:\dbs\title.db
ID="TEMPIDB",00h --> 3ds:\dbs\tmp_i.db, tmp_t.db
ID="TEMPTDB",00h --> sd:\Nintendo 3DS\<ID0>\<ID1>\dbs\import.db, title.db
Notes
"It is important to note the database doesn't contain a hash of the .cmd. So if
a user has more than one valid set of application data for a given .cmd Content
ID they can be manually interchanged without issue. Though renaming a .cmd file
to match the Content ID which the title.db is expecting will result in an
error, as the CTR for the per-console encryption layer changes depending on the
file path, and the MAC of the .cmd is probably generated with the .cmd Content
ID in mind."
"These NAND/SD /dbs images seem to be loaded by the ARM9 while NATIVE_FIRM is
booting."
"Removing ticket.db from a New3DS with signature checks disabled will not
result in an unbootable system, however all icons except Slot-1 will disappear
from Home. Applets can however still be used. Recovery can be accomplished via
hardmod or arm9loaderhax plus a known good backup of the file (or the whole
partition or disk); Gamecard exploits were not tested, and Browserhax did not
work."
TMD (B34h+N*30h bytes), contains info about the separate APP file(s)
--> 3DS Files - Title Metadata (TMD)
APP file(s)
This region can contain one or more contents (eg. separate .app files for
executable and manual, with .app sizes as listed in the TMD file; the .app
files can be 3DS NCCH images, or DSiware images, or DSi datafiles like DS Cart
Whitelist).
The .app contents are usually encrypted using the ticket's titlekey (see the
Ticket chapter for details).
There are two unencrypted variants:
1) Encryption can be disabled in Content Type flags in the TMD file (that's
done in most or all homebrew CIA's like ctrQuake.cia)
2) Pre-retail prototype CIA's from mid 2010 didn't include tickets, and are
thus unencrypted (the Ticket Size entry in CIA header is probably zero?)
APP Flags
This appears to be a 64Kbit array with flags for Content Index 0000h..FFFFh
(the first flag for index 0000h being located in bit7 of first byte).
The number of contents and content indices are found in the TMD file (most
titles have only 1 or 2 contents, so the first flag byte is usually 80h or C0h,
followed by 1FFFh zero bytes).
Unknown if these flags are used for anything... maybe there are cases where the
TMD lists multiple APPs, but only one of them being updated in the CIA?
Overview
CIA format allows the installation of titles to the 3DS. CIA files and titles
on Nintendo's CDN contain identical data. As a consequence, valid CIA files can
be generated from CDN content. This also means CIA files can contain anything
that titles on Nintendo's CDN can contain. Uh, what is a CDN?
Under normal circumstances CIA files are used where downloading a title is
impractical or not possible. Such as distributing a Download Play child, or
installing forced Gamecard updates. Those CIA(s) are stored by the titles in
question, in an auxiliary CFA file.
Development Units, are capable of manually installing CIA files via the Dev
Menu.
Format
The CIA format has a similar structure to the Wii's WAD format (aka DSi Tad?).
The file is represented in little-endian.
The data is aligned in 40h-byte blocks (if a content ends at the middle of the
block, the next content will begin from a new block).
This system update CFA contains the below files in the RomFS. This CFA is
stored in the NCSD system-update partition (partition 7), the data from this
CFA RomFS can also be transferred for Download Play when the client needs
updated.
ROM Cart NCSD Partition 6, NCCH RomFS:\SNAKE\cup_list ;\New3DS System Update
ROM Cart NCSD Partition 6, NCCH RomFS:\SNAKE\*.cia ;/
ROM Cart NCSD Partition 7, NCCH RomFS:\cup_list ;\Old3DS System Update
ROM Cart NCSD Partition 7, NCCH RomFS:\*.cia ;/
cup_list
This uses the same format as the CVer cup_list, this system-update CFA cup_list
contains the titleIDs for all of the titles stored in this RomFS.
--> 3DS Files - Version (CVer and NVer)
<titleID>.cia
This is the CIA for each system-update title, for retail gamecards these CIAs
are generated from the titles available on CDN at the time the NCSD image was
finalized. The latest version(at the time of CFA generation) of every system
title from CDN is stored here, excluding titles with the title-versions for
1.0.0-0.
New3DS
New3DS system-update partitions are located at partition6 in gamecards. The
RomFS contains a "SNAKE" directory, the contents of that directory have the
same structure as the Old3DS sysupdate CFA RomFS.
Late 2010
The final version was invented in late 2010 (and, with the 3DS being released
in 2011, retail CIA's are probably always using the final version).
The 3DSX format is a homebrew executable file format. The main feature is
having relocateable code, which may have been required for some older exploits
that didn't provide full control of the virtual memory mapping.
As such, the .3dsx format is no longer useful (at least not once when having
installed a bootloader), and one could instead use regular .code, .firm, .ncch,
or .cia files for homebrew.
Note
Some 3DSX files can be found at:
http://www.3dbrew.org/wiki/Homebrew_Applications
The console-unique CTCert is used for signing CTX files (uh, really signing
them? with a public key??), the DeviceCert used by eShop, and for DSiWare
exports. This ECDSA signature, the ECDSA private key for this cert, and the
IssuerID is loaded from memory initialized by bootrom instead of NAND. This is
the 3DS equivalent of the DSi TWCert (aka the "TW cert" in DSi "Tad" files?).
The CTCert is signed with ECDSA by Nintendo. CTCerts can be verified via a DER
stored in NATIVE_FIRM, separate DERs are used for retail and dev/debug.
Structure
000h 4 Signature Type (00010005h)
004h 3Ch Signature ECDSA
040h 40h Signature padding/alignment (zerofilled)
080h 40h Signature Name (retail="Nintendo CA - G3_NintendoCTR2prod")
(dev="Nintendo CA - G3_NintendoCTR2dev")
0C0h 4 Key Type
0C4h 40h Key Name "CT<DeviceId>-<ConsoleType>" aka "CTxxxxxxxx-xx"?
DeviceId is the hex DeviceId (aka Decrypted OTP[04h..07h]?)
ConsoleType is "00"=retail, "01"=dev
104h 04 Key Expiration UNIX Time, big endian (seconds since 1 Jan 1970 ?)
108h 3Ch Key Public ECDSA Key (point X,Y)
"This is two consecutive u8 arrays (each one of length 1Eh),
where the first one corresponds to the ECDSA R coordinate,
and the second to ECDSA S coordinate. These are in big endian."
144h 3Ch Key padding/alignment (zerofilled)
The ECDSA public key for this cert is converted from the ECDSA private key
initialized by bootrom (uh, that's probably meant to be from Decrypted OTP).
The curve used for ECDSA is sect233r1.
NJDC files contain dictionaries (maybe for spellchecking?), NJDC files are
found in:
Shared Data Archives: Dictionary (RomFS:\..\*.a) ;for console/region languages
System Applets: 3DS Browser applet (RomFS:\iwnn\..\*.a) ;for all languages
Dictionary Format
The files contain a header and several large tables. The header size (and the
location/presence of the header entries) varies from file to file; possibly
depending on some header flags?
All values, offsets and UTF-16 chars are BIG-ENDIAN.
000h 4 Header ID ("NJDC")
004h 2 Unknown (1 or 2)
006h 2 Unknown (0 or 1)
008h 2 Unknown (4 or 5 or 0Fh)
00Ah 2 Unknown (0)
00Ch 4 Total Filesize minus a few bytes?
010h 4 Unknown (00xxh)
014h 4+4 Unknown (00xxh,00xxh) (usually both the same value)
01Ch 4 Unknown (00xxh)
... .. ???
... 4 Offset to 10-byte Table
... 4 Offset to UTF-16 Strings
... 4 Offset to 2-byte Table
.. .. Some zeroes and offsets?
... 4 Offset to 2 bytes? (08h,06h)
... 4 Values 00h,01h,01h,01h
... 4 Values 00h,01h,01h,01h
... .. ???
... 4 Number of words (N) ?
... .. ???
... .. 4-byte Table (maybe some lookup table?)
... 2 2 bytes? (08h,06h)
... N*10 10-byte Table (see below)
... .. UTF-16 Strings (raw strings, without trailing zeroes)
... N*2 2-byte Table (values 0101h*(40h..7Dh)?) (flags/lookup?) (if any)
... 4 Footer ID ("NJDC") (can be unaligned)
10-byte Table:
000h 1 String Length in bytes (always even, since chars are UTF-16)
001h 3 String Offset (relative to String Table base)
004h 6 Zerofilled
GBIN Files are found in 3DS Camera & 3DS Sound (RomFS:\res\Guide*.gbin).
The files contain several "T_xxx" and "D_xxx_y" strings, bundled with unknown
small numbers.
Purpose is unknown, maybe some Tree structure, or a list of Chapters (T) and
Pages (D).
The files contain no real data, so they do probably refer to whatever other
files, ie. translating names to file indices and/or assigning attributes.
GBIN Format
000h 4 ID "GBIN"
004h 4 Number of GUID entries
008h .. GUID entries
GUID entry format:
000h 4 ID "GUID"
004h 4 Number of D-entries
008h 4 Unknown (0 or 1 or 2)
00Ch 4 Unknown (0 or 1 or 2)
010h 4 Unknown (0..0Fh?)
014h 0Ch Unknown (0)
020h 10h T-Name ("T_001" and up, zeropadded)
030h N*14h D-Entries
D-Entry Format:
000h 10h D-NAME ("D_001_0" and up, zeropadded)
010h 4 Unknown (0..04h?)
CRO0 and CRR0 files are reportedly somehow related, but unknown how exactly.
System Tools: Nintendo Network ID Settings and System Applets: Miiverse have
"RomFS:\.crr\static.crr" ;-CRR0 (whatever)
"RomFS:\cro\static.crs" ;-CRO0 (without actual code/data in there)
System Data Arvives 1: web-lot/OSS CROs has
"RomFS:\cro2\oss.cro" ;\both are CRO0's (with code/data each)
"RomFS:\cro2\webkit.cro" ;/(but without any CRR0 file)
System Applets 3DS Browser has
"RomFS:\.crr\static.crr" ;-CRR0 (whatever)
"RomFS:\*.cro.lex" ;-several LZ11 compressed .cro's
"RomFS:\static.crs" ;-CRO0 (without actual code/data in there)
Unknown if/where any more such files exist.
CRO with extension .cro is used for "DLLs". CRS with extension .crs is in the
same format of CRO but storing the symbol information of the static module (the
main application) (uh, aka the "ExeFS:\.code" file?) (uh, and, importantly,
.crs files seem to contain only symbols and stuff (and empty code/data
sections)).
Upon loading, the RO module will look for export symbol "nnroAeabiAtexit_" to
patch it to its import symbol "__aeabi_atexit".
DARC archives are used in various places, sometimes uncompressed, or often with
LZSS or LZ11 compression. For example,
Uncompressed DARC Manual.bcma file (e-manual)
LZSS compressed DARC .arc files (nested within above .bcma file)
LZ11 compressed DARC NCCH Logo (in NCCH Header, or NCCH ExeFS:\logo)
LZ11 compressed DARC .arc.LZ files (eg. in 3DS Camera RomFS "lyt" folder)
The DARC format is about same as the Wii's U8 format (with different header,
different byte-order, and UTF-16 instead of ASCII names).
DARC header
000h 4 ID "darc"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (001Ch)
008h 4 Version (01000000h)
00Ch 4 Total Filesize (excluding trailing 20h-byte SHA256-HMAC, if any)
010h 4 Offset of File/Folder List (usually 1Ch)
014h 4 Size of File/Folder List, PLUS File/Folder Name Area
018h 4 Offset of File Data Area
.. .. File/Folder List (0Ch bytes per file/folder)
.. .. File/Folder Name Area (UTF-16)
.. .. File Data Area (usually each file is 20h-byte aligned)
(..) (20h) Trailing SHA256-HMAC, if any (this is NOT 20h-byte aligned)
Special Cases
3DS Face Raiders RomFS:\hal\effect\kbb\kbb.dat doesn't have a "." dot folder.
3DS Mii Maker RomFS:\shaders\shader.arc has nested folders & empty folders.
3DS Activity Log RomFS:\P_UlcdTest_LZ.bin contains an empty darc.
Example
64 61 72 63 ;id "darc"
FF FE 1C 00
00 00 00 01
28 65 00 00
1C 00 00 00
1C 04 00 00
40 04 00 00
00 00 00 01 00 00 00 00 15 00 00 00 ;00h folder ""
02 00 00 01 00 00 00 00 15 00 00 00 ;01h folder "."
06 00 00 01 01 00 00 00 09 00 00 00 ;02h folder "anim";\
10 00 00 00 40 04 00 00 F8 00 00 00 ;03h ;
54 00 00 00 40 05 00 00 EC 00 00 00 ;04h ;
98 00 00 00 40 06 00 00 F8 00 00 00 ;05h ;
DC 00 00 00 40 07 00 00 CC 0C 00 00 ;06h ;
20 01 00 00 20 14 00 00 54 0C 00 00 ;07h ;
64 01 00 00 80 20 00 00 4C 02 00 00 ;08h ;/
A8 01 00 01 01 00 00 00 0C 00 00 00 ;09h folder "..." ;\
B2 01 00 00 E0 22 00 00 A8 02 00 00 ;0Ah ;
E2 01 00 00 A0 25 00 00 3C 10 00 00 ;0Bh ;/
12 02 00 01 01 00 00 00 15 00 00 00 ;0Ch folder "..." ;\
1C 02 00 00 00 36 00 00 28 04 00 00 ;0Dh ;
3E 02 00 00 80 3A 00 00 28 01 00 00 ;0Eh ;
60 02 00 00 00 3C 00 00 28 04 00 00 ;0Fh ;
82 02 00 00 80 40 00 00 28 08 00 00 ;10h ;
A4 02 00 00 00 49 00 00 A8 00 00 00 ;11h ;
C4 02 00 00 00 4A 00 00 28 08 00 00 ;12h ;
DC 02 00 00 80 52 00 00 28 02 00 00 ;13h ;
F4 02 00 00 00 55 00 00 28 10 00 00 ;14h ;/
00 00 ;name "",0000h
2E 00 00 00 ;name ".",0000h
61 00 6E 00 69 00 6D 00 00 00 ;name "anim",0000h
...
SARC archives contain only files, not folders. However, the filenames do
usually contain slashes (eg. "bsnd/cursor.bcwav"), so software could split
those names into folder+filename, if desired.
SARC is used by 3DS eShop Applet, RomFS:\layout\ and RomFS:\sound\.
SARC Header
000h 4 ID "SARC"
004h 2 Header Size (14h)
006h 2 Byte Order (FEFFh)
008h 4 Total Filesize
00Ch 4 Data Offset (aka Size of SARC+SFAT+SFNT)
010h 2 Unknown/version? (always 0100h)
012h 2 Unknown/reserved? (0)
.. .. SFAT Chunk (see below) (Directory)
.. .. SFNT Chunk (see below) (Filename strings)
.. .. Data
Tools
SARC Extractor/Creator with TAR-like command line flags. Can decompress a .zlib
SARC file (4-byte size header + ZLIB data).
arcless Format
This is a very simple archive format, found in some LZ-compressed files, eg. in
3DS Sound and 3DS Camera (RomFS:\lyt\C.LZ and RomFS:\shaders\shaders.LZ), 3DS
Picture Picker (RomFS:\sound\csnd.LZ), and also in uncompressed form, eg. 3DS
Sound (RomFS:\res\S.pack).
000h+N*40h 38h Filename (ASCII, zeropadded) ;\
038h*N*40h 4 File Offset (always 80h-aligned) ;
03Ch*N*40h 4 File Size ; header
.. 1 Zero (indicates end of directory) ;
.. .. Zeropadding to 80h-byte boundary ;/
xxx*80h .. File data (at above offsets) ;\data
.. .. Zeropadding to 80h-byte boundary, after each file ;/
The header doesn't contain any ID (like "NARC", "SARC", or "darc" or so).
However, one can more or less reliably detect it by checking for valid ASCII
characters, zeropaddings, 1st Offset being located after the directory, further
Offsets being located at Offset+Size+Alignment from previous entry, and with
Offset+Size not exceeding the archive size.
Filetypes Entries
000h 4 Number of Files for the Filetype (0=None)
004h 4 Offset to File List for the Filetype (FFFFFFFFh=None)
008h 4 Offset to Filetype name (eg. "unknown",0 or "zsi",0 etc.)
00Ch 4 Unknown (always FFFFFFFFh)
The File List contains a list of 32bit File indices for the Filetype (0=1st
file, 1=2nd file, etc).
The number of filetypes varies between 2 and 8 in known files. Known filetype
names are:
"anb",00h boy/.../*.anb ;eg. in actor\zelda_link_child_ultra.zar
"ccb",00h ?
"cmab",00h misc/.../*.cmab
"cmb",00h Model/.../*.cmb (or lowercase, model/.../*.cmb)
"csab",00h Anim/.../*.csab
"ctxb",00h tex/.../*.ctxb
"faceb",00h boy/.../*.faceb ;eg. in actor\zelda_link_opening.zar
"qdb",00h demo/.../*.qdb ;eg. in actor\zelda_horse.zar, scene\*.zar
"tbd",00h txt/.../*.tbd ;eg. in kankyo\kankyo_common.zar
"unknown",00h Anim/.../*.cskla ;eg. in actor/zelda_magic_wind.zar
"zsi",00h collision/.../*.zsi
Type "unknown" does always exist as first type entry (even if it contains no
files; the only archive containing an "unknown" file is
actor/zelda_magic_wind.zar, which contains Anim/new_magic_wind.cskla).
Filesize/Filename Entries
000h 4 File size
004h 4 Offset to filename (ASCII, terminated by zero)
Fileoffset Entries
000h 4 Offset to File data
Directories
The ZAR format doesn't directly support directories. However, most filenames
contain slashes so one could split those into folder/filename.
Note: RomFS:\scene\*.zar does use "\" backslashes instead of "/" slashes, that,
with some names starting with dot or dotdot (".\" or "..\..\").
If desired, one could also treat the ZAR's Filetypes section as top-level
directories, or as filetype suffix (although "Model" and ".cmb" in filenames
like "Model\filename.cmb" do already imply the type anyways).
Note
See https://wiki.cloudmodding.com/oot/Category:File_Formats for more Zelda
fileformats (QBF, QCL, QM, etc).
The two HWCAL files contain (initial?) calibration values, the data is also
stored in the system settings "config" file, unknown which of those three files
contains the most up to date values for daily use.
--> 3DS Files - Config Savegame
Reading
"If 0x1FF81006 (uh, what, where from?) is 3 or 4 or 7 or 8 or 9 then the
calibration data is read from the EEPROM using the i2c:EEP service command
0x001000C0, using offset 0x000 for HWCAL0, and offset 0x800 for HWCAL1.
Otherwise attempt is made to read CTRNAND:/ro/sys/HWCAL(0|1).dat instead."
Summary
Below shows the offset in file (and in raw data area), the size (excluding
checksum and Value 0001h), the BlkID corresponding "config" file entries, and
the "Aging flags" bit number.
File Data Size BlkID Bit Description
000h - 200h - - Header
200h 000h 10h 00040000h 3 Input Touchscreen
214h 014h 08h? 00040001h.1 Input Circle Pad (part 1)
220h 020h 2 00050000h 1 LCD Screen flicker (VCOM)
224h 024h 1 00010000h 7 RTC Compensation value (WHAT is that???)
228h 028h 1 00030000h RTC Correction value
230h 030h 8Ah 00060000h.1 2? Outer Cameras (part 1)
2BCh 0BCh 12h 00040002h 6 Input Gyroscope
2D0h 0D0h 0Ch 00040003h 8 Input Accelerometer
2E0h 0E0h 134h 00020000h 5 Codec (CDC aka TSC)
418h 218h 04h 00050007h null? LCD or Programmable Infrared Transmitter?
420h 220h 214h 00070000h 9? Sound Surround 3D filters
640h 440h 20h 00050003h 10 LCD Power saving mode (ABL) (read by GSP)
670h 470h 20h 00050005h 11? LCD Stereoscopic Display Settings
6A0h 4A0h 38h 00050002h 12 LCD Backlight PWM (BLPWM)
6E0h 4E0h 18h 00040001h.2 Input Circle Pad (part 2)
700h 500h 0Ch 00060000h.2 Outer Cameras (part 2)
710h 510h 20h 00050004h LCD Power saving mode (ABL) (read by LGY)
740h 540h 08h 00120000h not? Slider Calibration
750h 550h 02h 00050006h not11? LCD 2D/3D Mode Switching Delay
760h 560h 08h 00070002h not? Sound Microphone echo cancellation
770h 570h 10Ch 00050008h not? LCD Power saving mode (ABL) extra ;New3DS
880h 680h 08h 00040004h not? Input CStick (Right analog stick) ;New3DS
890h 690h 18h 00180001h null? QTM (Quad Tracking Module) ;New3DS
Unknown things
The HMAC key for header signature is unknown.
The Checksum function is unknown (for 1-2 byte sections it's just the 1-2
byte(s) XORed FFh).
The purpose of most entries is unknown.
Unknown how to read the EEPROM data (maybe similar as for Wifi EEPROM?).
Unknown what size EEPRM has (apparently at least 1000h bytes).
Unknown if EEPROM has any header (maybe only 30h bytes instead 200h bytes?) (it
should/must have header entry[00Dh]).
This page describes the format of the "Cfg NAND savegame" (whut?). These blocks
can be accessed with the "Cfg service commands".
Configuration blocks
BlkID Flags Size Description
00000000h 0Ch 2 Config Version? (0015h or 0039h)
00010000h 0Ch 1 RTC Compensation value (usually 80h) (WHAT is that???)
00020000h 0Ch 134h Codec (CDC aka TSC)
00030000h 0Ch 1 RTC Correction value (read by PTM)
00030001h 0Eh 08h RTC Time offset (read by CECD): displayed_time-rtc_time
00030002h 0Ch 08h RTC Settings Time offset: newly_set_time-rtc_time
00040000h 0Ch 10h Input Touchscreen
00040001h 0Ch 1Ch Input Circle Pad (left Analog Stick)
00040002h 0Ch 12h Input Gyroscope
00040003h 0Ch 0Ch Input Accelerometer
00040004h 0Ch 1Ch Input CStick (Right analog stick)
00050000h 0Ch 2 LCD Screen flicker (VCOM)
00050001h 0Ch 2 LCD Backlight controls (read by GSP)
00050002h 0Ch 38h LCD Backlight PWM (read by GSP)
00050003h 0Ch 20h LCD Power saving mode (ABL) calibration (read by GSP)
00050004h 0Ch 20h LCD Power saving mode (ABL) calibration (read by LGY)
00050005h 0Eh 20h LCD Stereoscopic Display Settings
00050006h 0Ch 2 LCD 2D/3D Mode Switching Delay
00050007h 0Ch 4 LCD or Programmable Infrared Transmitter? (PIT)
00050008h 0Ch 10Ch LCD Power saving mode (ABL) extra config ;New3DS
00050009h 0Ch 08h LCD new3DS only(?) backlight control ;New3DS
00060000h 0Ch 96h Outer Cameras
00070000h 0Eh 214h Sound Surround 3D filters
00070001h 0Eh 1 Sound Output Mode (mono=0, stereo=1, surround=2)
00070002h 0Eh 08h Sound Microphone echo cancellation params
00080000h 0Ch C00h Wifi Internet Access Point 1
00080001h 0Ch C00h Wifi Internet Access Point 2
00080002h 0Ch C00h Wifi Internet Access Point 3
00090000h 0Eh 08h User ID 1 (for NWMUDS:InitializeWithVersion)
00090001h 0Eh 08h User ID 2 (for GenHashConsoleUnique)
00090002h 0Eh 4 User ID Random
000A0000h 0Eh 1Ch User Name in UTF16 (and NGWord version)
000A0001h 0Eh 2 User Birthday (u8 month, u8 day)
000A0002h 0Eh 1 User Language
000B0000h 0Eh 4 Local Country/State Codes
000B0001h 0Eh 800h Local Country name in UTF-16 (in various languages)
000B0002h 0Eh 800h Local State name in UTF-16 (in various languages)
000B0003h 0Eh 4 Local Country/State Coordinates
000C0000h 0Eh C0h Parental Restrictions
000C0001h 0Eh 14h Parental Child Online Privacy Protection (COPPACS)
000C0002h 0Eh 200h Parental Email and Custom Secret Question
000D0000h 0Eh 4 EULA Version which was agreed to
000E0000h 0Eh 1 Wifi Internet Spotpass Flags
000F0000h 0Ch 10h System Debug configuration
000F0001h 0Ch 8 System ?
;000F0002h - - System N/A (or did this exist in some/older firmwares?)
000F0003h 0Ch 1 System ?
000F0004h 0Ch 4 System Model value byte, followed by 3 unknown bytes
000F0005h 0Ch 4 System Network Update Enable
000F0006h 0Ch 28h System NPNS string for "X-Device-Token" http header field
00100000h 0Ch 2 DSi EULA
00100001h 0Ch 94h DSi Parental Restrictions
00100002h 0Ch 1 DSi Country
00100003h 0Ch 10h DSi ?
00110000h 0Ch 4 Boot System Setup Request flag
00110001h 0Ch 8 Boot TitleID of Home Menu
00120000h 0Ch 8 Slider Calibration (Read by HID and PTM)
00130000h 0Eh 4 Debug mode enable
;00140000h - - Reserved BlkID for SecureInfo Region ;\not used in
;00140001h - - Reserved BlkID for SecureInfo Serial/Barcode ;/config file
00150000h 0Ch 4 ?
00150001h 0Ch 8 ?
00150002h 0Eh 4 NPNS: Character for making the URL for NPNS
00160000h 0Eh 4 Unknown, 1st byte is used by config service-cmd 00070040h
00170000h 0Eh 4 Miiverse (OLV) access key
00180000h 0Ch 4 QTM Infrared LED related, can be 0 or 1 ... maybe "PIT"?
00180001h 0Ch 18h QTM calibration data
00190000h 0Ch 1 NFC module (checks for value1/non-value1)
The Debug/New3DS specific entries do exist even in Retail/Old3DS config files
(except, old firmware versions don't have New3DS entries, of course).
BlkID=000F0001h - System ?
000h 8 Unknown (0)
BlkID=000F0003h - System ?
000h 1 Unknown (0)
BlkID=00100003h - DSi ?
"TWL "movable" UID, used for DSiWare exports"
000h 10h Unknown (DD E8 51 xx xx xx xx xx xx xx xx xx xx xx xx xx)
First 3 bytes seem to be fixed, the other bytes are console unique ID or Key.
Maybe some equivalent to DSi's HWINFO_N values? Maybe derived from 3DS OTP?
BlkID=00150000h - ?
000h 4 Unknown (24F0h or 9D0h) (aka 9456 and 2512)
BlkID=00150001h - ?
000h 8 Unknown (0)
NDS/DSi Mode
The Favorite color and User message for NDS/DSi titles can be changed in 3DS
System Settings, however, those two settings are only stored in NDS User
Settings (in Wifi FLASH), not in the config file.
3ds:\title\0004000e Patches/Updates?
Whatever, patches/updates for titles in 3ds:\title\00040000 or so?
3ds:\data\<ID0>\extdata\00048000:
e0000000 System transfer (request transfer if file is present)
f0000001 Camera application NAND JPEG/MPO files, phtcache.bin, UploadData.dat
f0000002 Sound application NAND M4A files
f0000009 SpotPass content storage for notifications
f000000b Miis and Play/Usage Records
f000000c Contains bashotorya.dat and bashotorya2.dat
f000000d Home Menu SpotPass content data storage
f000000e Update notification versionlist.dat (added in 7.0.0-13)
3ds:\data\<ID0>\sysdata:
System Module Savegames (0001xxxx)...
0001000f reportedly SEEDDB or so
00010011 FS module savedata ;used for Anti Savegame Restore
00010015 AM module savedata
00010017 Config savegame ;aka System Settings (user name, etc.)
00010022 PTM savegame
00010026 CECD savegame
0001002c NIM savegame
00010032 Friends module savegame
00010034 BOSS module savegame
00010035 News module savegame
00010038 Act module savegame
00010040 NFC module savegame
System application and applet savegames (0002xxxx)...
00020082 Home Menu savegame JPN
0002008f Home Menu savegame USA
00020098 Home Menu savegame EUR
00020086 Instruction Manual applet savegame JPN
00020092 Instruction Manual applet savegame USA
0002009b Instruction Manual applet savegame EUR
00020087 Game Notes applet savegame JPN
00020093 Game Notes applet savegame USA
0002009c Game Notes applet savegame EUR
00020088 Old3DS/New3DS Internet Browser savegame JPN
00020094 Old3DS/New3DS Internet Browser savegame USA
0002009d Old3DS/New3DS Internet Browser savegame EUR
0002008d Friend List applet savegame JPN
00020096 Friend List applet savegame USA
0002009f Friend List applet savegame EUR
000200bb Additional savedata t.bin history for the New3DS Browser (ALL)
000200bc olv applet savegame, Miiverse JPN
000200bd olv applet savegame, Miiverse USA
000200be olv applet savegame, Miiverse EUR
000200c5 error applet savegame (ALL)
000200c6 mint applet savegame (ALL)
00020200 System Settings savegame JPN ;\whatever, contains Mset.data
00020210 System Settings savegame USA ; and MsetForBoss.dat
00020220 System Settings savegame EUR ;/
00020202 Activity Log application savegame JPN
00020212 Activity Log application savegame USA
00020222 Activity Log application savegame EUR
00020204 Nintendo 3DS Camera application savegame JPN
00020214 Nintendo 3DS Camera application savegame USA
00020224 Nintendo 3DS Camera application savegame EUR
00020205 Nintendo 3DS Sound application savegame JPN
00020215 Nintendo 3DS Sound application savegame USA
00020225 Nintendo 3DS Sound application savegame EUR
00020207 Mii Maker application savegame JPN
00020217 Mii Maker application savegame USA
00020227 Mii Maker application savegame EUR
00020208 StreetPass Mii Plaza application savegame JPN
00020218 StreetPass Mii Plaza application savegame USA
00020228 StreetPass Mii Plaza application savegame EUR
00020209 eShop application savegame JPN
00020219 eShop application savegame USA
00020229 eShop application savegame EUR
0002020a System Transfer savegame JPN
0002021a System Transfer savegame USA
0002022a System Transfer savegame EUR
0002020b Nintendo Zone savegame JPN
0002021b Nintendo Zone savegame USA
0002022b Nintendo Zone savegame EUR
0002020d Face Raiders savegame JPN
0002021d Face Raiders savegame USA
0002022d Face Raiders savegame EUR
0002020e AR Games savegame JPN
0002021e AR Games savegame USA
0002022e AR Games savegame EUR
000202bf act (NNID settings) application savegame JPN
000202c0 act (NNID settings) application savegame USA
000202c1 act (NNID settings) application savegame EUR
00020231 microSD Management application savegame JPN
00020241 microSD Management application savegame USA
00020251 microSD Management application savegame EUR
key.bin
Unknown purpose, used when launching applications, contains several entries
with flags and 20bit title IDs for Ridge Racer and Zelda Ocarina of Time (for
several regions each).
000h N*4 Entries (00Xttttth)
Original filesize was 12 bytes, changed to 48 bytes in v6.0.0, and changed to
32 bytes in later New3DS versions (and also changed the flag bits in bit20-23).
The separate entries are:
12-byte 48-byte 32-byte ;Title
- 00000000h - ;Garbage?
- 00400000h - ;Garbage?
- 00800000h - ;Garbage?
- 00800000h - ;Garbage?
00200328h 00E00328h 00200328h ;Ridge Racer 3D (JPN)
- 00000334h 00400334h ;Zelda Ocarina of Time 3D (JPN)
- 00000335h 00400335h ;Zelda Ocarina of Time 3D (USA)
- 00000336h 00400336h ;Zelda Ocarina of Time 3D (EUR)
0020033Bh 00E0033Bh 0020033Bh ;Ridge Racer 3D (EUR)
00200358h 00E00358h 00200358h ;Ridge Racer 3D (USA)
- 000008F8h 004008F8h ;Zelda Ocarina of Time 3D (KOR)
- 000008F9h 004008F9h ;Zelda Ocarina of Time 3D (CHN)
value.bin
000h N*8 Entries (00000000xxxxxxxxh)
Original filesize was 8 bytes, changed to 32 bytes in v6.0.0, and changed to 16
bytes in later New3DS versions.
8-bytes on Old3DS:
000h 8 Unknown, 0000000047E00001h
32-bytes on Old3DS:
000h 8 Unknown, 0000000000000002h
008h 8 Unknown, 00000000002001CAh
010h 8 Unknown, 0000000000000000h
018h 8 Unknown, 0000000047E00001h
16-bytes on New3DS:
000h 8 Unknown, 0000000047E00001h
008h 8 Unknown, 0000000000000002h
This is used when launching applications.
"This page describes the format and encryption of extdata, "extra data" stored
on SD card and NAND, at":
3ds:\data\<ID0>\extdata\00048000\
sd:\Nintendo 3DS\<ID0>\<ID1>\extdata\00000000\
"Extdata ID High is always 00000000 for SD, and always 00048000 for eMMC.
Regular apps can only mount SD extdata using the same Extdata ID which is
stored in the CXI exheader. Therefore, regular apps which have the exheader
Extdata ID set to zero can't use extdata. This restriction doesn't apply for
shared extdata with Extdata ID high "bitmask"(=?) 48000h stored on NAND. System
apps with a certain(=?) access right can mount arbitrary extdata. All NAND
extdata is shared extdata, while all SD extdata is normal extdata."
User extdata and SpotPass extdata use separate mount points at /user and /boss.
Therefore one mount can't access the other virtual directory, and also can't
access /icon (the title's SpotPass extdata can be mounted by the title itself,
if it uses SpotPass).
SD Extdata ID's
JPN USA EUR Description Extdata images
00000082 0000008f 00000098 Home Menu extdata, this contains home-menu
savedata and cached icons for applications.
00000200 00000210 00000220 System Settings extdata added with 2.0.0-2.
00000207 00000217 00000227 Mii Maker, contains an ExBanner cleartext
00000208 00000218 00000228 Streetpass Mii Plaza 11 mb big!
00000209 00000219 00000229 eShop, contains store music in AAC format.
0000020b 0000021b 0000022b Nintendo Zone
0000020d 0000021d 0000022d Face Raiders, likely contains an ExBanner
000002cc 000002cd 000002ce Home Menu theme
? 000004aa 000004ab Nintendo Video Extra Data
This is where the video files are stored, and includes the thumbnail, the
description, and possibly some checksum info in each video file stored in the
extdata images. There are always 9 files within the subdirectory "00000000" of
this folder, even without any videos downloaded. The files are "00000001" -
"00000009", and "00000003" - "00000008" have the same filesize of 50.7 MB. It
is possible to restore the older videos by overwriting all the files within
this directory. Provided of course you have made a backup of the files before
hand, by copying all the files within this directory to your computer. As far
I'm aware its not possible to mix and match the files in order to get certain
videos in one grouping, ie. having all 3 Zelda orchestral recordings in one
group of 4 Nintendo videos.
00000306 00000308 00000307 Mario Kart 7
0000030b 0000030d 0000030c Nintendogs + Cats
00000326 00000326 00000326 Pok�dex 3D
00000305 0000032d 0000033c Super Street Fighter IV 3D
00000328 00000358 0000033b Ridge Racer 3D
? 0000034d 00000402 Samurai Warriors Chronicles
? 0000034f 0000038a Dead or Alive Dimensions
00000481 N/A N/A Monster Hunter Tri G (Download-Quests)
? 00000517 00000518 Swapnote
0000055d 0000055d 0000055d P-Letter X, P-Letter Y
? 00000725 00000724 Ambassador Certificate
? ? 000007af New Super Mario Bros. 2
? 00000863 00000864 Animal Crossing: New Leaf
? 00000a85 00000a86 Professor Layton and the Miracle Mask
? ? 00000a87 Professor Layton and the Azran Legacy (German)
? ? 00000b4f Fullblox / Crashmo
? ? 00000ba9 Pok�mon Mystery Dungeon: Gates to Infinity
? ? 00000c24 Denpa men
00000c73 00000c73 00000c73 Save Data Transfer Tool
? ? 00000d9a Donkey Kong Country Returns 3D: Trailer
? ? 00000ea6 Etrian Odyssey IV
? 00000edf 00000ee0 Super Smash Bros. for Nintendo 3DS
? 00000f14 00000f1e Phoenix Wright: Ace Attorney - Dual Destinies
? 00001007 00001005 Professor Layton vs Phoenix Wright: Ace Attorney
? ? 00001062 Nintendo Pocket Football Club
? ? 0000111c Yoshi's New Island
? ? 00001131 Fantasy Life
000011c5 000011c5 000011c5 Pok�mon Omega Ruby, Pok�mon Alpha Sapphire
? ? 000012ca Mario vs. Donkey Kong: Tipping Stars
? ? 00001499 Korg DSN-12
? ? 000014f2 Animal Crossing: Happy Home Designer
000014d1 000014d1 000014d1 Home Menu badge
? ? 00001632 Fullblox / Stretchmo
? ? 00001646 Pok�mon Rumble World
00001648 00001648 00001648 Pok�mon Sun, Pok�mon Moon
0000165c 0000165c 0000165c Home Menu saved theme layouts
? ? 00001678 Yo-kai Watch
? ? 000018fa Phoenix Wright: Ace Attorney - Spirit of Justice
? ? 0000198f Animal Crossing: New Leaf - Welcome amiibo
? ? 00001a05 Super Mario Maker
? ? 00001a2e Swapdoodle
Tools
3ds-save-tool - Extract/verifies extdata
SAVE/BDRI/VSXE Header
000h 4 ID "SAVE",00h,00h,04h,00h ;for savegame (file names + data clusters)
ID "BDRI",00h,00h,03h,00h ;for database (file IDs + data clusters)
ID "VSXE",00h,00h,03h,00h ;for extdata (file names + data IDs)
008h 8 File System Information offset (SAVE/BDRI=20h or VSXE=138h)
010h 8 Image size in blocks (eg. 1Eh)
018h 4 Image block size (usually 1000h) (or 80h or 200h, in databases)
01Ch 4 Padding
Extra entries, for VSXE (extdata) only:
020h 8 Unknown (can be 1) (1)
028h 4 Most recently mounted Extdata image 'Action' ;whut? (0)
02Ch 4 Unknown (0)
030h 4 Most recently mounted Extdata image FAT file (eg. 3="00000003")
034h 4 Unknown (0)
038h 100h Most recently mounted Extdata image VSXE name (eg. "/user/file",0)
Note: The Quota.dat file does also seem to log some "most recent" stuff.
Directory Table
Entry #0 Dummy Entry (aka entrypoint for unused (deleted?) entries)
Entry #1 Root Directory (aka entrypoint for used entries)
Entry #2..X Sub-directories (used and deleted entries?)
Entry #Y..Z Sub-directories (still unused entries?) (zerofilled)
Directory Entries:
SAVE VSXE BDRI Siz Content
000h 000h 000h 4 Directory Index of Parent directory (0=none; in root)
004h 004h - 16 Directory Name in ASCII, zeropadded (all zero for root)
014h 014h 004h 4 Directory Index of next sibling directory (0=none)
018h 018h 008h 4 Directory Index of first subdirectory (0=none)
01Ch 01Ch 00Ch 4 File index of first file in this directory (0=none)
020h 020h 010h .. Padding (0) / zero?
024h 024h 01Ch 4 Directory Index of next same hash table bucket (0=none)
Dummy Directory entries:
SAVE VSXE BDRI Siz Content
000h 000h 000h 4 Current Total entry count (eg. 2 = Dummy+Root)
004h 004h 004h 4 Maximum entry count = maximum directory count + 2
008h 008h 008h .. Padding / All zero
024h 024h 01Ch 4 Directory Index of next dummy (=deleted?) entry (0=none)
Dummy entries are left there when deleting directories, and reserved for future
use.
File Table
Entry #0 Dummy Entry
Entry #1..X File Entries (used and deleted entries?)
Entry #Y..Z File Entries (still unused entries?) (zerofilled)
The file entry table is an array of the entry type shown below. It contains
information for each file.
SAVE VSXE BDRI Siz Content
000h 000h 000h 4 Directory index of Parent Directory
004h 004h - 16 File Name in ASCII, zeropadded
- - 004h 8 Title ID
014h 014h 00Ch 4 File index of next sibling file (0=none)
018h 018h 010h 4 Padding
01Ch - 014h 4 First cluster-1 (0..N-1 = Cluster 1..N, or 80000000h=None)
020h - 018h 8 File Size
- - 020h 4 Padding?
- 01Ch - 4 Always 80000000h (extdata has no clusters)
- 020h - 8 Unique identifier. See Extdata
028h 028h 024h 4 Padding?
02Ch 02Ch 028h 4 File Index of next file in same hash table bucket (0=none)
Dummy File entries:
SAVE VSXE BDRI Siz Content
000h 000h 000h 4 Current total entry count (eg. 2=Dummy+OneFile)
004h 004h 004h 4 Maximum File entry count = maximum file count + 1
008h 008h 008h .. Padding (0)
02Ch 02Ch 028h 4 File Index of the next dummy (=deleted?) entry (0=last)
Dummy entries are left there when deleting files, and reserved for future use.
Initialization
When a save FLASH contains all xFFFF blocks it's assumed uninitialized by the
game cartridges and it initializes default data in place, without prompting the
user. The FFFFFFFFh blocks are uninitialized data. When creating a non-gamecard
savegame and other images/files, it's initially all FFFFFFFFh until it's
formatted where some of the blocks are overwritten with encrypted data.
Tools
3dsfuse supports reading and modifying savegames. In the mounted FUSE
filesystem, the /output.sav is the raw FLASH save-image. When the save was
modified, a separate tool to update the CMAC must be used with /clean.sav,
prior to writing output.sav to a gamecard.
3DSExplorer supports reading of savegames, it doesn't support reading the new
encrypted savegames and maybe in the future it will support modifying (some of
the modyfing code is already implemented).
wwylele's 3ds-save-tool supports extracting files from savegames and extdata.
It properly reconstructs data from the DPFS tree and extracts files in
directories hierarchy.
3dsfuse-ex similar to 3dsfuse, but supports savegame inner FS, proper DPFS
handling, and automatic CMAC update. Still WIP.
DISA and DIFF are two container formats (usually containing SAVE/BDRI/VSXE
filesystems, or raw data in some cases).
The DISA/DIFF containers are storing everything in data pairs that consist of
active/inactive halves (somewhat maintaining a backup copy in the active half,
whilst allowing to write new data to the inactive half). Additionally, there
are SHA256's for all data blocks (for error checking, and for preventing
hacks/patches when not having the AES-CMAC key for the master checksum).
Format
A DISA / DIFF file consists of the following components:
0000h 200h Header (DISA or DIFF)
0200h 130h 1st DIFI+IVFC+DPFS+SHA256 for Partition A
(and somewhere DIFI+IVFC+DPFS+SHA256 for Partition B, if any?)
0330h 130h 2nd DIFI+IVFC+DPFS+SHA256 for Partition A (as above)
1000h ... Partition A
xxxxh ... Partition B (optional, can only exist for DISA, not for DIFF).
Encryption
DISA and DIFF formats don't have their own encryption specification. They
follow the encryption method defined by their media:
- Gamecard savegames have special wear leveling + encryption layers.
- Files on SD follow the general SD filesystem encryption rule.
- Files on NAND are in cleartext, after decrypting the NAND partition.
DISA header (used for Savegame and System savedata)
DIFF header (for Extdata and Title Database)
All offsets in the header are relative to the beginning of the DISA/DIFF file,
except for partition descriptor offsets, which are relative to the beginning of
the (active) partition table.
DISA DIFF Siz Content
000h 000h 10h AES-CMAC on SHA256 on special ID-strings-and-Header[100h..1FFh]
010h 010h F0h Padding (0)
100h 100h 8 ID ("DISA",00h,00h,04h,00h or "DIFF",00h,00h,03h,00h)
108h - 4 Partition count, 1 or 2 (aka "1=A" or "2=A+B") (1)
10Ch - 4 Padding
110h 108h 8 1st DIFI offset ;\the active one is selected (200h)
118h 110h 8 2nd DIFI offset ;/via below Active flag) (330h)
120h 118h 8 DIFI+IVFC+DPFS+SHA256 table size (12Ch) (or 12Ch*2 when two?)
128h - 8 Partition A DIFI+IVFC+DPFS+SHA256 offset in active DIFI (0)
130h - 8 Partition A DIFI+IVFC+DPFS+SHA256 size (12Ch)
138h - 8 Partition B DIFI+IVFC+DPFS+SHA256 offset in active DIFI (0) ;?
140h - 8 Partition B DIFI+IVFC+DPFS+SHA256 size (0) ;12Ch?
148h 120h 8 Partition A offset (DPFS flags, IVFC SHA's, ... (1000h)
150h 128h 8 Partition A size (3F000h)
158h - 8 Partition B offset (0)
160h - 8 Partition B size (0)
168h 130h 4 Active DIFI+IVFC+DPFS+SHA256 flag (0=2nd DIFI, 1=First DIFI)
16Ch 134h 20h Active DIFI+IVFC+DPFS+SHA256 table SHA256
- 154h 8 Unique identifier for Extdata (zero for title database)
18Ch 15Ch .. Unused (up to 1FFh), might contain leftover data
When the partition count is 1, there is no partition B and all of its related
fields are zero.
DIFI table
All offsets are relative to the beginning of the DIFI partition descriptor,
except for External IVFC level 7 offset, which is relative to the beginning of
the partition.
000h 8 ID "DIFI",00h,00h,01h,00h
008h 8 IVFC descriptor offset (44h) ;\checksum tree SHA256's ;"IVFC"
010h 8 IVFC descriptor size (78h) ;/
018h 8 DPFS descriptor offset (BCh) ;\active/inactive data pair flags
020h 8 DPFS descriptor size (50h) ;/
028h 8 SHA256 Partition hash offset (10Ch) ;\aka "Partition master hash"?
030h 8 SHA256 Partition hash size (20h*N) ;/
038h 1 IVFC level 7 location (0=Internal, Nonzero=External) (usually 0)
039h 1 Active flag for DPFS Level 1 (0=1st half, 1=2nd half)
03Ah 2 Padding (0)
03Ch 8 External IVFC level 7 offset (zero if Internal IVFC level 7)
044h 78h IVFC descriptor (see below)
0BCh 50h DPFS descriptor (see below)
10Ch 20h*N SHA256 Partition master hash list (SHA's for Level 4)
(then followed by another DIFI+IVFC+DPFS+SHA256 for partition B, if any?)
Note: There are two DIFI tables (the active one being selected in
DISA[168h]/DIFF[130h]). Both DIFI's are usually containing the exact same
offsets and sizes (and do differ only by Flag in DIFI[039h] and the SHA's at
DIFI[10Ch]) (however, the inactive DIFI may initially contain unformatted
garbage).
DPFS descriptor
This header defines each level of DPFS tree. All offsets are relative to the
beginning of the partition.
000h 8 ID "DPFS",00h,00h,01h,00h
008h 8 Level 1 offset (usually 0) ;\Flags for
010h 8 Level 1 size per half (usually 4, or N*4 if bigger) ; Level 2
018h 8 Level 1 block size (unused, usually 0) ;/
020h 8 Level 2 offset (usually N*4*2, at level 1 end) ;\Flags for
028h 8 Level 2 size per half (usually 80h*N) ; Level 3
030h 8 Level 2 block size (1 SHL N, usually 7=80h bytes) ;/
038h 8 Level 3 offset (usually 1000h-aligned) ;\IVFC's
040h 8 Level 3 size per half (usually 1000h*N) ; (SHA's+Data)
048h 8 Level 3 block size (1 SHL N, usually 12=1000h bytes) ;/
The flags are stored in 32bit snippets, weirdly with bit31 being the 1st block
(that can be resolved as "BitNumber=BlockNumber XOR 1Fh"). The flags are
selecting the active half of the next level (0=1st Half, or 1=2nd Half).
The above DPFS "size" values refer to "one half" (the 1st half is at "offset",
the 2nd half is at "offset+size").
--> 3DS Files - Savedata DISA and DIFF - Data Pairs
IVFC descriptor
This header defines each level of IVFC tree. All offsets are relative to
the beginning of the active half of DPFS level 3.
000h 8 ID "IVFC",00h,00h,02h,00h
008h 8 Master hash size = partition master hash size in DIFI header (N*20h)
010h 8 Level 4 offset (usually 0) ;\SHA's for
018h 8 Level 4 size (usually 20h, or N*20h if bigger) ; Level 5
020h 8 Level 4 block size (1 SHL N, usually 9=200h bytes) ;/
028h 8 Level 5 offset (usually 20h, aka level 1 end) ;\SHA's for
030h 8 Level 5 size (usually 20h, or N*20h if bigger) ; Level 6
038h 8 Level 5 block size (1 SHL N, usually 9=200h bytes) ;/
040h 8 Level 6 offset (usually 40h, aka level 2 end) ;\SHA's for
048h 8 Level 6 size (usually 20h*N) ; Data
050h 8 Level 6 block size (1 SHL N, usually 12=1000h bytes) ;/
058h 8 Level 7 offset (unused for External IVFC Level 7) ;\Data (eg.
060h 8 Level 7 size (usually 1000h*N) ; SAVE filesys)
068h 8 Level 7 block size (1 SHL N, usually 12=1000h bytes) ;/
070h 8 IVFC descriptor size? (usually 78h)
The above IVFC "size" values refer to "one half" (the 1st half is at "offset",
the 2nd half is at "offset+level3size").
--> 3DS Files - Savedata DISA and DIFF - Checksums
Partition
A partition can have two types of layout. This is determined by the field
DIFI+38h (Enable external IVFC level 7).
The layout type 0 (external IVFC level 7 disabled) contains
DPFS Level 1 (contains active flags for DPFS level 2)
DPFS Level 2 (contains active flags for DPFS level 3)
DPFS Level 3 (contains IVFC levels and Data?)
IVFC Level 4 (contains SHA256's for IVFC level 5)
IVFC Level 5 (contains SHA256's for IVFC level 6)
IVFC Level 6 (contains SHA256's for IVFC level 7)
IVFC Level 7 (contains the actual content data)
The layout type 1 (external IVFC level 4 enabled) contains
DPFS Level 1 ;Flags for DPFS Level 2
DPFS Level 2 ;Flags for DPFS Level 3
DPFS Level 3, and inside
IVFC Level 4 ;SHA256's on IVFC Level 5
IVFC Level 5 ;SHA256's on IVFC Level 6
IVFC Level 6 ;SHA256's on IVFC Level 7
IVFC Level 7 ;the actual content data, note that this is outside DPFS level 3
Summary diagram
external link: https://i.imgur.com/BjwShJZ.png
Please move this into 3dbrew when file uploading is fixed.
AES CMAC
The AES CMAC is located at the beginning of the DISA / DIFF image, and it is
10h long. The rest F0h bytes before the header are unused.
The key used for the AES CMAC is generated by the hardware key engine.
The data being authenticated by the AES CMAC is a 20h-byte SHA-256 hash of a
data block.
CTR-NOR0 This CMAC type is used for gamecard savegames, 28h-bytes
000h 8 ID "CTR-NOR0" ;\CMAC area
008h 20h SHA-256 of the following 108h-byte block ;/
028h 8 ID "CTR-SAV0"
030h 100h Copy of the DISA header
CTR-SIGN This CMAC type is used for SD savegames, 30h-bytes
000h 8 ID "CTR-SIGN" ;\
008h 8 Title ID ; CMAC area
010h 20h SHA-256 of the following 108h-byte block ;/
030h 8 ID "CTR-SAV0"
038h 100h Copy of the DISA header
CTR-SYS0 This CMAC type is used for NAND system save, 110h-bytes
000h 8 ID "CTR-SYS0"
008h 8 Save ID. The higher word is always zero
010h 100h Copy of the DISA header
CTR-EXT0 This CMAC type is used for extdata, 11Ch-bytes
000h 8 ID "CTR-EXT0"
008h 8 Extdata ID eg. "00048000\x00000xx\" ?
010h 4 0 for Quota.dat, 1 otherwise
014h 4 ID in the "device" file name "\00000000\nnnnnnnn" ? ;\zero for
018h 4 ID in the "device" directory name that the file is in ;/Quota.dat
01Ch 100h Copy of the DIFF header
CTR-9DB0 This CMAC type is used for title database, 10Ch-bytes
000h 8 ID "CTR-9DB0"
008h 4 Database .db file ID (0..5, see below)
00Ch 100h Copy of the DIFF header
The Database .db file IDs are:
0=ticket.db, 1=certs.db, 2=title.db, 3=import.db, 4=tmp_t.db, 5=tmp_i.db
Here is a summary table of the CMAC type and the AES key slot used:
Usage Media Format CMAC type CMAC Keyslot
Savegames Gamecard DISA CTR-NOR0 19h/33h
Savegames SD DISA CTR-SIGN 30h
System SaveData NAND DISA CTR-SYS0 30h
Private Extdata SD DIFF CTR-EXT0 30h
Shared Extdata NAND DIFF CTR-EXT0 30h
Title Database SD DIFF CTR-9DB0 30h
Title Database NAND DIFF CTR-9DB0 0Bh
Note: The AES keyslots are known (shown above), but the AES IV appears to be
unknown?
IVFC tree
The IVFC tree is used for data verification. It is very similar to the IVFC
tree in RomFS, except that it has an additional level here. For level 4, 5 and
6, each level is a list of SHA-256 hash, of which each corresponds to a block
of the next level which is zero-padded to align the block size (the block size
of the next level is defined in the IVFC descriptor).
The partition master hash in the partition descriptor can be seen as IVFC level
0, which hashes level 4 following the same rule. The master hash is usually 20h
long, consisting only one hash. This is because most DISA / DIFF files are not
large enough to have multiple hashes on the top level, which isn't the case for
some title database files.
However, not all data is hashed - only ranges that have been written with valid
data are properly hashed.
Level 7 is the actual content of the partition, which is what the container
format essentially contains.
Unlike SD and NAND savegames, Gamecard savegames have and additional Encryption
and Wear Leveling layer.
The reason this works is because the stream cipher used has a period of 512
bytes. That is to say, it will repeat the same keystream after 512 bytes. The
way you encrypt with a stream cipher is you XOR your data with the keystream as
it is produced. Unfortunately, if your streamcipher repeats and you are
encrypting a known plain-text (in our case, zeros) you are basically giving
away your valuable keystream.
Savegame keyY
All gamecard and (!!?!!) SD savegames are encrypted with AES-CTR. The base CTR
for gamecard savegames is all-zero. The gamecard savegame keyslots' keyY (these
savegame keyslots use the hardware key-generator) is unique for each region and
for each game. The NCSD partition flags determine the method used to generate
this keyY. When the save NCSD flags checked by the running NATIVE_FIRM are
all-zero, the system will use the repeating CTR, otherwise a proper CTR which
never repeats within the image is used.
When all of the flags checked by the running NATIVE_FIRM are clear, the keyY
(original keyY method used with saves where the CTR repeats within the image)
is the following:
00h 8 First 8-bytes from the plaintext CXI accessdesc signature.
08h 4 u32 CardID0 from gamecard plaintext-mode command 0x90,
Process9 reads this with the NTRCARD hw. The actual cmdID used
by Process9 is different since Process9 reads it with the
gamecard in encrypted-mode.
0Ch 4 u32 CardID1 from gamecard plaintext-mode command 0xA0,
Process9 reads this with the NTRCARD hw. The actual cmdID used
by Process9 is different since Process9 reads it with the
gamecard in encrypted-mode.
This keyY generation method was implemented with 2.0.0-2 via NCSD partition
flag[3], however the proper CTR wasn't implemented for flag[7] until 2.2.0-4.
The hashed keyY flag[3] implemented with 2.0.0-2 was likely never used with
retail gamecards.
The keyY used for calculating this AES-CMAC is initialized while NATIVE_FIRM is
loading, this keyY is generated via the RSA engine. The RSA slot used here is
slot0 (key-data for slot0 is initialized by bootrom), this RSA slot0 key-data
is overwritten during system boot. This RSA slot0 key-data gets overwritten
with the RSA key-data used for verifying RSA signatures, every time Process9
verifies any RSA signatures except for NCCH accessdesc signatures. Starting
with 7.0.0-13 this key-init function used at boot is also used to initialize a
separate keyslot used for the new NCCH encryption method.
The 3DS employs a wear leveling scheme on the savegame FLASH chips (only used
for CARD1 gamecards). This is done through the usage of blockmaps and a
journal. The blockmap is located at offset 0 of the flash chip, and is
immediately followed by the journal. The initial state is dictated by the
blockmap, and the journal is then applied to that.
First, there are 8 bytes whose purposes are currently unknown. Then comes the
actual blockmap. The blockmap structure is simple:
struct header_entry {
uint8_t phys_sec ;when bit7=1: block has chksums (else chksums are all 0)
uint8_t alloc_cnt
uint8_t chksums[8]
} __attribute__((__packed__));
There's one entry per sector, counting from physical sector 1 (sector 0
contains the blockmap/journal).
The 2 bytes that follow the blockmap are the CRC16 (with initial value FFFFh)
of the first 8 bytes and the blockmap.
struct long_sector_entry{
struct sector_entry sector
struct sector_entry dupe
uint32_t magic ;With magic being a constant 080D6CE0h.
}__attribute__((__packed__));
Message files contain text messages, usually there are separate message files
for different languages (in separate folders).
<name>.msbt (MsgStdBn format) - Message Text
<name>.msbp (MsgPrnBn format) - Message Project/styles (if present)
RI.mstl (raw binary) - Unknown purpose
Hash Tables
Many items (such as messages in msbt files or colors in msbp files) are looked
up by label. The labels are looked up with a hash table and are stored in a
different block than the items themselves. In official files the hash table
always has a fixed number of slots (101 in msbt files, 29 in msbp files), even
if it contains only a few labels.
The following hash algorithm is used:
def calc_hash(label, num_slots):
hash = 0
for char in label:
hash = hash * 492h + ord(char)
return (hash AND 0FFFFFFFFh) MOD num_slots
The block with the labels contains the following data:
000h 4 Number of slots
004h 8*N Hash table slots
... .. Labels
Hash Table Slot
000h 4 Number of labels
004h 4 Offset to labels
Label
000h 1 Length of label string
001h .. Label string (without null terminator)
... 4 Item index
This page describes the format of the icon stored at CXI ExeFS:/icon and CIA
icons. The CXI icon is displayed by Home Menu and System Settings (3DS Software
Management), while CIA icons are dummies and not yet utilised by Dev 3DS' (as
of rev 47586).
Flags [2028h]
0 Visibility Flag (Required for visibility on the Home Menu) (1=show?)
1 Auto-boot this gamecard title
2 Allow use of 3D? (For use with parental Controls. An application
can use the 3D affect, even when this flag isn't set)
3 Require accepting CTR EULA before being launched by Home
4 Autosave on exit? (see below)
5 Uses an Extended Banner?
6 Region game rating required
7 Uses save data? (see below)
8 Application usage is to be recorded. If this is zero, it causes
the application's usage to be omitted from the Home Menu's icon
cache, as well as in other places.
9 unknown/unspecified
10 Disables SD Savedata Backups for this title. This is in addition to
the blacklist.
11 unknown/unspecified
12 New 3DS exclusive title. Shows an error if used on Old 3DS.
13-31 unknown/unspecified
Age Rating: Active ratings have a bitmask of 80h, and inactive ratings have no
bitmask at all. Ratings without the 80h bitmask are ignored. 40h bitmask
indicates Rating Pending. 20h bitmask indicates No Age Restriction. Age limits
are set by adding the minimal age to 80h (for example, limiting to 12 years and
up would give a bitmask of 8Ch)
Region Lockout: Regions are 'included' in region lock by setting their bitmask
value. Nintendo defines region free as 7FFFFFFFh. Early in the 3DS'
development, Nintendo grouped the Australian and Europe markets together.
Nintendo defines market Europe as having the combined bitmasks of Europe and
Australia. No 3DS' which check the Australia bitmask have been seen (Australia
uses the European 3DS model).
The EULA version is checked when the Accept EULA flag is set, the version is
compared to one stored in the 3DS. If the SMDH version is greater, then the
user will be prompted to accept the EULA.
CEC (StreetPass) ID
This u32 represents the application CEC ID. This is likely loaded by
applications for use with the CEC services as well.
Icon graphics
Both of the icons are encoded in RGB565 meaning 16bpp.
The data is encoded in tiles (starting from size 8x8, continuing recursively).
If the buffer is like this:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16
Then the image would look like this:
x=0 x=1 x=2 x=3 x=4
0 1 4 5 16
2 3 6 7 ...
8 9 12 13
10 11 14 15
Uh, are that pixels or 8x8pix tiles?
Either way, how would that translate to actual 24x24pix or 48x48pix icons??
Although both icons are known to be RGB565, developers have the option of
encoding icons (and banners) with the following encodings:
RGBA8
RGB8
RGBA5551
RGB565 (used)
RGBA4
LA8
HILO8
L8
A8
LA4
L4
ETC1
ETC1A4
This does not necessarily mean the other encodings will be used, it is just
that those are the options when compiling. Like we've seen with Super Mario 3D
Land Nintendo has changed save file encryption, and "likewise" they can encode
icons and banners differently should they choose to. Currently we've seen just
RGB565 so don't be fooled if an icon doesn't show up right! It is probably one
of these formats above. Although we will probably not see other formats used
for a while it's nice to know they have an opportunity to change.
Also note that it seems Nintendo stores "each pixel in word-order", so the
actual "order of order" of "each color channel" in memory will depend on the
endianness. uh, what?
Tools
CiTRUS - (GUI)(Windows Only) Generating ICN files (aka icon files)
3DSExplorer - (GUI)(Windows Only) Parsing ICN files (aka icon files)
CBMD Header
000h 4 ID "CBMD"
004h 4 Zero
008h 4 CGFX Offset for Default (88h) ;-main CGFX file (for all regions)
00Ch 4 CGFX Offset for EUR-English ;\
010h 4 CGFX Offset for EUR-French ; region-specific CGFX files
014h 4 CGFX Offset for EUR-German ; (or 0=None)
018h 4 CGFX Offset for EUR-Italian ; (these are smaller CGFX files,
01Ch 4 CGFX Offset for EUR-Spanish ; usually with one or two custom
020h 4 CGFX Offset for EUR-Dutch ; Textures) (3DS Activity Log has
024h 4 CGFX Offset for EUR-Portuguese ; more custom entries though)
028h 4 CGFX Offset for EUR-Russian ; (Nintendo Network ID Settings
02Ch 4 CGFX Offset for JPN-Japanese ; doesn't have any custom CGFX's)
030h 4 CGFX Offset for USA-English ;
034h 4 CGFX Offset for USA-French ; (unknown if CHN/KOR/TWN are
038h 4 CGFX Offset for USA-Spanish ; also supported?)
03Ch 4 CGFX Offset for USA-Portuguese ;/
040h 44h Padding (0) ;<-- XXX probably CHN/KOR/TWN here?
084h 4 CWAV Offset for Sound wave data
088h .. CFGX/CWAV data area...
"The common CGFX is used if the CGFX offset for the system region/language is
zero. Those optional offsets can be used in extdata exbanner, but separate CBMD
banner files for each region/language can be used as well."
Entry Size
The header contains only offsets. To compute the size, search the next bigger
offset (or use the filesize as max offset), and then subtract the current
offset from that value. Note: The list does usually contain increasing offsets
(but it may be a bad idea to rely on that, eg. EUR-Spanish and USA-Spanish
might use the same offsets).
CGFX Graphics
--> 3DS Files - Video Archive (CGFX)
Banner CGFX files are LZ11-compressed, the decompressed CGFX size shouldn't
exceed 80000h bytes for banners.
CWAV Sound
--> 3DS Files - Sound Wave Data (CWAV Format)
Banner CWAV total channels must be 2, and the length of the audio must be 3
seconds or less (uh, is that regardless of sample rate/sample size?), otherwise
the sound will play incorrectly (beeping/clicking) or the model may fail to
load.
Overview
The Extended Banner is used to add text (and optionally an extra texture) to a
given banner. It can also (optionally) be used to set an expiration date for a
banner.
See "\user\ExBanner\" for how the extended-banners are loaded from extdata. The
Home Menu extended-banner loading function will immediately return without
loading anything if the programID is for System Settings.
SpotPass
When Home Menu loads extended-banners, it also attempts to load a "CBMD" banner
via SpotPass service commands. Normally this CBMD banner doesn't exist in
extended-banner extdata. This is broken with New3DS titles since Home Menu uses
these BOSS commands with the New3DS bitmask in the programID set. The common
and language-specific (when offset is non-zero) "CGFX" specified by the CBMD
are decompressed and processed.
The "CGFX" sections in this CBMD are actually the exact same exbanners loaded
from normal extdata. The exbanner data from SpotPass is stored to the same
state as the extdata-exbanners. No CWAV is loaded from SpotPass data.
The exbanners from SpotPass must have a timestamp less than current_datetime,
otherwise they won't be parsed. The timestamp for the banner is calculated
with: nintimestamp_mktime(out, exbanner->year, exbanner->month, exbanner->day,
<hour=23>, <minute = 59>, <second = 59>, <millisecond = 999>);
CLYT (.bclyt) is the layout format used on the 3DS. It stands for (Binary) CTR
Layout, and is similar to the RLYT format used on the Wii.
FLYT is something similar (used in 3DS eShop applet RomFS:\layout\).
CLYT Header
000h 4 ID ("CLYT") ;or "FLYT"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (0014h)
008h 4 Version (02020000h)
00Ch 4 Total Filesize
010h 4 Number of following Chunks
lyt1 (Layout)
000h 4 Chunk ID "lyt1"
004h 4 Chunk Size
008h 4 Origin type (0=Classic, 1=Normal)
00Ch 8 Vector2 Canvas Size
mat1 (Materials)
000h 4 Chunk ID "mat1"
004h 4 Chunk Size
008h 4 Number of Materials (N)
00Ch N*4 Material Entry Offsets (relative to the start of this "section")
After this, the material entries follow.
00h 14h String Material Name
14h 4 RGBA8 Tev Color (Buffer Color?)
18h 18h RGBA8[6] Tev Constant Colors
30h 4 UInt32 Flags / bitfield
Bit Flag / data
0-1 Nr texMap
2-3 Nr texMatrix
4-5 Nr texCoordGen
6-8 Nr tevStage
9 Has alphaCompare
10 Has blendMode
11 Use Texture Only
12 Separate Blend Mode
14 Has Indirect Parameter
15-16 Nr projectionTexGenParameter
17 Has Font Shadow Parameter
Texture Map Entry:
00h 2 UInt16 Texture Index
02h 1 Byte Bitfield
Bit Data
0-1 Wrap S (0=Clamp, 1=Repeat, 2=Mirror)
2-3 Min Filter (0=Near, 1=Linear)
02h 1 Byte Bitfield ;<-- uh, maybe at offset 03h?
Bit Data
0-1 Wrap T (0=Clamp, 1=Repeat, 2=Mirror)
2-3 Mag Filter (0=Near, 1=Linear)
Texture Matrix Entry:
00h 8 Vector2 Translation
08h 4 Single Rotation
0Ch 8 Vector2 Scale
TODO: texCoordGen, tevStage, alphaCompare, blendMode, etc...
pan1 (Pane)
000h 4 Chunk ID "pan1"
004h 4 Chunk Size
008h 1 UInt8 Flags
Bit Flag
0 Visible
1 InfluencedAlpha
2 LocationAdjust
009h 1 UInt8 Origin
00Ah 1 UInt8 Alpha
00Bh 1 UInt8 Pane magnification flags
Bit Flag
0 IgnorePartsMagnify
1 AdjustToPartsBounds
00Ch 18h String Pane name
024h 0Ch Vector3 Translation
030h 0Ch Vector3 Rotation
03Ch 8 Vector2 Scale
048h 8 Vector2 Size
pic1 (Picture)
000h 4 Chunk ID "pic1"
004h 4 Chunk Size
008h 4 RGBA8 Top left vertex color
00Ch 4 RGBA8 Top right vertex color
010h 4 RGBA8 Bottom left vertex color
014h 4 RGBA8 Bottom right vertex color
018h 2 UInt16 Material ID
01Ah 2 UInt16 Nr texture coordinates = N
Texture coordinates entry
01Ch+N*20h 8 Vector2 Top left vertex texture coordinate
024h+N*20h 8 Vector2 Top right vertex texture coordinate
02Ch+N*20h 8 Vector2 Bottom left vertex texture coordinate
034h+N*20h 8 Vector2 Bottom right vertex texture coordinate
txt1 (Text)
wnd1 (Window)
...?
bnd1 (Bounding)
000h 4 Chunk ID "bnd1"
004h 4 Chunk Size
008h 2 UInt16? ?
00Ah 2 UInt16? ?
00Ch ? (0x10h up to 0x30h) String Bounding name
03Ch 8 Vector2 ?
044h 4 Vector2 ?
? ? ? ?
pts1 (Parts 1)
...?
grp1 (Group)
3 000h 4 Chunk ID "grp1"
004h 4 Chunk Size (1Ch+(0..N)*10h)
008h 10h String Group Name
018h 4 UInt32 Nr Pane References (=N) (can be zero)
01Ch 10h*N String[N] Pane References
Tools
Every File Explorer has limited support for viewing these
See also
http://florian.nouwt.com/wiki/index.php/CLYT_%28File_Format%29
https://github.com/Gericom/EveryFileExplorer/tree/master/3DS/NintendoWare/LYT1
3DS Files - Video Layout Animation (CLAN/FLAN)
----------------------------------------------
CLAN (.bclan) is the layout animation format used on the 3DS. It stands for
(Binary) CTR Layout Animation, and is similar to the RLAN format used on the
Wii.
FLAN is something similar, used in 3DS eShop applet (RomFS:\layout\) and 3DS
Browser applet (RomFS:\lyt\).
Header
00h 4 String ID ("CLAN") ;or "FLAN"
04h 2 UInt16 Byte Order (FEFFh)
06h 2 UInt16 Header Size (14h)
08h 4 UInt32 Revision
0Ch 4 UInt32 File Size
10h 4 UInt32 Nr Sections
pat1 (Pattern 1)
00h 4 String Signature (pat1)
04h 4 UInt32 Section Size
08h 4 UInt32 Flags?
0Ch 4 UInt32 ?
10h 4 Int32 ?
14h 4 UInt32 ?
18h 10h String Pattern name
See also
http://wiki.tockdom.com/wiki/BRLAN
http://wiibrew.org/wiki/Wii_Animations#Animations_.28.2A.brlan.29
Footer
00000000h .. Images...
Footer+00h 4 ID "CLIM" ;or "FLIM"
Footer+04h 2 Byte Order (FEFFh)
Footer+06h 2 Footer Size (14h)
Footer+08h 4 Version? (02020000h)
Footer+0Ch 4 Total Filesize
Footer+10h 4? Maybe number of images? (00000001h)
Footer+14h 4 Chunk ID "imag" ;\
Footer+18h 4 Chunk Size (10h) ; image data is at offset 0
Footer+1Ch 2 Width? ; (if multiple images should be allowed...
Footer+1Eh 2 Height? ; next image is at WHICH offset?)
Footer+20h 4? Type? (0Dh = 4bpp?) ;/ ;<-- ETC1A4 ?
Footer+24h 4 Footer Offset (from begin of file to "CLIM") ;<--at end of file
CGFX files exist as standalone files, and can be also found in CBMD banner
archives, usually with LZ11 compression.
CGFX is a container format used to store graphics resources.
CGFX Sections
--> 3DS Files - Video Archive (CGFX_00h - CMDL Models)
--> 3DS Files - Video Archive (CGFX_01h - TXOB Textures)
--> 3DS Files - Video Archive (CGFX_02h - LUTS Look-up Tables)
--> 3DS Files - Video Archive (CGFX_04h - SHDR Shaders)
--> 3DS Files - Video Archive (CGFX_05h - CCAM Cameras)
--> 3DS Files - Video Archive (CGFX_06h - CFLT/CHLT/CALT Lights)
--> 3DS Files - Video Archive (CGFX_08h - CENV Environments)
--> 3DS Files - Video Archive (CGFX_09h,0Ah,0Dh - CANM Animations)
--> 3DS Files - Video Archive (CGFX_0Eh,0Fh - PEMT Emitters/Particles)
Tools
Every File Explorer
Ohana3DS and its forks
SPICA
Links
Another CGFX Format Description (Archived Page):
http://florian.nouwt.com/wiki/index.php/CGFX_(File_Format)
https://web.archive.org/web/20150511211029/http://florian.nouwt.com
/wiki/index.php/CGFX_(File_Format)
CGFX Header
000h 4 ID "CGFX"
004h 2 Byte Order (FEFFh)
006h 2 CGFX header size (14h)
008h 4 Revision (can be 05000000h) (or 01000000h=Old, incompatible)
00Ch 4 Total Filesize (bytes)
010h 4 Number of blocks (usually 1=DATA, or 2=DATA+IMAG)
... .. DATA Block (DICT's, CMDL/TXOB/etc., and DICT Symbols)
... .. IMAG Block (optional, eg. for TXOB bitmaps)
The DATA block contains various small data structures. It's more or less
required to load the whole DATA block to memory when parsing those structs.
The IMAG block isn't required in memory (or, when needed, one may want to store
its content directly in VRAM).
Note on DICT names: There can be several root entries with same name (eg. 3DS
Download Play ExeFS:\banner has name "COMMON" used for CFGX_00h and CFGX_09h
and CFGX_0Ah root entries).
CMDL - 3D Model
000h 4 Flags (bit7: hasSkeletonSobj) (eg. 40000092h)
004h 4 ID "CMDL"
008h 4 Revision? (07000000h)
00Ch 4 Name Offset (self-relative, same name as in parent DICT)
010h 4 Unknown (0)
014h 4 Unknown (0)
018h 4 Unknown (1)
01Ch 4 Unknown (1)
020h 4 Unknown (0)
024h 4 Unknown (0)
028h 4+4 DICT for Animation Types (NumEntries, Offset)
030h 0Ch Scale (3 float32: x, y, z) ;-usually (1,1,1)
03Ch 0Ch Rotation (3 float32) ;-usually (0,0,0)
048h 0Ch Translation (3 float32) ;-usually (0,0,0)
054h 30h Local Matrix (4x3 float32) ;-usually unit matrix
084h 30h World Matrix (4x3 float32) ;-usually unit matrix
0B4h 4+4 Vertex Info SOBJ List (Meshes) (NumEntries, Offset)
0BCh 4+4 DICT for MTOB (Materials) (NumEntries, Offset)
0C4h 4+4 Vertex Info SOBJ List (Shapes) (NumEntries, Offset)
0CCh 4+4 DICT for Unknown (Mesh Nodes) (NumEntries, Offset)
0D4h 4 Unknown (1)
0D8h 4 Unknown (0)
0DCh 4 Unknown (0)
0E0h 4 Skeleton Info SOBJ offset (self-relative) (present if flag bit7=1)
A CMDL section refers to outside data; it can not be considered separately from
the rest of the CGFX file. The second DICT in the CMDL section contains offsets
to MTOB objects.
SOBJ
SOBJ structures can be used to describe 3D objects that are part of the model.
If such is the case then they will follow this structure:
000h 4 Flags (bit4: model, bit1: skeleton)
004h 4 ID "SOBJ"
008h 4 ?
00Ch 4 Unknown symbol offset (self-relative)
010h 0Ch ?
01Ch 4 Offset (self-relative) to Unknown1 (array of floats?)
020h 0Ch Mesh position vector (X/Y/Z floats)
02Ch 4+4 Face Group List (NumEntries, Offset) (list contains offsets)
034h 4 ?
038h 4+4 Vertex Group List (NumEntries, Offset) (list contains offsets)
040h 4 Unknown offset (self-relative) ?
Face groups:
000h 4+4 Bone Group ID List (NumEntries, Offset) (list contains 32bit IDs)
008h 4 ?
00Ch 4+4 Unknown2 List (NumEntries, Offset) (list contains offsets)
Unknown2:
000h 4+4 Face Group Descriptor List (NumEntries, Offset) (contains offsets)
008h 4+4 Unknown3 List (NumEntries, Offset) (contains 32bit's)
010h 8 ?
Vertex groups come in a number of different formats. Typically the first vertex
group entry is of format 40000002h and contains the actual vertex array.
LUTS is found in some CGFX files (eg. 3DS System Settings ExeFS:\banner).
CCAM Format
000h 4 Flags (eg. 4000000Ah)
004h 4 ID "CCAM"
008h 4 Revision (07000000h)
00Ch 4 Name Offset (self-relative) (same as in parent DICT)
010h 4+4 Unknown (0,0)
018h 4+4 Unknown (1,1)
020h 4+4 Unknown (0,0)
028h 4+4 DICT for Camera Animation (NumEntries,Offset)
030h 0Ch Vector? (3xFloat32) (1.0, 1.0, 1.0)
... .. More Vectors and/or Matrices ?
0BCh 4 Unknown (1D4h)
0C0h 4 Unknown (1E8h)
0C4h 4 Unknown (0)
CFLT (Directional/Fragment Lights) is found in some CGFX files, eg. 3DS System
Settings banner
CHLT (Hemisphere Lights) is less common, but found in StreetPass Mii Plaza
RomFS:\graphics\model\figure_Galaxy2.lz77 and figure_Link.lz77
CALT (Ambient? Lights) is even less common, found in StreetPass Mii Plaza
RomFS:\graphics\model\figure_Pikmin.lz77 and figure_Samus.lz77
CFLT Format
000h 4 Flags (eg. 400000A2h)
004h 4 ID "CFLT"
008h 4 Revision (06000000h)
00Ch 4 Name Offset (self-relative) (same as in parent DICT)
010h 4+4 Unknown (0,0)
018h 4+4 Unknown (1,1)
020h 4+4 Unknown (0,0)
028h 4+4 DICT for Light Animation (NumEntries,Offset)
030h 0Ch Vector? (3xFloat32) (1.0, 1.0, 1.0)
03Ch 0Ch Vector? (3xFloat32) (0.0, 0.0, 0.0)
048h 0Ch Vector? (3xFloat32) (0.0, 0.0, 0.0)
054h 30h Matrix? (4x3xFloat32) (Identity)
084h 30h Matrix? (4x3xFloat32) (Identity)
0B4h 4 Unknown (1)
0B8h 10h Unknown (zeroes)
0BCh 40h Float32's (all 1.0)
0FCh 10h Unknown (FF000000h, FFFFFFFFh, FFFFFFFFh, FFFFFFFFh)
10Ch 0Ch Vector? (3xFloat32?) (3F13CD3Ah, 3F13CD3Ah, BF13CD3Ah)
118h 0Ch Vector? (3xFloat32?) (00000000h, 00000000h, 00000000h)
124h 0Ch Vector? (3xFloat32?) (3F800000h, 0003F000h, 00080000h)
130h 4 Unknown (1)
Some of the Vectors might be X,Y,Z vectors. Some might be R,G,B colors?
CHLT Format
CALT Format
Unknown. Seems to be similar as CFLT (but, in case of CALT, with less Light
Animation DICT entries).
3DS Files - Video Archive (CGFX_08h - CENV Environments)
--------------------------------------------------------
CENV is found in some CGFX files, eg. 3DS System Settings ExeFS:\banner (with
Unknown2) or Mii Maker ExeFS:\banner (with Unknown1, Unknown2, Unknown3)
CENV Format
000h 4 Flags (eg. 00800000h)
004h 4 ID "CENV"
008h 4 Revision (01000000h)
00Ch 4 Name Offset (self-relative) (same as in parent DICT)
010h 4+4 Unknown0 (0,0)
018h 4+4 Unknown1 (0,0) (or 1,14h) ;(Num,Offset ?)
020h 4+4 Unknown2 (1,0Ch) (or 2,10h) ;(Num,Offset ?)
028h 4+4 Unknown3 (0,0) (or 1,10h) ;(Num,Offset ?)
... 4*n1 Offset List for Unknown1 ?
... 4*n2 Offset List for Unknown2 ?
... 4*n3 Offset List for Unknown3 ?
Entries for Unknown1 (if any):
000h 4 Unknown (0)
004h 4 Corresponding name? (eg. Offset to "FragmentOperation")
008h 4 Unknown (0)
00Ch 4 Unknown (0)
Entries for Unknown2:
000h 4 Unknown (1)
004h 4 Unknown (4)
008h 4 Unknown (4)
00Ch 4 Unknown (0)
010h 4 Corresponding Light name? (eg. Offset to Name "Light1")
014h 4 Unknown (0)
Entries for Unknown3 (if any):
... .. ?
All of those types do begin with ID "CANM", but unknown if they are actually
using the same data structure(s).
Variant without DICT and Flags=20000000h (despite same Flags can have DICT)
And Mii Maker also has some file with yet smaller DICT-less block, but with
20000000h (which usuallly DOES have DICT, but not in this case).
000h 4 Unknown (20000000h)
004h 4 Unknown (0) ;has only some floats, no DICT...
008h 18h Floats and/or whatever
020h 2 Uhm, bytes 00h, 01h? (then followed by Symbol table)
Some of the DICT-less variants seem to contain two bytes (rather than a whole
32bit word) in last entry? Usually that's padded to 32bit alignment, but not in
the last entry (which occurs right before the string table, which can start at
a non-aligned location).
DVLB Format (Vertex Shader Library) (can contain one or more shaders)
000h 4 ID "DVLB" (Vertex Shader Library)
004h 4 N = number of DVLEs in SHBIN
008h 4*N DVLE offset table (offsets to start of the DVLB(???) sections)
There is one DVLP block, containing the binary opcode/opdesc data for all
shaders (located right after the above header, ie. at offset 008h+4*N).
000h 4 ID "DVLP" (Vertex Shader Library Program Opcodes/Opdescs)
004h 2 Type/Version? (can be 0C02h)
006h 2 Unknown (can be 0000h)
008h 4 Opcode Table Offset (from DVLP start) (28h)
00Ch 4 Opcode Table Size (in 4-byte units)
010h 4 Opdesc Table Offset (from DVLP start)
014h 4 Opdesc Table Size (in 8-byte units)
018h 4 Line Number Table Offset ? (from DVLP start)
01Ch 4 Line Number Table Size ? (usually zero)
020h 4 Filename Symbol Table Offset (from DVLP start)
024h 4 Filename Symbol Table Size (in 1-byte units)
028h .. Data for above Opcodes, Opdescs, etc.
There can be one or more DVLE blocks, with information about entrypoint and
parameters for each shader (located at Header[008h+index*4]).
000h 4 ID "DVLE" (Vertex Shader Library Function Entrypoints/Params)
004h 2 Type/Version? (can be 0C02h)
006h 1 Shader type (0=Vertex shader, 1=Geometry shader, other=?)
008h 4 Opcode Entrypoint Address (in words, in memory) (main)
00Ch 4 Opcode End Address (in words, in memory) (endmain)
010h 4 Unknown (can be 001F0001h)
014h 4 Unknown (can be 00000000h)
018h 4 Constant Table Offset (relative to DVLE start) (eg. 40h)
01Ch 4 Constant Table Size (in 14h-byte units)
020h 4 Label Table Offset (relative to DVLE start)
024h 4 Label Table Size (in 10h-byte units)
028h 4 Output Register Table Offset (relative to DVLE start)
02Ch 4 Output Register Table Size (in 8-byte units)
030h 4 Input Register Table Offset (relative to DVLE start)
034h 4 Input Register Table Size (in 8-byte units)
038h 4 Symbol Table Offset (relative to DVLE start)
03Ch 4 Symbol Table Size (in 1-byte units)
040h .. Data for above Constants, Labels, etc.
Line Number Table (with 8-byte entries, one for each Opcode Table entry)
000h 4 Source Filename Offset (in Symbol Table) (eg. "font_XxxShader.vsh")
004h 4 Source Line number? (for the corresponding Opcode Table entry)
CFNT Header
000h 4 ID ("CFNT" or "CFNU" or "FFNT")
004h 2 Byte Order (FEFFh)
006h 2 Header Size
008h 4 Version (usually 03000000h) (also so for FFNT ?)
00Ch 4 File size (the total)
010h 4 Number of "blocks" to read
Tools
BFFNT Extractor/Creator. Creates PNG files from TGLP atlas data and a JSON
manifest.
CTPK archives can contain one or more texture files. The archive does usually
contain filenames with .tga extension (although the bitmaps are raw data,
unrelated to the Targa .tga format).
CTPK Header
000h 4 ID "CTPK" ;\
004h 2 Version (0001h) ;
006h 2 Number of Texture Info Entries ;
008h 4 Texture Data section offset (aka size of header+info) ; Header
00Ch 4 Texture Data section size ;
010h 4 Texture Filename CRC32 Table ;
014h 4 Conversion Info section offset ;
018h 8 Padding (0) ;/
020h N*20h Texture Info Entries ;\
... N*4 Texture Bitmap Sizes (same as [004h] in Info Entries?) ;
... N*var Texture Filename Strings (ASCII, terminated by 00h) ;
... .. Padding (0) (to 8-byte boundary) ; Info
... N*8 Texture Filename CRC32 Table ;
... N*4 Conversion Info Block Entries ;
... ... Padding (0) (to 80h-byte boundary) ;/
... N*var Texture Data section (raw bitmaps) ;-Data
Conversion Info Block Entries (unknown purpose, maybe info on source data?)
000h 1 Texture Format (usually 4,5,9,0Dh) (see below)
001h 1 Unknown (usually 1=what?)
002h 1 Compressed (usually 1=what?)
003h 1 ETC1 Related (Quality?) (usually 3 or 6=what?)
Texture Formats:
00h=RGBA8888
01h=RGB888
02h=RGBA5551
03h=RGB565
04h=RGBA4444
09h=?
0Ch=ETC1
0Dh=ETC1 + Alpha
BASE64 is used to encode binary data into 7bit ASCII characters (with 6 bits
per char, aka 3 bytes per 4 chars), eg. for binary attachments in email
messages. The 3DS uses BASE64 in .CSDR shader files, and in 3DS Browser applet
.PEM files.
IFD=1101h - Nintendo's 64-Byte Note (little endian, unlike the JPEG headers)
000h 4 ID ("3DS1")
004h 4 Unknown (can be 1, 2, 4, or 5)
008h 4 Timestamp (number of seconds since 1st Jan 2000)
00Ch 4 Padding (0)
010h 4 Title ID Low ("but without the last two letters" uh?)
014h 4 Flags
018h 4 Console ID (unique identifier, unknown where from...?)
01Ch 12 Padding (0)
028h 4 3D Parallax "[-52,54]" ;2x float16? or 1x float32 in range -52..+54?
02Ch 4 Padding (0)
030h 2 Gender Category??? (1000h=mii, 2000h=man, 4000h=woman)
032h 2 Filter (unknown meaning)
034h 12 Padding (0)
CSAR files are usually found in "RomFS:\sound\" folder, with extension ".bcsar"
(Binary CTR Sound Archive).
The CSAR archive contains CSEQ, CWSD, CBNK, CWAR files (and optionally CGRP).
Whereof, the CWAR file contains CWAV files.
CSAR Header
000h 4 ID "CSAR"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 40h)
008h 4 Version (usually 02000000h) (02030200h in Miiverse-posting)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 3 = STRG+INFO+FILE)
014h 4+4+4 STRG Block (RefID=2000h, Offset from CSAR+0, Size)
020h 4+4+4 INFO Block (RefID=2001h, Offset from CSAR+0, Size)
02Ch 4+4+4 FILE Block (RefID=2002h, Offset from CSAR+0, Size)
038h 8 Padding to 20h-byte boundary (0)
Resource IDs
The Resource IDs refer to entries in the INFO Block (the upper 8bit indicate a
List number, and lower 24bit contain the entry number in that list):
ID List File Types Common Name prefix
01xxxxxxh = Audio List (CSEQ, CWSD files) ;name SE,BGM
02xxxxxxh = Set List (folders for above Audio entries) ;name WSDSET,SEQSET
03xxxxxxh = Bank List (CBNK files) ;name BANK
04xxxxxxh = Player List (...whatever?) ;name PLAYER
05xxxxxxh = Wav Archive (CWAR files) <-- unless nameless ;name WARC ;or none
06xxxxxxh = Group List (CGRP files) <-- if any ;name GROUP
Groups exist only in some files. Wav Archives do exist in all files, but they
are often completely omitted in the string tree (or have only one of them
listed in the string tree).
CSEQ is usually found inside of CSAR (but can be also a standalone file, eg. in
3DS Camera Applet, RomFS:\sound\csnd.LZ).
CSEQ Header
000h 4 ID "CSEQ"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 40h)
008h 4 Version? (can be 01000000h)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 2 = DATA+LABL)
014h 4+4+4 DATA Block (RefID=5000h, Offset from CSEQ+0, Size)
020h 4+4+4 LABL Block (RefID=5001h, Offset from CSEQ+0, Size)
02Ch 14h Padding to 20h-byte boundary (0)
DATA Block
000h 4 ID "DATA"
004h 4 DATA Block Size (same as in CSEQ Header)
008h ... Data (addressed via Offsets in LABL block)
... .. Padding to 20h-byte boundary (0)
The content of the Data area is unknown, probably some midi-like notes?
LABL Block
000h 4 ID "LABL"
004h 4 LABL Block Size (same as in CSEQ Header)
008h 4 Number of following List entries (eg. 26h)
00Ch (4+4)*N List Entries (RefID=5100h, Offset from LABL+8)
... .. Padding to 20h-byte boundary (0)
List Entry Format:
000h (4+4)*N Data Entry (RefID=1F00h, Offset from DATA+8)
008h 4 String Length, excluding ending 00h
00Ch LEN+1 String (ASCII, plus ending 00h) (eg. "SMF_TWL_function_xxx")
... .. Padding to 4-byte boundary (0)
CWSD Header
000h 4 ID "CWSD"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 20h)
008h 4 Version? (can be 01000000h)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 1 = INFO)
014h 4+4+4 INFO Block (RefID=6800h, Offset from CWSD+0, Size)
INFO Block
000h 4 ID "INFO"
004h 4 INFO Block Size (same as in CWSD Header)
008h 4+4 ID List (RefID=0100h, Offset from INFO+8) ;Offs=10h
010h 4+4 Crazy List (RefID=0101h, Offset from INFO+8)
ID List: (uh, are these Resource ID's pointing to CSAR entries):
000h 4 Nummber of below 8-byte entries
004h (4+4)*N Resource ID and Index (ID=050000xxh, Index=0, 1, 2, etc.)
Crazy List:
000h 4 Nummber of below 8-byte entries
004h (4+4)*N Crazy Entry N (RefID=4900h, Offset from Crazy List+0)
Crazy Entry:
000h 4+4 Crazy Part1 (RefID=4901h, Offset from Crazy Entry+0)
008h 4+4 Crazy Part2 (RefID=0101h, Offset from Crazy Entry+0)
010h 4+4 Crazy Part3 (RefID=0101h, Offset from Crazy Entry+0)
Crazy Part1:
000h 4 Unknown (303h)
004h 4 Unknown (40h)
008h 4 Unknown (3F800000h, 3FE66666h, or 3F4CCCCDh) ;Int? Float?
00Ch 4 Unknown (14h)
010h 4 Unknown (1Ch)
014h 4 Unknown (27Fh)
018h 4 Unknown (0)
01Ch 4 Unknown (0)
020h 4 Unknown (08h)
024h 4 Unknown (7F7F7F7Fh)
028h 4 Unknown (7Fh)
Crazy Part2:
000h 4 Unknown (1) ;Num entries?
004h 4+4 Child Block (RefID=4903h, Offset from 000h+0) ;Offs=0Ch
00Ch 4 Unknown (0)
010h 4 Unknown (08h)
014h 4 Unknown (1) ;Num entries?
018h 4+4 Child Block (RefID=4904h, Offset from 014h+0) ;Offs=0Ch
020h 4 Unknown (0)
024h 4 Unknown (0)
028h 4 Unknown (0)
02Ch 4 Unknown (0)
Crazy Part3:
000h 4 Unknown (1) ;Num entries?
004h 4+4 Child Block (RefID=4902h, Offset from Crazy Part3+0) ;Offs=0Ch
00Ch 4 Unknown (0 or 2)
010h 4 Unknown (0)
CBNK Header
000h 4 ID "CBNK"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 20h)
008h 4 Version? (can be 01000100h)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 1 = INFO)
014h 4+4+4 INFO Block (RefID=5800h, Offset from CBNK+0, Size)
INFO Block
000h 4 ID "INFO"
004h 4 INFO Block Size (same as in CBNK Header)
008h 4+4 Footer Entry (RefID=0100h, Offset from Info+8) ;Offs=Near end
010h 4+4 List Entry (RefID=0101h, Offset from Info+8) ;Offs=10h
018h 4 Number of following List Entries
01Ch (4+4)*N List Entries (RefID=59xxh, Offs from INFO+18h or Offs=FFFFFFFFh)
... .. Entries for above list
... 4+8*X Footer Entry
List Entry with RefID=5903h:
Nothing (these entries have Offset=FFFFFFFFh)
CWAR files can contain CWAV files. The CWAR files are located inside of CSAR
archives.
Note: The CWARs are often left nameless (the CSAR may contain only one name
entry in its STRG block (or none at all), despite of have multiple CWARs in its
INFO block.
CWAR Header
000h 4 ID "CWAR"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 40h)
008h 4 Version? (can be 01000000h)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 2 = INFO+FILE)
014h 4+4+4 INFO Block (RefID=6800h, Offset from CWAR+0, Size)
020h 4+4+4 FILE Block (RefID=6801h, Offset from CWAR+0, Size)
02Ch 14h Padding to 20h-byte boundary (0)
INFO Block
000h 4 ID "INFO"
004h 4 INFO Block Size (same as in CWAR Header)
008h 4 Number of following List entries
00Ch (4+4+4)*N List Entries (RefID=1F00h, Offset from FILE+8, Size)
... .. Padding to 20h-byte boundary (0)
FILE Block
000h 4 ID "FILE"
004h 4 FILE Block Size (same as in CWAR Header)
008h 18h Padding to 20h-byte boundary (0)
020h ... Data Area (contains CWAV files)
3DS Files - Sound Wave Data (CWAV Format)
-----------------------------------------
CWAV files contain audio samples for use as instruments or sound effects,
somewhat resembling .wav files.
The CWAV is usually stored in a CWAR Wave Archive (with the CWAR being stored
in a CSAR Sound Archive). Additionally, a CWAV block can be found inside of
Banner files. And, there are also standalone CWAV files (eg. in 3DS Camera
"RomFS:\sound\*.bcwav").
CWAV Header
000h 4 ID "CWAV"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 0040h)
008h 4 Version (02010000h)
00Ch 4 Total File Size
010h 2 Number of Blocks (usually 2, INFO+DATA)
012h 2 Reserved
014h 4+4+4 INFO Block (RefID=7000h, Offset from CWAV+0, Size)
020h 4+4+4 DATA Block (RefID=7001h, Offset from CWAV+0, Size)
02Ch 14h Padding to 20h-byte boundary (0)
Info Block
000h 4 Chunk ID "INFO"
004h 4 Chunk Size
008h 1 Encoding (0=PCM8, 1=PCM16, 2=DSP-ADPCM, 3=IMA-ADPCM)
009h 1 Loop (0=Don't loop, 1=Loop)
00Ah 2 Padding (0)
00Ch 4 Sample Rate (eg. 3E80h = 16000Hz?)
010h 4 Loop Start Frame (0=Begin of sample?, or 0=None when not looping)
014h 4 Loop End Frame (eg. 409h ?) (also End Frame when not looping)
018h 4 Unknown (0)
01Ch 4 Unknown (1)
020h 4+4 Sample Info (RefID=7100h, Offset from INFO+8?) ;Offs=0Ch
028h 4+4 Sample Data (RefID=1F00h, Offset from DATA+8) ;Offs=18h
.. .. Sample Info
.. .. ADPCM Info (if any)
.. .. Padding to 20h-byte boundary (0)
Sample Info (RefID=7100h):
000h 4+4 DSP-ADPCM Info (RefID=0300h, Offset from INFO+?) ;Offs=14h ;\
IMA-ADPCM Info (RefID=0301h, Offset from INFO+?) ;Offs=14h ;
No ADPCM Info (RefID=0000h, Offset=FFFFFFFFh) ;None ;/
008h 4 Unknown (0)
ADPCM Info (RefID=0300h) (when Encoding is DSP-ADPCM):
000h 32 16bit Coefficients ;-Whatever Coefficients
020h 1 4bit Predictor + 4bit Scale ;\
021h 1 Reserved (0) ; Initial context
022h 2 Previous Sample ;
024h 2 Second Previous Sample ;/
026h 1 4bit Predictor + 4bit Scale ;\
027h 1 Reserved (0) ; Loop context
028h 2 Previous Sample ;
02Ah 2 Second Previous Sample ;/
02Ch 2 ? Padding ?? ;-uh?
ADPCM Info (RefID=0301h) (when Encoding is IMA-ADPCM):
000h 2 Data ;\Initial context
002h 1 Table Index ; ...for port 10103418h+(N*20h)?
003h 1 Padding ;/
004h 2 Data ;\Loop context
006h 1 Table Index ; ...for port 1010341Ch+(N*20h)?
007h 1 Padding ;/
Data Block
000h 4 Chunk ID "DATA"
004h 4 Chunk Size
008h 18h Padding to 20h-byte boundary (0)
020h .. Sample Data (eg. PCM16) ;at Offsets specified in INFO block
CSTM files are very similar to CWAV files, with slightly differently arranged
data, and with an additional SEEK block.
Unknown if/which games or system titles are using CSTM files. They can be
reporedly found in following locations:
- RomFS:\sound\stream\*.bcstm (eg. in Zelda Ocarina of Time)
- Inside of a CSAR (unknown where exactly, maybe inside of CWAR blocks?)
- CSAR's can contain RefID=220Dh entries for external CSTM file (eg. Zelda)
CSTM seems to be intended for streaming medium length recordings (longer than
normal CWAV instruments/effects, and shorter than fully fledged AAC/OGG/MP3
recordings).
CSTM Header
000h 4 ID "CSTM"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 40h)
008h 4 Version (02000000h)
00Ch 4 File Size
010h 2 Number of Blocks (usually 3, INFO+SEEK+DATA)
012h 2 Reserved
014h 4+4+4 INFO Block Reference (RefID=4000h, Offset from CSTM+0, Size)
020h 4+4+4 SEEK Block Reference (RefID=4001h, Offset from CSTM+0, Size)
02Ch 4+4+4 DATA Block Reference (RefID=4002h, Offset from CSTM+0, Size)
038h 8 Padding to 20h-byte boundary
Info Block
000h 4 Chunk ID "INFO"
004h 4 Chunk Size
008h 4+4 Stream Info Entry (RefID=4100h, Offset relative to INFO+8)
010h 4+4 Track Info List (RefID=4101h, Offset relative to INFO+8)
018h 4+4 Channel Info List (RefID=4102h, Offset relative to INFO+8)
020h 38h Stream Info Entry ;\
058h .. Track Info List ; from above Header ;<-- 4+(N*8) ?
.. .. Channel Info List ;/ ;<-- 4+(N*8) ?
.. .. Track Info Entries ;\from above Lists
.. .. Channel Info Entries ;/
If encoding is DSP-ADPCM:
.. .. DSP-ADPCM Info Entries
If encoding is IMA-ADPCM:
.. .. IMA-ADPCM Info Entries
The info block is aligned to 20h bytes. uh, that is, the "Stream Info" block?
Seek Block
000h 4 Chunk ID "SEEK"
004h 4 Chunk Size
008h .. Data ... whatever ?
The seek block is aligned to 20h bytes.
Tools
The following tools can play BCSTMs and convert them to other formats:
Isabelle Sound Editor
vgmstream
Every File Explorer
CGRP files are included in some CSAR files, but not always (for example, a CGRP
can be found in the "AR Games" system title).
The purpose of CGRP is unknown. The INFO block seems to be mainly good for
re-ordering whatever indices. And the FILE block is somewhat empty.
CGRP Header
000h 4 ID "CGRP"
004h 2 Byte Order (FEFFh)
006h 2 Header Size (usually 40h)
008h 4 Version? (can be 01000000h)
00Ch 4 Total Filesize
010h 4 Number of Blocks (usually 2 = INFO+FILE)
014h 4+4+4 INFO Block (RefID=7800h, Offset from CGRP+0, Size)
020h 4+4+4 FILE Block (RefID=7801h, Offset from CGRP+0, Size)
02Ch 14h Padding to 20h-byte boundary (0)
INFO Block
000h 4 ID "INFO"
004h 4 INFO Block Size (same as in CGRP Header)
008h 4 Number of following List entries (eg. 40h)
00Ch (4+4)*N List Entries (RefID=7900h, Offset from INFO+8)
... .. Padding to 20h-byte boundary (0)
List Entry Format:
000h 4 Unknown (0..NumListEntries, in no specific order)
(and apparently one value skipped, since using values
in range 0..Num would be Num+1 values in total)
004h 4 Unknown (FFFFFFFFh)
008h 4 Unknown (FFFFFFFFh)
00Ch 4 Unknown (0)
FILE Block
000h 4 ID "FILE"
004h 4 FILE Block Size (same as in CGRP Header) (=20h)
008h 18h Padding to 20h-byte boundary (0)
Apart from the above header, there is no actual data in the FILE block, unless
it's meant to be a prefix for the following CWAR blocks in the CSAR file?
Some titles have the CSAR file bundled with a separate CSID file with .csid
extension (eg. 3DS Health Safety RomFS:\sound\Main.csid and 3DS Instruction
Manual applet RomFS:\sound\Main.csid), which appears to be a relict from
devkit, used before/after generating the CSAR file.
The file contains Symbols and 32bit Resource IDs in ASCII, oddly, with an UTF-8
Byte Order Mark (EFh,BBh,BFh) in the file header.
Teak DSP binaries are usually having extension .cdc (supposedly unrelated to
the "cdc" codec services). DSP binaries are found in some titles (eg. 3DS eShop
RomFS:\sound\dspaudio.cdc, 3DS Browser Applet RomFS:\snd\dspaudio.cdc, and
(LZ11-compressed) 3DS Nintendo Zone RomFS:\dspaudio.cdc.nwcx).
Unknown if there is some kind of default DSP driver for use by other titles.
Flags.bit0=RecvData
If set, DSP module calls DSP:RecvData on "all three registers" and expects them
to reply value, uh, that is... probably done as handshake AFTER uploading the
DSP binary?
Flags.bit1=WithSpecialSegment
If set, 214h bytes are read from CfgS:GetConfigInfoBlk8 block 70000h, and then
copied to the special segment area/address. If the reading fails, zeroes are
written in its place. The purpose of this segment is currently unknown.
NWM File/versions
The wifi driver can be found in following locations (each console should have
one normal mode file, and one safe mode file):
3ds:\title\00040130\00002d02\content\000000vv.app ;NWM Normal mode (all 3DS)
3ds:\title\00040130\00002d03\content\0000000v.app ;NWM Safe mode (Old3DS)
3ds:\title\00040130\20002d03\content\0000000v.app ;NWM Safe mode (New3DS)
The .app file contains a compressed .code file (inside of the NCCH ExeFS). That
.code file contains ARM11 code and six datablocks with the actual Xtensa wifi
firmware (similar as in the DSi wifi firmware):
Stub.data 038h bytes ;\Database and EEPROM reading stub
Stub.code 316h bytes ; (always same size/content)
Database 1E8h bytes ;/
Main.type1 0FD3h, 10F7h, or 1B1Bh bytes ;\Main firmware (compressed)
Main.type4 A053h, A482h, or A5EBh bytes ; (size/content varies per version)
Main.type5 78F6h, or 7A2Eh bytes ;/
There are a few safe mode versions, and dozen(s) of normal mode versions. The
versions may contain different ARM11 code, and/or different Xtensa code (as
shown above, there are at least three revisions of the Xtensa "Main" code
blocks (spotted in four different NWM files, so there may be much more
variations)).
RARC archives are used in Wii and GameCube games like Super Mario Galaxy 1 & 2
and Supermario Sunshine. The RARC format is unique in terms of storing
duplicated folder data in both Folder List and Directory Entries.
Info Block (20h-bytes, plus Folder List, Directory List, String Table)
000h 4 Folder List Size/10h (number of folders)
004h 4 Folder List Offset (relative to the start of Info block)
008h 4 Directory List Size/14h (number of files+folders)
00Ch 4 Directory List Offset (relative to the start of Info block)
010h 4 String Table Size/1 (in bytes)
014h 4 String Table Offset (relative to the start of Info block)
018h 2 Number of directory entries that are Files (number of files)
01Ah 6 Unknown (zerofilled)
020h .. Folder List (10h bytes per entry)
... .. Directory List (14h bytes per entry)
... .. String Table
U8 archives are used in Mario Kart Wii and maybe other games (something called
Wii discs is reportedly using a similar format, too).
Note: The U8 format is about same as 3DS "darc" format (with different header,
different byte-order, and ASCII instead of UTF-16 names).
--> 3DS Files - Archive DARC
Hardware IDs
The main Console ID is stored in OTP memory:
--> 3DS Crypto - PRNG and OTP Registers
The eMMC CID is used for generating console specific encryption keys. The SD
card CID is also used for generating a SD card specific <ID1> folder name.
eMMC Images
no$gba can load 3DS eMMC images from following files in no$gba folder
(currently that merely allows to view eMMC images in Window/Filesystem, ie.
there isn't any actual 3DS emulation supported in no$gba):
3DS-#.mmc ;\with "#" being the machine number ("1".."C")
New3DS-#.mmc ;/
For decrypting the image, CID and OTP needs to be stored at following eMMC
offsets:
DC00h 20h ID '3DS CID/OTP/NCSD/FIRM BackupData'
DC20h 10h eMMC CID (from eMMC command CMD10)
DC30h D0h Reserved
DD00h 100h OTP (from ARM9 I/O address 10012000h)
DE00h 200h Copy of original NCSD (from eMMC offset 00000000h)
E000h 1000h Copy of original FIRM0 (from eMMC offset 0B130000h)
F000h 1000h Copy of original FIRM1 (from eMMC offset 0B530000h)
The copy of original NCSD/FIRM0/FIRM1 allows to uninstall sighax-based stuff
(or to install such stuff; doing that works even without having OTP dump, as
long as the unencrypted content of the NCSD/FIRM0/FIRM1 sectors is known).
3DS XL
2DS
New3DS
New2DS XL
Unknown. These consoles seem to be quite rare, and no PCB photos exist...?
Old 2DS does have a Sleep button additionally to Power, maybe Sleep is
equivalent to Hinge on folded consoles?
3DS Testpoints
--------------
Testpoints for New 3DS, New 3DS XL, and New 2DS
New 3DS and New 3DS XL (and probably New 2DS) do also have testpoints, but only
half as many, and without text layer (so they could be used/described only via
photos or drawings).
See also
http://www.3dbrew.org/wiki/Hardware
http://www.3dbrew.org/wiki/TP_Nets
http://www.3dbrew.org/wiki/Pinouts
http://www.3dbrew.org/wiki/Video_Capture
P1 - 19pin - NDS/DSi cartridge slot (17pin slot + 2pin switch at right side)
1 GND NDS Slot GND
2 TP95 NDS Slot CLK
3 NC? NDS Slot ?
4 TP107 NDS Slot /RomCS
5 TP108 NDS Slot /Reset
6 TP99 NDS Slot /SaveCS
7 TP102 NDS Slot IRQ
8 TP16 NDS Slot 3.3V
9 TP110 NDS Slot D0
10 TP111 NDS Slot D1
11 TP112 NDS Slot D2
12 TP104 NDS Slot D3
13 TP105 NDS Slot D4
14 TP113 NDS Slot D5
15 TP114 NDS Slot D6
16 TP106 NDS Slot D7
17 GND NDS Slot GND
18 TP109 NDS Slot /Insert Signal
19 GND NDS Slot /Insert GND
P2 - 6pin - External Power Supply input (4.6V DC IN) (with sticky glue!)
1 TP4 4.6VIN (Power pin +)
2 TP1 GND (Power pin -)
3 TP1 GND (Shield)
4 TP1 GND (Shield)
5 TP4 4.6VIN (goldplate +) ;\alternate contacts (requires constant
6 TP1 GND (goldplate -) ;/pressure, maybe for expansion hardware)
Note: This surface mounted connector breaks off easily, but it can be soldered
back in without problems (the 2DS uses a better connector with thru-holes; and
without goldplates).
P4 - 3pin - Battery
+ TP22 Battery + ;(via F2 to TP259)
x TP23 Battery type/detect/alert?
- GND Battery -
P22/P23 - N/A
None such.
Accelerometer (LIS331DLH)
1 VDD_IO Power supply for I/O pins TP240=1.8V
2 NC Not connected -
3 NC Not connected -
4 SCL,SPC I2C.clock (or SPI.clock) TP34=SCL
5 GND 0V supply GND
6 SDA,SDI,SDO I2C.data (or SPI.data.in, or 3-wire.data.out) TP33=SDA
7 SA0,SDO I2C.device.id (or SPI.data.out) CL1=GNDed
8 CS Mode (high=I2C, low=SPI) TP240=1.8V
9 INT2 Inertial interrupt 2 TP54
10 Reserved Connect to GND GND
11 INT1 Inertial interrupt 1 TP53
12 GND 0V supply GND
13 GND 0V supply GND
14 VDD Power supply D7-to-TP3
15 Reserved Connect to VDD D7-to-TP3
16 GND 0V supply GND
BQ24072 Charging IC (should match the "CKP" chip in Old3DS and New3DS XL)
1 TS I External NTC Thermistor (3DS: dummy R2 resistor?);10K-to-GND
2 BAT I/O Battery (charge output, and battery sense input) ;TP259/F2/TP22
3 BAT I/O Battery (charge output, and battery sense input) ;TP259/F2/TP22
4 /CE I Charge Enable ;TP11
5 EN2 I ;10K-to-TP8
6 EN1 I ;GNDed
7 /PGOOD O External Supply Power Good (open drain) ;TP7
8 GND - Ground ;GND
9 /CHG O Charging (open drain) ;TP10
10 OUT O Supply Output ;\from BAT or IN to system ;TP8
11 OUT O Supply Output ;/ ;TP8
12 ILIM I Current Limit adjust (wire 1100..8000ohm to GND) ;1.96K-to-GND
13 IN I External Supply Input (4.35V..6.6V) ;EM1/F1/TP4
14 TMR I ;56K-to-GND
15 TD I ;GNDed
16 ISET I Fast Charge Current (wire 590..8900ohm to GND) ;1.5K-to-GND
Whatever "EPB" (Maybe power on/off main cpu power supplies?) (Old3DS U12)
Voltage Supervisor with Reset? Voltage Regulator with adjust/enable?
.-----.
TP5 -|1 6|- TP3 ;TP3=Supply +3.3V, TP5=Supply 1.8V
GND -|2 5|- GND
TP245 -|3 4|- TP246 ;TP246=low 0V, and TP245=high 1.7V
'-----'
Note: Upon Power on, TP246 carries a "variable frequency clock signal" for a
moment, and then goes low.
Note
Switching between ARM and THUMB state can be done by using the Branch and
Exchange (BX) instruction.
Further Information
--> ARM Pseudo Instructions and Directives
--> ARM CP15 System Control Coprocessor
--> ARM Vector Floating-point Unit (VFP)
--> ARM CPU Instruction Cycle Times
--> ARM CPU Versions
--> ARM CPU Data Sheet
The ARM7TDMI is a 32bit RISC (Reduced Instruction Set Computer) CPU, designed
by ARM (Advanced RISC Machines), and designed for both high performance and low
power consumption.
Fast Execution
Depending on the CPU state, all opcodes are sized 32bit or 16bit (that's
counting both the opcode bits and its parameters bits) providing fast decoding
and execution. Additionally, pipelining allows - (a) one instruction to be
executed while (b) the next instruction is decoded and (c) the next instruction
is fetched from memory - all at the same time.
Data Formats
The CPU manages to deal with 8bit, 16bit, and 32bit data, that are called:
8bit - Byte
16bit - Halfword
32bit - Word
Also, as both ARM and THUMB are using the same register set, it is possible to
pass data between ARM and THUMB mode very easily.
The best memory & execution performance can be gained by combining both states:
THUMB for normal program code, and ARM code for timing critical subroutines
(such like interrupt handlers, or complicated algorithms).
Overview
The following table shows the ARM7TDMI register set which is available in each
mode. There's a total of 37 registers (32bit each), 31 general registers (Rxx)
and 6 status registers (xPSR).
Note that only some registers are 'banked', for example, each mode has it's own
R14 register: called R14, R14_fiq, R14_svc, etc. for each mode respectively.
However, other registers are not banked, for example, each mode is using the
same R0 register, so writing to R0 will always affect the content of R0 in
other modes also.
Bit 27: Sticky Overflow Flag (Q) - ARMv5TE and ARMv5TExP and up only
Used by QADD, QSUB, QDADD, QDSUB, SMLAxy, and SMLAWy only. These opcodes set
the Q-flag in case of overflows, but leave it unchanged otherwise. The Q-flag
can be tested/reset by MSR/MRS opcodes only.
Bit 27-8: Reserved Bits (except Bit 27 on ARMv5TE and up, see above)
These bits are reserved for possible future implementations. For best forwards
compatibility, the user should never change the state of these bits, and should
not expect these bits to be set to a specific value.
The 26bit Memory Interface was used by ARMv1 and ARMv2. The 32bit interface is
used by ARMv3 and newer, however, 26bit backward compatibility was included in
all ARMv3 (except ARMv3G), and optionally in some non-T variants of ARMv4.
Writing to R15
ALU opcodes with S=1, and LDM opcodes with PSR=1 can write to all 32bits in R15
(in 26bit mode, that is allowed even in user mode, though it does then affect
only NZCF, not the write protected IFMM bits ???), other opcodes which write to
R15 will modify only the program counter bits. Also, special CMP/CMN/TST/TEQ{P}
opcodes can be used to write to the PSR bits in R15 without modifying the PC
bits.
Exceptions
SWIs, Reset, Data/Prefetch Aborts and Undefined instructions enter Supervisor
mode. Interrupts enter IRQ and FIQ mode. Additionally, a special 26bit Address
Exception exists, which enters Supervisor mode on accesses to memory
addresses>=64M as follows:
R14_svc = PC ($+8, including old PSR bits)
M1,M0 = 11b = supervisor mode, F=same, I=1, PC=14h,
to continue at the fault location, return by SUBS PC,LR,8.
32bit CPUs with 26bit compatibility mode can be configured to switch into 32bit
mode when encountering exceptions.
Exception Vectors
The following are the exception vectors in memory. That is, when an exception
arises, CPU is switched into ARM state, and the program counter (PC) is loaded
by the respective address.
Address Prio Exception Mode on Entry Interrupt Flags
BASE+00h 1 Reset Supervisor (_svc) I=1, F=1
BASE+04h 7 Undefined Instruction Undefined (_und) I=1, F=unchanged
BASE+08h 6 Software Interrupt (SWI) Supervisor (_svc) I=1, F=unchanged
BASE+0Ch 5 Prefetch Abort Abort (_abt) I=1, F=unchanged
BASE+10h 2 Data Abort Abort (_abt) I=1, F=unchanged
BASE+14h ?? Address Exceeds 26bit Supervisor (_svc) I=1, F=unchanged
BASE+18h 4 Normal Interrupt (IRQ) IRQ (_irq) I=1, F=unchanged
BASE+1Ch 3 Fast Interrupt (FIQ) FIQ (_fiq) I=1, F=1
BASE is normally 00000000h, but may be optionally FFFF0000h in some ARM CPUs.
Priority for simultaneously occuring exceptions ranges from Prio=1=Highest to
Prio=7=Lowest.
As there's only space for one ARM opcode at each of the above addresses, it'd
be usually recommended to deposit a Branch opcode into each vector, which'd
then redirect to the actual exception handlers address.
Software Interrupt
Generated by a software interrupt instruction (SWI). Recommended to request a
supervisor (operating system) function. The SWI instruction may also contain a
parameter in the 'comment field' of the opcode:
In case that your main program issues SWIs from both inside of THUMB and ARM
states, then your exception handler must separate between 24bit comment fields
in ARM opcodes, and 8bit comment fields in THUMB opcodes (if necessary
determine old state by examining T Bit in SPSR_svc); However, in Little Endian
mode, you could use only the most significant 8bits of the 24bit ARM comment
field (as done in the GBA, for example) - the exception handler could then
process the BYTE at [R14-2], regardless of whether it's been called from ARM or
THUMB state.
To return from Supervisor Mode (continuing at following opcode):
MOVS PC,R14 ;both PC=R14_svc, and CPSR=SPSR_svc
Note: Like all other exceptions, SWIs are always executed in ARM state, no
matter whether it's been caused by an ARM or THUMB state SWI instruction.
Reset
Forces PC=VVVV0000h, and forces control bits of CPSR to T=0 (ARM state), F=1
and I=1 (disable FIQ and IRQ), and M4-0=10011b (Supervisor mode).
The CPU does NOT support accessing mis-aligned addresses (which would be rather
slow because it'd have to merge/split that data into two accesses).
When reading/writing code/data to/from memory, Words and Halfwords must be
located at well-aligned memory address, ie. 32bit words aligned by 4, and 16bit
halfwords aligned by 2.
Multiply
Instruction Cycles Flags Expl.
MUL{cond}{S} Rd,Rm,Rs 1S+mI NZx- Rd = Rm*Rs
MLA{cond}{S} Rd,Rm,Rs,Rn 1S+mI+1I NZx- Rd = Rm*Rs+Rn
UMULL{cond}{S} RdLo,RdHi,Rm,Rs 1S+mI+1I NZx- RdHiLo = Rm*Rs
UMLAL{cond}{S} RdLo,RdHi,Rm,Rs 1S+mI+2I NZx- RdHiLo = Rm*Rs+RdHiLo
SMULL{cond}{S} RdLo,RdHi,Rm,Rs 1S+mI+1I NZx- RdHiLo = Rm*Rs
SMLAL{cond}{S} RdLo,RdHi,Rm,Rs 1S+mI+2I NZx- RdHiLo = Rm*Rs+RdHiLo
SMLAxy{cond} Rd,Rm,Rs,Rn ARMv5TE(xP) ----q Rd=HalfRm*HalfRs+Rn
SMLAWy{cond} Rd,Rm,Rs,Rn ARMv5TE(xP) ----q Rd=(Rm*HalfRs)/10000h+Rn
SMULWy{cond} Rd,Rm,Rs ARMv5TE(xP) ---- Rd=(Rm*HalfRs)/10000h
SMLALxy{cond} RdLo,RdHi,Rm,Rs ARMv5TE(xP) ---- RdHiLo=RdHiLo+HalfRm*HalfRs
SMULxy{cond} Rd,Rm,Rs ARMv5TE(xP) ---- Rd=HalfRm*HalfRs
Memory Load/Store
Instruction Cycles Flags Expl.
LDR{cond}{B}{T} Rd,<Address> 1S+1N+1I+y ---- Rd=[Rn+/-<offset>]
LDR{cond}H Rd,<Address> 1S+1N+1I+y ---- Load Unsigned halfword
LDR{cond}D Rd,<Address> ---- Load Dword ARMv5TE
LDR{cond}SB Rd,<Address> 1S+1N+1I+y ---- Load Signed byte
LDR{cond}SH Rd,<Address> 1S+1N+1I+y ---- Load Signed halfword
LDM{cond}{amod} Rn{!},<Rlist>{^} nS+1N+1I+y ---- Load Multiple
STR{cond}{B}{T} Rd,<Address> 2N ---- [Rn+/-<offset>]=Rd
STR{cond}H Rd,<Address> 2N ---- Store halfword
STR{cond}D Rd,<Address> ---- Store Dword ARMv5TE
STM{cond}{amod} Rn{!},<Rlist>{^} (n-1)S+2N ---- Store Multiple
SWP{cond}{B} Rd,Rm,[Rn] 1S+2N+1I ---- Rd=[Rn], [Rn]=Rm
PLD <Address> 1S ---- Prepare Cache ARMv5TE
For LDR/LDM, add y=1S+1N if Rd=R15, or if R15 in Rlist.
ARM Opcodes: Branch and Branch with Link (B, BL, BX, BLX, SWI, BKPT)
--------------------------------------------------------------------
Opcode Format
Bit Expl.
31-28 Condition
27-26 Must be 00b for this instruction
25 I - Immediate 2nd Operand Flag (0=Register, 1=Immediate)
24-21 Opcode (0-Fh) ;*=Arithmetic, otherwise Logical
0: AND{cond}{S} Rd,Rn,Op2 ;AND logical Rd = Rn AND Op2
1: EOR{cond}{S} Rd,Rn,Op2 ;XOR logical Rd = Rn XOR Op2
2: SUB{cond}{S} Rd,Rn,Op2 ;* ;subtract Rd = Rn-Op2
3: RSB{cond}{S} Rd,Rn,Op2 ;* ;subtract reversed Rd = Op2-Rn
4: ADD{cond}{S} Rd,Rn,Op2 ;* ;add Rd = Rn+Op2
5: ADC{cond}{S} Rd,Rn,Op2 ;* ;add with carry Rd = Rn+Op2+Cy
6: SBC{cond}{S} Rd,Rn,Op2 ;* ;sub with carry Rd = Rn-Op2+Cy-1
7: RSC{cond}{S} Rd,Rn,Op2 ;* ;sub cy. reversed Rd = Op2-Rn+Cy-1
8: TST{cond}{P} Rn,Op2 ;test Void = Rn AND Op2
9: TEQ{cond}{P} Rn,Op2 ;test exclusive Void = Rn XOR Op2
A: CMP{cond}{P} Rn,Op2 ;* ;compare Void = Rn-Op2
B: CMN{cond}{P} Rn,Op2 ;* ;compare neg. Void = Rn+Op2
C: ORR{cond}{S} Rd,Rn,Op2 ;OR logical Rd = Rn OR Op2
D: MOV{cond}{S} Rd,Op2 ;move Rd = Op2
E: BIC{cond}{S} Rd,Rn,Op2 ;bit clear Rd = Rn AND NOT Op2
F: MVN{cond}{S} Rd,Op2 ;not Rd = NOT Op2
20 S - Set Condition Codes (0=No, 1=Yes) (Must be 1 for opcode 8-B)
19-16 Rn - 1st Operand Register (R0..R15) (including PC=R15)
Must be 0000b for MOV/MVN.
15-12 Rd - Destination Register (R0..R15) (including PC=R15)
Must be 0000b (or 1111b) for CMP/CMN/TST/TEQ{P}.
When above Bit 25 I=0 (Register as 2nd Operand)
When below Bit 4 R=0 - Shift by Immediate
11-7 Is - Shift amount (1-31, 0=Special/See below)
When below Bit 4 R=1 - Shift by Register
11-8 Rs - Shift register (R0-R14) - only lower 8bit 0-255 used
7 Reserved, must be zero (otherwise multiply or LDREX or undefined)
6-5 Shift Type (0=LSL, 1=LSR, 2=ASR, 3=ROR)
4 R - Shift by Register Flag (0=Immediate, 1=Register)
3-0 Rm - 2nd Operand Register (R0..R15) (including PC=R15)
When above Bit 25 I=1 (Immediate as 2nd Operand)
11-8 Is - ROR-Shift applied to nn (0-30, in steps of 2)
7-0 nn - 2nd Operand Unsigned 8bit Immediate
The instruction "MOV R0,R0" is used as "NOP" opcode in 32bit ARM state.
Execution Time: (1+p)S+rI+pN. Whereas r=1 if I=0 and R=1 (ie. shift by
register); otherwise r=0. And p=1 if Rd=R15; otherwise p=0.
Opcode Format
Bit Expl.
31-28 Condition
27-25 Must be 000b for this instruction
24-21 Opcode
0000b: MUL{cond}{S} Rd,Rm,Rs ;Rd=Rm*Rs ;\works as both
0001b: MLA{cond}{S} Rd,Rm,Rs,Rn ;Rd=Rm*Rs+Rn ;/signed+unsigned
0010b: UMAAL{cond} RdLo,RdHi,Rm Rs ;RdHiLo=Rm*Rs+RdHi+RdLo;\un-
0100b: UMULL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHiLo=Rm*Rs ; signed
0101b: UMLAL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHiLo=Rm*Rs+RdHiLo ;/
0110b: SMULL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHiLo=Rm*Rs
0111b: SMLAL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHiLo=Rm*Rs+RdHiLo
1000b: SMLAxy{cond} Rd,Rm,Rs,Rn ;Rd=HalfRm*HalfRs+Rn
1001b: SMLAWy{cond} Rd,Rm,Rs,Rn ;Rd=(Rm*HalfRs)/10000h+Rn
1001b: SMULWy{cond} Rd,Rm,Rs ;Rd=(Rm*HalfRs)/10000h
1010b: SMLALxy{cond} RdLo,RdHi,Rm,Rs ;RdHiLo=RdHiLo+HalfRm*HalfRs
1011b: SMULxy{cond} Rd,Rm,Rs ;Rd=HalfRm*HalfRs
20 S - Set Condition Codes (0=No, 1=Yes) (Must be 0 for Halfword & UMAAL)
19-16 Rd (or RdHi) - Destination Register (R0-R14)
15-12 Rn (or RdLo) - Accumulate Register (R0-R14) (Set to 0000b if unused)
11-8 Rs - Operand Register (R0-R14)
For Non-Halfword Multiplies
7-4 Must be 1001b for these instructions
For Halfword Multiplies
7 Must be 1 for these instructions
6 y - Rs Top/Bottom flag (0=B=Lower 16bit, 1=T=Upper 16bit)
5 x - Rm Top/Bottom flag (as above), or 0 for SMLAW, or 1 for SMULW
4 Must be 0 for these instructions
3-0 Rm - Operand Register (R0-R14)
Store Return State (SRS) (stores the R14 and SPSR of the current mode)
to the word at the specified address and the following word respectively. The
address is determined from the banked version of R13 belonging to a specified
mode.
Syntax
SRS<addressing_mode> #<mode>{!} ;<-- original (pre-UAL)
SRS<addressing_mode> sp!,#<mode> ;<-- more common (UAL)
<addressing_mode>: Is similar to the <addressing_mode> in LDM and STM
instructions, see Addressing Mode 4 - Load and Store Multiple on page A5-41,
but with the following differences:
- The base register, Rn, is the banked version of R13 for the mode specified by
<mode>, rather than the current mode.
- The number of registers to store is 2.
- The register list is {R14, SPSR}, with both R14 and the SPSR being the
versions belonging to the current mode.
<mode> Specifies the number of the mode whose banked register is used as the
base register for <addressing_mode>. The mode number is the 5-bit encoding of
the chosen mode in a PSR, as described in The mode bits on page A2-14.
! If present, sets the W bit. This causes the instruction to write a modified
value back to its base register, in a manner similar to that specified for
Addressing Mode 4 - Load and Store Multiple on page A5-41. If ! is omitted, the
W bit is 0 and the instruction does not change the base register.
31-25 Fixed, 1111100b
24 P
23 U
22 Fixed, 1
21 W
20 Fixed, 0 (store)
19-5 Fixed, 110100000101000b
4-0 mode
Supported on ARMv6 and above.
CPY
CPY Rd,Rm is an alias for MOV Rd,Rm (without flags affected).
31-28 Condition
27-16 Fixed, 000110100000
15-12 Rd - Destination Register
11-4 Fixed, 00000000
3-0 Rm
The alias was invented in ARMv6 for THUMB and ARM code (apparently because
pre-UAL THUMB syntax couldn't distinguish between MOV and MOVS) (ie. in ARM
it's useless, but in THUMB it does allow using a formerly undocumented opcode).
ARMv6 and above.
SADD16
SADD16 (Signed Add) performs two 16-bit signed integer additions. It sets the
GE bits in the CPSR according to the results of the additions.
ARMv6 and above.
Operation
sum = Rn[15:0] + Rm[15:0] /* Signed addition */
Rd[15:0] = sum[15:0]
GE[1:0] = if sum >= 0 then 0b11 else 0
sum = Rn[31:16] + Rm[31:16] /* Signed addition */
Rd[31:16] = sum[15:0]
GE[3:2] = if sum >= 0 then 0b11 else 0
31-28 Condition
27-23 Fixed, 01100b
22-20 Opcode, part 1:
001b: for Sxx (signed, with GE flags)
010b: for Qxx (signed, with saturation)
011b: for SHxx (signed, with halving)
101b: for Uxx (unsigned, with GE flags)
110b: for UQxx (unsigned, with saturation)
111b: for UHxx (unsigned, with halving)
19-16 Rn - First Source Register (R0-R14)
15-12 Rd - Destination Register (R0-R14)
11-8 Fixed, 1111b
7-5 Opcode, part 2:
000b: xxADD16{cond} Rd, Rn, Rm
001b: xxADDSUBX{cond} Rd, Rn, Rm
010b: xxSUBADDX{cond} Rd, Rn, Rm
011b: xxSUB16{cond} Rd, Rn, Rm
100b: xxADD8{cond} Rd, Rn, Rm
111b: xxSUB8{cond} Rd, Rn, Rm
4 Fixed, 1
3-0 Rm - Second Source register (R0-R14)
SMLAD
SMLAD (Signed Multiply Accumulate Dual) performs two signed 16 x 16-bit
multiplications. It adds the products to a 32-bit accumulate operand.
Optionally, you can exchange the halfwords of the second operand before
performing the arithmetic. This produces top x bottom and bottom x top
multiplication.
This instruction sets the Q flag if the accumulate operation overflows.
Overflow cannot occur during the multiplications.
X Sets the X bit of the instruction to 1, and the multiplications are bottom x
top and top x bottom.
If the X is omitted, sets the X bit to 0, and the multiplications are bottom x
bottom and top x top.
<Rm> Specifies the register that contains the first operand.
<Rs> Specifies the register that contains the second operand.
<Rn> Specifies the register that contains the accumulate operand.
31-28 Condition
27-23 Fixed, 01110
22-20 Opcode part 1 (part2 in bit7-6)
Merged part1.part2:
000.00: SMUAD{X}{cond} Rd,Rm,Rs
000.00: SMLAD{X}{cond} Rd,Rm,Rs,Rn
000.01: SMUSD{X}{cond} Rd,Rm,Rs
000.01: SMLSD{X}{cond} Rd,Rm,Rs,Rn
100.00: SMLALD{X}{cond} RdLo,RdHi,Rm,Rs
100.01: SMLSLD{X}{cond} RdLo,RdHi,Rm,Rs
101.00: SMMUL{R}{cond} Rd,Rm,Rs ;Rd=(Rm*Rs)/100000000h
101.00: SMMLA{R}{cond} Rd,Rm,Rs,Rn ;Rd=(Rm*Rs)/100000000h+Rz
101.11: SMMLS{R}{cond} Rd,Rm,Rs,Rn ;Rd=(Rm*Rs)/100000000h-Rz
19-16 Rd or RdHi - Destination Register
15-12 Rn or RdLo or unused (must be 0Fh for SMUAD/SMUSD/SMMUL)
11-8 Rs
7-6 Opcode part 2 (part1 in bit22-20, see there)
5 X or R flag (X=Exchange, R=Rounded)
4 Fixed, 1
3-0 Rm
ARMv6 and above.
Most significant word multiply
There are three signed 32-bit x 32-bit Multiply instructions that produce top
32-bit results:
SMMUL Multiplies the 32-bit values of two registers together, and stores
the top 32 bits of the signed 64-bit result in a third register.
SMMLA Multiplies the 32-bit values of two registers together, extracts the
top 32 bits, adds the 32-bit value from a third register, and stores
the signed 32-bit result in a fourth register.
SMMLS Multiplies the 32-bit value of two registers together, extracts the
top 32 bits, subtracts this from a 32-bit value from a third
register, and stores the signed 32-bit result in a fourth register.
The above three instructions do not affect any flags.
Dual halfword multiply
There are six dual, signed 16-bit x 16-bit Multiply instructions:
SMUAD Multiplies the values of the top halfwords of two registers together,
multiplies the values of the bottom halfwords of the same two
registers together, adds the products, and stores the 32-bit result
in a third register.
SMUSD Multiplies the values of the top halfwords of two registers together,
multiplies the values of the bottom halfwords of the same two
registers together, subtracts one product from the other, and stores
the 32-bit result in a third register.
---(descriptions below seem to be bugged, seem to describe 32bit SMMxx)---
SMLAD Multiplies the 32-bit value of two registers together, extracts the
top 32 bits, subtracts this from a 32-bit value from a third
register, and stores the signed 32-bit result in a fourth register.
SMLSD Multiplies the 32-bit values of two registers together, extracts the
top 32 bits, adds the 32-bit value from a third register, and stores
the signed 32-bit result in a fourth register.
SMLALD Multiplies the 32-bit value of two registers together, extracts the
top 32 bits, subtracts this from a 32-bit value from a third
register, and stores the signed 32-bit result in a fourth register.
SMLSLD Multiplies the 32-bit value of two registers together, extracts the
top 32 bits, subtracts this from a 32-bit value from a third
register, and stores the signed 32-bit result in a fourth register.
SMUAD, SMLAD, and SMLSLD can set the Q flag if overflow occurs in the
operation. All other instructions do not affect any flags.
Opcode Format
These instructions occupy an unused area (TEQ,TST,CMP,CMN with S=0) of ALU
opcodes.
Bit Expl.
31-28 Condition
27-26 Must be 00b for this instruction
25 I - Immediate Operand Flag (0=Register, 1=Immediate) (Zero for MRS)
24-23 Must be 10b for this instruction
22 Psr - Source/Destination PSR (0=CPSR, 1=SPSR_<current mode>)
21 Opcode
0: MRS{cond} Rd,Psr ;Rd = Psr
1: MSR{cond} Psr{_field},Op ;Psr[field] = Op
20 Must be 0b for this instruction (otherwise TST,TEQ,CMP,CMN)
For MRS:
19-16 Must be 1111b for this instruction (otherwise SWP)
15-12 Rd - Destination Register (R0-R14)
11-0 Not used, must be zero.
For MSR:
19 f write to flags field Bit 31-24 (aka _flg)
18 s write to status field Bit 23-16 (reserved, don't change)
17 x write to extension field Bit 15-8 (reserved, don't change)
16 c write to control field Bit 7-0 (aka _ctl)
15-12 Not used, must be 1111b.
For MSR Psr,Rm (I=0)
11-4 Not used, must be zero. (otherwise BX)
3-0 Rm - Source Register <op> (R0-R14)
For MSR Psr,Imm (I=1)
11-8 Shift applied to Imm (ROR in steps of two 0-30)
7-0 Imm - Unsigned 8bit Immediate
In source code, a 32bit immediate should be specified as operand.
The assembler should then convert that into a shifted 8bit value.
MSR/MRS and CPSR/SPSR supported by ARMv3 and up.
ARMv2 and below contained PSR flags in R15, accessed by CMP/CMN/TST/TEQ{P}.
The field mask bits specify which bits of the destination Psr are write-able
(or write-protected), one or more of these bits should be set, for example,
CPSR_fsxc (aka CPSR aka CPSR_all) unlocks all bits (see below user mode
restriction though).
Restrictions:
In non-privileged mode (user mode): only condition code bits of CPSR can be
changed, control bits can't.
Only the SPSR of the current mode can be accessed; In User and System modes no
SPSR exists.
The T-bit may not be changed; for THUMB/ARM switching use BX instruction.
Unused Bits in CPSR are reserved for future use and should never be changed
(except for unused bits in the flags field).
Execution Time: 1S.
Note: The A22i assembler recognizes MOV as alias for both MSR and MRS because
it is practically not possible to remember whether MSR or MRS was the load or
store opcode, and/or whether it does load to or from the Psr register.
Opcode Format
Bit Expl.
31-28 Condition (Must be 1111b for PLD)
27-26 Must be 01b for this instruction
25 I - Immediate Offset Flag (0=Immediate, 1=Shifted Register)
24 P - Pre/Post (0=post; add offset after transfer, 1=pre; before trans.)
23 U - Up/Down Bit (0=down; subtract offset from base, 1=up; add to base)
22 B - Byte/Word bit (0=transfer 32bit/word, 1=transfer 8bit/byte)
When above Bit 24 P=0 (Post-indexing, write-back is ALWAYS enabled):
21 T - Memory Management (0=Normal, 1=Force non-privileged access)
When above Bit 24 P=1 (Pre-indexing, write-back is optional):
21 W - Write-back bit (0=no write-back, 1=write address into base)
20 L - Load/Store bit (0=Store to memory, 1=Load from memory)
0: STR{cond}{B}{T} Rd,<Address> ;[Rn+/-<offset>]=Rd
1: LDR{cond}{B}{T} Rd,<Address> ;Rd=[Rn+/-<offset>]
(1: PLD <Address> ;Prepare Cache for Load, see notes below)
Whereas, B=Byte, T=Force User Mode (only for POST-Indexing)
19-16 Rn - Base register (R0..R15) (including R15=PC+8)
15-12 Rd - Source/Destination Register (R0..R15) (including R15=PC+12)
When above I=0 (Immediate as Offset)
11-0 Unsigned 12bit Immediate Offset (0-4095, steps of 1)
When above I=1 (Register shifted by Immediate as Offset)
11-7 Is - Shift amount (1-31, 0=Special/See below)
6-5 Shift Type (0=LSL, 1=LSR, 2=ASR, 3=ROR)
4 Must be 0 (Reserved, see The Undefined Instruction)
3-0 Rm - Offset Register (R0..R14) (not including PC=R15)
Notes
Shift amount 0 has special meaning, as described for ALU opcodes.
When writing a word (32bit) to memory, the address should be word-aligned.
When reading a byte from memory, upper 24 bits of Rd are zero-extended.
LDR PC,<op> on ARMv4 leaves CPSR.T unchanged.
LDR PC,<op> on ARMv5 sets CPSR.T to <op> Bit0, (1=Switch to Thumb).
In a virtual memory based environment (ie. not in the GBA), aborts (ie. page
faults) may take place during execution, if so, Rm and Rn should not specify
the same register when post-indexing is used, as the abort-handler might have
problems to reconstruct the original value of the register.
Opcode Format
Bit Expl.
31-28 Condition
27-25 Must be 000b for this instruction
24 P - Pre/Post (0=post; add offset after transfer, 1=pre; before trans.)
23 U - Up/Down Bit (0=down; subtract offset from base, 1=up; add to base)
22 I - Immediate Offset Flag (0=Register Offset, 1=Immediate Offset)
When above Bit 24 P=0 (Post-indexing, write-back is ALWAYS enabled):
21 Not used, must be zero (0)
When above Bit 24 P=1 (Pre-indexing, write-back is optional):
21 W - Write-back bit (0=no write-back, 1=write address into base)
20 L - Load/Store bit (0=Store to memory, 1=Load from memory)
19-16 Rn - Base register (R0-R15) (Including R15=PC+8)
15-12 Rd - Source/Destination Register (R0-R15) (Including R15=PC+12)
11-8 When above Bit 22 I=0 (Register as Offset):
Not used. Must be 0000b
When above Bit 22 I=1 (immediate as Offset):
Immediate Offset (upper 4bits)
7 Reserved, must be set (1)
6-5 Opcode (0-3)
When Bit 20 L=0 (Store) (and Doubleword Load/Store):
0: Reserved for SWP instruction
1: STR{cond}H Rd,<Address> ;Store halfword [a]=Rd
2: LDR{cond}D Rd,<Address> ;Load Doubleword R(d)=[a], R(d+1)=[a+4]
3: STR{cond}D Rd,<Address> ;Store Doubleword [a]=R(d), [a+4]=R(d+1)
When Bit 20 L=1 (Load):
0: Reserved.
1: LDR{cond}H Rd,<Address> ;Load Unsigned halfword (zero-extended)
2: LDR{cond}SB Rd,<Address> ;Load Signed byte (sign extended)
3: LDR{cond}SH Rd,<Address> ;Load Signed halfword (sign extended)
4 Reserved, must be set (1)
3-0 When above Bit 22 I=0:
Rm - Offset Register (R0-R14) (not including R15)
When above Bit 22 I=1:
Immediate Offset (lower 4bits) (0-255, together with upper bits)
STRH,LDRH,LDRSB,LDRSH supported on ARMv4 and up.
STRD/LDRD supported on ARMv5TE and up only, not ARMv5, not ARMv5TExP.
STRD/LDRD: base writeback: Rn should not be same as R(d) or R(d+1).
STRD: index register: Rm should not be same as R(d) or R(d+1).
STRD/LDRD: Rd must be an even numbered register (R0,R2,R4,R6,R8,R10,R12).
STRD/LDRD: Address must be double-word aligned (multiple of eight).
Opcode Format
Bit Expl.
31-28 Condition
27-25 Must be 100b for this instruction
24 P - Pre/Post (0=post; add offset after transfer, 1=pre; before trans.)
23 U - Up/Down Bit (0=down; subtract offset from base, 1=up; add to base)
22 S - PSR & force user bit (0=No, 1=load PSR or force user mode)
21 W - Write-back bit (0=no write-back, 1=write address into base)
20 L - Load/Store bit (0=Store to memory, 1=Load from memory)
0: STM{cond}{amod} Rn{!},<Rlist>{^} ;Store (Push)
1: LDM{cond}{amod} Rn{!},<Rlist>{^} ;Load (Pop)
Whereas, {!}=Write-Back (W), and {^}=PSR/User Mode (S)
19-16 Rn - Base register (R0-R14) (not including R15)
15-0 Rlist - Register List
(Above 'offset' is meant to be the number of words specified in Rlist.)
Return: No Flags affected.
Execution Time: For normal LDM, nS+1N+1I. For LDM PC, (n+1)S+2N+1I. For STM
(n-1)S+2N. Where n is the number of words transferred.
Notes
The base address should be usually word-aligned.
LDM Rn,...,PC on ARMv4 leaves CPSR.T unchanged.
LDR Rn,...,PC on ARMv5 sets CPSR.T to <op> Bit0, (1=Switch to Thumb).
Transfer Order
The lowest Register in Rlist (R0 if its in the list) will be loaded/stored
to/from the lowest memory address.
Internally, the rlist register are always processed with INCREASING addresses
(ie. for DECREASING addressing modes, the CPU does first calculate the lowest
address, and does then process rlist with increasing addresses; this detail can
be important when accessing memory mapped I/O ports).
Opcode Format
Bit Expl.
31-28 Condition
27-23 Must be 00010b for this instruction
Opcode (fixed)
SWP{cond}{B} Rd,Rm,[Rn] ;Rd=[Rn], [Rn]=Rm
22 B - Byte/Word bit (0=swap 32bit/word, 1=swap 8bit/byte)
21-20 Must be 00b for this instruction
19-16 Rn - Base register (R0-R14)
15-12 Rd - Destination Register (R0-R14)
11-4 Must be 00001001b for this instruction
3-0 Rm - Source Register (R0-R14)
SWP/SWPB supported by ARMv2a and up. SWP/SWPB has been deprecated in ARMv6,
made optional in ARMv7 (with the possibility of disabling it if still
available), and removed in ARMv8.
Swap works properly including if Rm and Rn specify the same register.
R15 may not be used for either Rn,Rd,Rm. (Rn=R15 would be MRS opcode).
Upper bits of Rd are zero-expanded when using Byte quantity. For info about
byte and word data memory addressing, read LDR and STR opcode description.
Execution Time: 1S+2N+1I. That is, 2N data cycles, 1S code cycle, plus 1I.
The table below lists all THUMB mode instructions with clock cycles, affected
CPSR flags, Format/chapter number, and description.
Only register R0..R7 can be used in thumb mode (unless R8-15,SP,PC are
explicitly mentioned).
Logical Operations
Instruction Cycles Flags Format Expl.
MOV Rd,Imm8bit 1S NZ-- 3 Rd=nn
MOV Rd,Rs 1S NZ00 2 Rd=Rs+0
MOV R0..14,R8..15 1S ---- 5 Rd=Rs
MOV R8..14,R0..15 1S ---- 5 Rd=Rs
MOV R15,R0..15 2S+1N ---- 5 PC=Rs
MVN Rd,Rs 1S NZ-- 4 Rd=NOT Rs
AND Rd,Rs 1S NZ-- 4 Rd=Rd AND Rs
TST Rd,Rs 1S NZ-- 4 Void=Rd AND Rs
BIC Rd,Rs 1S NZ-- 4 Rd=Rd AND NOT Rs
ORR Rd,Rs 1S NZ-- 4 Rd=Rd OR Rs
EOR Rd,Rs 1S NZ-- 4 Rd=Rd XOR Rs
LSL Rd,Rs,Imm5bit 1S NZc- 1 Rd=Rs SHL nn
LSL Rd,Rs 1S+1I NZc- 4 Rd=Rd SHL (Rs AND 0FFh)
LSR Rd,Rs,Imm5bit 1S NZc- 1 Rd=Rs SHR nn
LSR Rd,Rs 1S+1I NZc- 4 Rd=Rd SHR (Rs AND 0FFh)
ASR Rd,Rs,Imm5bit 1S NZc- 1 Rd=Rs SAR nn
ASR Rd,Rs 1S+1I NZc- 4 Rd=Rd SAR (Rs AND 0FFh)
ROR Rd,Rs 1S+1I NZc- 4 Rd=Rd ROR (Rs AND 0FFh)
NOP 1S ---- 5 R8=R8
Carry flag affected only if shift amount is non-zero.
Memory Load/Store
Instruction Cycles Flags Format Expl.
LDR Rd,[Rb,5bit*4] 1S+1N+1I ---- 9 Rd = WORD[Rb+nn]
LDR Rd,[PC,8bit*4] 1S+1N+1I ---- 6 Rd = WORD[PC+nn]
LDR Rd,[SP,8bit*4] 1S+1N+1I ---- 11 Rd = WORD[SP+nn]
LDR Rd,[Rb,Ro] 1S+1N+1I ---- 7 Rd = WORD[Rb+Ro]
LDRB Rd,[Rb,5bit*1] 1S+1N+1I ---- 9 Rd = BYTE[Rb+nn]
LDRB Rd,[Rb,Ro] 1S+1N+1I ---- 7 Rd = BYTE[Rb+Ro]
LDRH Rd,[Rb,5bit*2] 1S+1N+1I ---- 10 Rd = HALFWORD[Rb+nn]
LDRH Rd,[Rb,Ro] 1S+1N+1I ---- 8 Rd = HALFWORD[Rb+Ro]
LDSB Rd,[Rb,Ro] 1S+1N+1I ---- 8 Rd = SIGNED_BYTE[Rb+Ro]
LDSH Rd,[Rb,Ro] 1S+1N+1I ---- 8 Rd = SIGNED_HALFWORD[Rb+Ro]
STR Rd,[Rb,5bit*4] 2N ---- 9 WORD[Rb+nn] = Rd
STR Rd,[SP,8bit*4] 2N ---- 11 WORD[SP+nn] = Rd
STR Rd,[Rb,Ro] 2N ---- 7 WORD[Rb+Ro] = Rd
STRB Rd,[Rb,5bit*1] 2N ---- 9 BYTE[Rb+nn] = Rd
STRB Rd,[Rb,Ro] 2N ---- 7 BYTE[Rb+Ro] = Rd
STRH Rd,[Rb,5bit*2] 2N ---- 10 HALFWORD[Rb+nn] = Rd
STRH Rd,[Rb,Ro] 2N ---- 8 HALFWORD[Rb+Ro]=Rd
PUSH {Rlist}{LR} (n-1)S+2N ---- 14
POP {Rlist}{PC} ---- 14 (ARM9: with mode switch)
STMIA Rb!,{Rlist} (n-1)S+2N ---- 15
LDMIA Rb!,{Rlist} nS+1N+1I ---- 15
Form|_15|_14|_13|_12|_11|_10|_9_|_8_|_7_|_6_|_5_|_4_|_3_|_2_|_1_|_0_|
__1_|_0___0___0_|__Op___|_______Offset______|____Rs_____|____Rd_____|Shifted
__2_|_0___0___0___1___1_|_I,_Op_|___Rn/nn___|____Rs_____|____Rd_____|ADD/SUB
__3_|_0___0___1_|__Op___|____Rd_____|_____________Offset____________|Immedi.
__4_|_0___1___0___0___0___0_|______Op_______|____Rs_____|____Rd_____|AluOp
__5_|_0___1___0___0___0___1_|__Op___|Hd_|Hs_|____Rs_____|____Rd_____|HiReg/BX
__6_|_0___1___0___0___1_|____Rd_____|_____________Word______________|LDR PC
__7_|_0___1___0___1_|__Op___|_0_|___Ro______|____Rb_____|____Rd_____|LDR/STR
__8_|_0___1___0___1_|__Op___|_1_|___Ro______|____Rb_____|____Rd_____|""H/SB/SH
__9_|_0___1___1_|__Op___|_______Offset______|____Rb_____|____Rd_____|""{B}
_10_|_1___0___0___0_|Op_|_______Offset______|____Rb_____|____Rd_____|""H
_11_|_1___0___0___1_|Op_|____Rd_____|_____________Word______________|"" SP
_12_|_1___0___1___0_|Op_|____Rd_____|_____________Word______________|ADD PC/SP
_13_|_1___0___1___1___0___0___0___0_|_S_|___________Word____________|ADD SP,nn
_14_|_1___0___1___1_|Op_|_1___0_|_R_|____________Rlist______________|PUSH/POP
_17_|_1___0___1___1___1___1___1___0_|___________User_Data___________|ARM9:BKPT
_X__|_1___0___1___1___ .............................. |ARM11...
0110 011 Change Processor State CPS on page B4-2
0001 xxx Compare and Branch on Zero CBNZ, CBZ on page A6-52
1011 xxx Compare and Branch on Nonzero CBNZ, CBZ on page A6-52
0011 xxx Compare and Branch on Zero CBNZ, CBZ on page A6-52
1001 xxx Compare and Branch on Nonzero CBNZ, CBZ on page A6-52
0010 00x Signed Extend Halfword SXTH on page A6-256
0010 01x Signed Extend Byte SXTB on page A6-254
0010 10x Unsigned Extend Halfword UXTH on page A6-274
0010 11x Unsigned Extend Byte UXTB on page A6-272
1010 00x Byte-Reverse Word REV on page A6-191
1010 01x Byte-Reverse Packed Halfword REV16 on page A6-192
1010 11x Byte-Reverse Signed Halfword REVSH on page A6-193
1111 xxx If-Then, and hints If-Then, and hints on page A5-11
_15_|_1___1___0___0_|Op_|____Rb_____|____________Rlist______________|STM/LDM
_16_|_1___1___0___1_|_____Cond______|_________Signed_Offset_________|B{cond}
_U__|_1___1___0___1___1___1___1___0_|_____________var_______________|UndefARM9
_17_|_1___1___0___1___1___1___1___1_|___________User_Data___________|SWI
_18_|_1___1___1___0___0_|________________Offset_____________________|B
_19_|_1___1___1___0___1_|_________________________var___________|_0_|BLX.ARM9
_U__|_1___1___1___0___1_|_________________________var___________|_1_|UndefARM9
_19_|_1___1___1___1_|_H_|______________Offset_Low/High______________|BL,BLX
THUMB.2: add/subtract
15-11 Must be 00011b for 'add/subtract' instructions
10-9 Opcode (0-3)
0: ADD{S} Rd,Rs,Rn ;add register Rd=Rs+Rn
1: SUB{S} Rd,Rs,Rn ;subtract register Rd=Rs-Rn
2: ADD{S} Rd,Rs,#nn ;add immediate Rd=Rs+nn
3: SUB{S} Rd,Rs,#nn ;subtract immediate Rd=Rs-nn
Pseudo/alias opcode with Imm=0:
2: MOV{ADDS} Rd,Rs ;move (affects cpsr) Rd=Rs+0
8-6 For Register Operand:
Rn - Register Operand (R0..R7)
For Immediate Operand:
nn - Immediate Value (0-7)
5-3 Rs - Source register (R0..R7)
2-0 Rd - Destination register (R0..R7)
Return: Rd contains result, N,Z,C,V affected (including MOV).
Execution Time: 1S
BX and ADD/MOV PC
See also THUMB.5: BX Rs, and ADD/MOV PC,Rs.
SETEND (ARMv6)
15-4 Must be 101101100101b
3 Opcode:
0: SETEND LE ;clear CPSR.E bit (little endian data access)
1: SETEND BE ;set CPSR.E bit (big endian data access)
2-0 Should be 000b
CPY
15-8 Must be 01000110b for CPY Rd,Rm
7 MSB of Rd
6 MSB of Rm
5-3 Rm Source Register
2-0 Rd Destination Register
Move without changing flags. It's called CPY because THUMB syntax didn't
distinguish between MOV and MOVS (until UAL syntax was invented, which makes
the name CPY irrelevant).
CPY is officially supported in "T variants of ARMv6 and above" (in practice, it
should work on ARMv4T and up, but wasn't officially documented until ARMv6).
A22i Directives
org adr assume following code from this address on
.gba indicate GBA program
.nds indicate NDS program
.dsi indicate DSi program
.firm3ds indicate 3DS program (.firm format)
.fix fix GBA/NDS/DSi header checksum
.ereader_create_bmp create GBA e-Reader dotcode .BMP file(s) (bitmaps)
.ereader_create_raw create GBA e-Reader dotcode .RAW file (useless)
.ereader_create_bin create GBA e-Reader dotcode .BIN file (smallest)
.ereader_japan_plus japanese/plus (default is non-japanese)
.ereader_japan_original japanese/original (with Z80-stub for GBA-code)
.title 'Txt' defines a title (used for e-Reader dotcodes)
.teak select TeakLiteII instruction set (for DSi DSP)
.xtensa select Xtensa instruction set (for DSi Atheros Wifi)
.rl78 select RL78 instruction set (for 3DS MCU)
.norewrite do not delete existing output file (keep following data in file)
.data? following defines RAM data structure (assembled to nowhere)
.code following is normal ROM code/data (assembled to ROM image)
.include includes specified source code file (no nesting/error handling)
.import imports specified binary file (optional parameters: ,begin,len)
.radix nn changes default numeric format (nn=2,8,10,16 = bin/oct/dec/hex)
.errif expr generates an error message if expression is nonzero
.if expr assembles following code only if expression is nonzero
.else invert previous .if condition
.endif terminate .if/.ifdef/.ifndef
.ifdef sym assemble following only if symbol is defined
.ifndef sym assemble following only if symbol is not defined
.align nn aligns to an address divisible-by-nn, inserts 00's
.msg defines a no$gba debugmessage string, such like .msg 'Init Okay'
.brk defines a no$gba source code break opcode
l equ n l=n
l: [cmd] l=$ (global label)
@@l: [cmd] @@l=$ (local label, all locals are reset at next global label)
end end of source code
db ... define 8bit data (bytes)
dw ... define 16bit data (halfwords)
dd ... define 32bit data (words)
defs nn define nn bytes space (zero-filled)
;... defines a comment (ignored by the assembler)
// alias for CRLF, eg. allows <db 'Text',0 // dw addr> in one line
The ICEbreaker aka EmbeddedICE module may be found in ARM7TDMI and possibly
also in other ARM processors. The main functionality of the module relies on
external inputs (BREAKPT signal, etc.) being controlled by external debugging
hardware. At software side, ICEbreaker contains a Debug Communications Channel
(again to access external hardware), which can be accessed as coprocessor 14
via following opcodes:
MRC{cond} P14,0,Rd,C0,C0,0 ;Read Debug Comms Control Register
MRC{cond} P14,0,Rd,C1,C0,0 ;Read Debug Comms Data Register
MRC{cond} P14,0,Rd,C2,C0,0 ;Read Debug Comms Status Register
MCR{cond} P14,0,Rd,C1,C0,0 ;Write Debug Comms Data Register
MCR{cond} P14,0,Rd,C2,C0,0 ;Write Debug Comms Status Register
The Control register consists of Bit31-28=ICEbreaker version (0001b for
ARM7TDMI), Bit27-2=Not specified, Bit0/Bit1=Data Read/Write Status Flags.
The NDS7 and GBA allow to access CP14 (unlike as for CP0..CP13 & CP15, access
to CP14 doesn't generate any exceptions), however, the ICEbreaker module
appears to be disabled (or completely unimplemented), any reads from
P14,0,Rd,C0,C0,0 through P14,7,Rd,C15,C15,7 are simply returning the prefetched
opcode value from [$+8]. ICEbreaker might be eventually used and enabled in
Nintendo's hardware debuggers, although external breakpoints are reportedly
implemented via /FIQ input rather than via ICEbreaker hardware.
The NDS9 doesn't include a CP14 unit (or it is fully disabled), any attempts to
access it are causing invalid instruction exceptions.
CP15
In many ARM CPUs, particulary such with memory control facilities, coprocessor
number 15 (CP15) is used as built-in System Control Coprocessor.
CPUs without memory control functions typically don't include a CP15 at all, in
that case even an attempt to read the Main ID register will cause an Undefined
Instruction exception.
CP15 Opcodes
CP15 can be accessed via MCR and MRC opcodes, with Pn=P15, and <cpopc>=0.
MCR{cond} P15,<cpopc>,Rd,Cn,Cm,<cp> ;move from ARM to CP15
MRC{cond} P15,<cpopc>,Rd,Cn,Cm,<cp> ;move from CP15 to ARM
Rd can be any ARM register in range R0-R14, R15 should not be used with P15.
<cpopc>,Cn,Cm,<cp> are used to select a CP15 register, eg. 0,C0,C0,0 = Main ID
Register.
Other coprocessor opcodes (CDP, LDC, STC) cannot be used with P15.
Data/Unified Registers
Some Cache/PU/TCM registers are declared as "Data/Unified".
That registers are used for Data accesses in case that the CPU contains
separate Data and Instruction registers, otherwise the registers are used for
both (unified) Data and Instruction accesses.
The MMU allows to assign virtual memory addresses, and to disable the data
cache in sensitive memory areas (eg. I/O area, and memory that is shared for
ARM9/ARM11). Additionally, it can trigger page fault exceptions (eg. for error
handling or memory mapped files).
MMU Tables
1st Level table (size 4000h) divides 4Gbyte address space into 1Mbyte sections
2nd Level table(s) (size 400h each) divides a 1Mbyte section into 4Kbyte pages
________________________________ ARMv6 Tables ________________________________
This is an older format, similar to the newer ARMv6 tables, but without the
"n,S,A,X" bits, and, instead, somehow allowing to divide 4K pages into smaller
1K snippets (with separate access privileges in AP0/AP1/AP2/AP3 bits, but
without TEX bits).
Background Region
Additionally, any memory areas outside of the eight Protection Regions are
handled as Background Region, this region has neither Read nor Write access.
Cache/Write-buffer should not be enabled for the whole 4GB memory area,
high-speed TCM memory doesn't require caching, and caching would have fatal
results on I/O ports. So, cache can be used only in combination with the
Protection Unit, which allows to enable/disable caching in specified regions.
Note
ARMv5 instruction set supports a Cache Prepare for Load opcode (PLD), see
--> ARM Opcodes: Memory: Single Data Transfer (LDR, STR, PLD)
Note
Data cache always requires PU/MMU. Code cache requires PU/MMU on ARM9, but also
works without PU/MMU on ARM11.
TCM and PU
TCM can be used without Protection Unit.
When the protection unit is enabled, TCM is controlled by the PU just like
normal memory, the PU should provide R/W Access Permission for TCM regions;
cache and write-buffer are not required for high-speed TCM (so both should be
disabled for TCM regions).
<cpopc>
Unlike for all other CP15 registers, the <cpopc> operand of the MRC/MCR opcodes
isn't always zero for below registers, so below registers are using
"cpopc,Cn,Cm,op2" notation (instead of the normal "Cn,Cm,op2" notation).
Built-In-Self-Test (BIST)
Allows to test internal memory (ie. TCM, Cache Memory, and Cache TAGs). The
tests are filling (and verifying) the selected memory region thrice (once with
the fillvalue, then with the inverted fillvalue, and then again with the
fillvalue). The BIST functions are intended for diagnostics purposes only, not
for use in normal program code (ARM doesn't guarantee future processors to have
backwards compatible BIST functions).
0,C15,C0,1 - BIST TAG Control Register (R/W)
1,C15,C0,1 - BIST TCM Control Register (R/W)
2,C15,C0,1 - BIST Cache Control Register (R/W)
0-15 Data Control (see below)
16-31 Instruction Control (see below)
The above 16bit control values are:
0 Start bit (Write: 1=Start) (Read: 1=Busy)
1 Pause bit (1=Pause)
2 Enable bit (1=Enable)
3 Fail Flag (1=Error) (Read Only)
4 Complete Flag (1=Ready) (Read Only)
5-15 Size (2^(N+2) bytes) (min=N=1=8bytes, max=N=24=64MB)
Size and Pause are not supported in all implementations.
Caution: While and as long as the Enable bit is set, the corresponding memory
region(s) will be disabled. Eg. when testing <either> DTCM <and/or> ITCM,
<both> DTCM <and> ITCM are forcefully disabled in C1,C0,0 (Control Register),
after the test the software must first clear the BIST enable bit, and then
restore DTCM/ITCM bits in C1,C0,0. And of course, the content of the tested
memory region must be restored when needed.
ARM9:
Q{D}ADD/SUB 1S+Interlock.
CLZ 1S.
LDR 1S+1N+1L
LDRB,LDRH,LDRmis 1S+1N+2L
LDR PC ...
STR 1S+1N (not 2N, and both in parallel)
Execution Time: 1S+Interlock (SMULxy,SMLAxy,SMULWx,SMLAWx)
Execution Time: 1S+1I+Interlock (SMLALxy)
ARM11:
Observe that Branch Prediction (enabled in CP15 Control register) can affect
timings for conditional jumps (and presumably non-conditional ones, too).
Without prediction: A waitloop made of "SUBS+BNE" takes 4 clks per loop cycle
With prediction: A waitloop made of "SUBS+BNE" takes 2.5 clks per loop cycle
(apparently the prediction assumes 75% of the jumps to be taken)
Whereas,
n = number of words transferred
b = number of cycles spent in coprocessor busy-wait loop
m = depends on most significant byte(s) of multiplier operand
Above 'trap' is meant to be the execution time for exceptions. And '{cond}
false' is meant to be the execution time for conditional instructions which
haven't been actually executed because the condition has been false.
The separate meaning of the N,S,I,C cycles is:
N - Non-sequential cycle
Requests a transfer to/from an address which is NOT related to the address used
in the previous cycle. (Called 1st Access in GBA language).
The execution time for 1N is 1 clock cycle (plus non-sequential access
waitstates).
S - Sequential cycle
Requests a transfer to/from an address which is located directly after the
address used in the previous cycle. Ie. for 16bit or 32bit accesses at
incrementing addresses, the first access is Non-sequential, the following
accesses are sequential. (Called 2nd Access in GBA language).
The execution time for 1S is 1 clock cycle (plus sequential access waitstates).
I - Internal Cycle
CPU is just too busy, not even requesting a memory transfer for now.
The execution time for 1I is 1 clock cycle (without any waitstates).
C - Coprocessor Cycle
The CPU uses the data bus to communicate with the coprocessor (if any), but no
memory transfers are requested.
Memory Waitstates
Ideally, memory may be accessed free of waitstates (1N and 1S are then equal to
1 clock cycle each). However, a memory system may generate waitstates for
several reasons: The memory may be just too slow. Memory is currently accessed
by DMA, eg. sound, video, memory transfers, etc. Or when data is squeezed
through a 16bit data bus (in that special case, 32bit access may have more
waitstates than 8bit and 16bit accesses). Also, the memory system may separate
between S and N cycles (if so, S cycles would be typically faster than N
cycles).
Version Numbers
ARM CPUs are distributed by name ARM#, and are described as ARMv# in
specifications, whereas "#" is NOT the same than "v#", for example, ARM7TDMI is
ARMv4TM. That is so confusing, that ARM didn't even attempt to clarify the
relationship between the various "#" and "v#" values.
Version Variants
Suffixes like "M" (long multiply), "T" (Thumb support), "E" (Enhanced DSP)
indicate presence of special features, additionally to the standard instruction
set of a given version, or, when preceded by an "x", indicate the absence of
that features.
ARMv2 and up
MUL,MLA
CDP,LDC,MCR,MRC,STC
SWP/SWPB (ARMv2a and up only)
Two new FIQ registers
ARMv3 and up
MRS,MSR opcodes (instead CMP/CMN/TST/TEQ{P} opcodes)
CPSR,SPSR registers (instead PSR bits in R15)
Removed never condition, cond=NV no longer valid
32bit addressing (instead 26bit addressing in older versions)
26bit addressing backwards comptibility mode (except v3G)
Abt and Und modes (instead handling aborts/undefined in Svc mode)
SMLAL,SMULL,UMLAL,UMULL (optionally, INCLUDED in v3M, EXCLUDED in v4xM/v5xM)
ARMv6K aka "ARM11 MPCore" (see ARM DDI 0360F) (used in 3DS)
Unknown how this is abbreviated (ARMv6-M would be something else: Cortex-M).
The MPCore processor provides support for extensions to ARMv6 that include:
- LDREX/STREX{B|H|D} for 8bit/16bit/64bit and CLREX
- HINT (TrueNOP, YIELD, WFI, WFE, SEV)
- Architectural remap registers.
- Revised use of TEX remap bits. The ARMv6 MMU page table descriptors use a
large number of bits to describe all of the options for inner and outer
cachability. In reality, no application requires all of these options
simultaneously. Therefore it is possible to use the TEX remap mechanism to
configure the MP11 CPUs to support only a small number of options. This implies
a level of indirection in the page table mappings.
The TEX CB encoding table provides two OS managed page table bits. For binary
compatibility with existing ARMv6 ports of OSs, this gives a separate mode of
operation of the MMU. This is called the TEX Remap configuration and is
controlled by bit [28] TR in CP15 Register 1.
- Revised use of AP bits. In the MP11 CPUs the APX and AP[1:0] encoding b111 is
Privileged or User mode read-only access. AP[0] indicates an abort type, Access
Bit fault, when CP15 c1[29] is 1.
For more information see the ARM Architecture Reference Manual.
ARMv6Z
ARMv6K with Security Extensions. Aka TrustZone, see Processor Feature Register
1.
Some details that I have treated as meaningless for GBA programming aren't
included - such like Big Endian format, and Virtual Memory data aborts, and
most of the chapters listed below.
Have a look at the complete data sheet (URL see below) for more detailed
verbose information about ARM7TDMI instructions. That document also includes:
- Signal Description
Pins of the original CPU, probably other for GBA.
- Memory Interface
Optional virtual memory circuits, etc. not for GBA.
- Coprocessor Interface
As far as I know, none such in GBA.
- Debug Interface
For external hardware-based debugging.
- ICEBreaker Module
For external hardware-based debugging also.
- Instruction Cycle Operations
Detailed: What happens during each cycle of each instruction.
- DC Parameters (Power supply)
- AC Parameters (Signal timings)
The official ARM7TDMI data sheet can be downloaded from ARMs webpage,
http://www.arm.com/Documentation/UserMans/PDF/ARM7TDMI.html
Be prepared for bloated PDF Format, approx 1.3 MB, about 200 pages.
BIOS Functions
--------------
The BIOS includes several System Call Functions which can be accessed by SWI
instructions. Incoming parameters are usually passed through registers
R0,R1,R2,R3. Outgoing registers R0,R1,R3 are typically containing either
garbage, or return value(s). All other registers (R2,R4-R14) are kept
unchanged.
Caution
When invoking SWIs from inside of ARM state specify SWI NN*10000h, instead of
SWI NN as in THUMB state.
Overview
--> BIOS Function Summary
--> BIOS Differences between GBA and NDS functions
3DS bootroms
--> BIOS 3DS Exception Vectors
Div
DivArm
Sqrt
ArcTan
ArcTan2
BgAffineSet
ObjAffineSet
For both Bg- and ObjAffineSet, Rotation angles are specified as 0-FFFFh
(covering a range of 360 degrees), however, the GBA BIOS recurses only the
upper 8bit; the lower 8bit may contain a fractional portion, but it is ignored
by the BIOS.
BitUnPack
Diff8bitUnFilter
HuffUnComp
LZ77UnComp
RLUnComp
CpuFastSet
CpuSet
Note: On GBA, NDS7 and DSi7, these two functions will silently reject to do
anything if the source start or end addresses are reaching into the BIOS area.
The NDS9 and DSi9 don't have such read-proctections.
Halt
IntrWait
VBlankIntrWait
Stop/Sleep
CustomHalt
SoftReset
RegisterRamReset
HardReset
GetBiosChecksum
WaitByLoop
GetCRC16
IsDebugger
GetSineTable
GetPitchTable
GetVolumeTable
CustomPost
GetBootProcs
MultiBoot
Nintendo DS
The GBA multiboot function requires a link port, and so, works on GBA and GBA
SP only. The Nintendo DS in GBA mode does include the multiboot BIOS function,
but it won't be of any use as the DS doesn't have a link port.
MidiKey2Freq
SoundBias
SoundChannelClear
SoundDriverInit
SoundDriverMain
SoundDriverMode
SoundDriverVSync
SoundDriverVSyncOff
SoundDriverVSyncOn
SoundWhatever0..4
SoundGetJumpList
SHA1_Default_Callback(struct,src,len)
for j=1 to len/40h
a=[struct+0], b=[struct+4], c=[struct+8], d=[struct+0Ch], e=[struct+10h]
for i=0 to 79
if i=0..15 then w[i] = bswap([src]), src=src+4
if i=16..79 then w[i] = (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) rol 1
if i=0..19 then f=5A827999h + e + (d xor (b and (c xor d)))
if i=20..39 then f=6ED9EBA1h + e + (b xor c xor d)
if i=40..59 then f=8F1BBCDCh + e + ((b and c) or (d and (b or c)))
if i=60..79 then f=CA62C1D6h + e + (b xor c xor d)
e=d, d=c, c=(b ror 2), b=a, a=f + (a rol 5) + w[i]
[struct+0]=[struct+0]+a, [struct+4]=[struct+4]+b, [struct+8]=[struct+8]+c
[struct+0Ch]=[struct+0Ch]+d, [struct+10h]=[struct+10h]+e
SHA1_Init_Update_Finish_HMAC(dst,key,src,srclen)
if len(key)>40h then key=SHA1(key) ;convert LONG keys to 14h-bytes length
if len(key)<40h then zero-pad key to 40h-bytes length
for i=0 to 3Fh, [inner_key+i]=[key+i] xor 36h ;\
[struct+60h]=00000000h ;
SHA1_Init(struct) ; compute 1st SHA1
SHA1_Update(struct,inner_key,40h) ; across inner key and data
SHA1_Update(struct,src,srclen) ;
SHA1_Finish(first_sha1,struct) ;/
for i=0 to 3Fh, [outer_key+i]=[key+i] xor 5Ch ;\
[struct+60h]=00000000h ;
SHA1_Init(struct) ; compute final SHA1
SHA1_Update(struct,outer_key,40h) ; across outer key and 1st SHA1
SHA1_Update(struct,first_sha1,14h) ;
SHA1_Finish(dst,struct) ;/
RSA is important because the DSi cartridge header and system files do contain
RSA signatures. Which makes it impossible to create unlicensed software
(without knowing Nintendo's private key).
--> BIOS RSA Basics
--> BIOS RSA Pseudo Code
Unencrypted Signatures
Emulators can hook the RSA BIOS functions to copy unencrypted signatures as-is
(instead of trying to decrypt them). That allows to create "authentic" files
that are fully compatible with the DSi firmware, and which would be actually
working on real hardware (when knowing the private key).
Unencrypted 80h-byte signatures should be stored in following format (as
defined in RFC 2313):
00h 1 "00" Leading zero (00h)
01h 1 "BT" Block type (always 01h on DSi)
02h 8+n "PS" Padding (FFh-filled, min 8 bytes, usually 69h bytes on DSi)
0Ah+n 1 "00" Padding end (00h)
0Bh+n 75h-n "D" Data (max 75h bytes, usually a 14h-byte SHA1 value on DSi)
If the hooked BIOS function sees a RSA source to contain "00h, 01h, at least
eight FFh, followed by 00h", then it could treat it as unencrypted data (it's
nearly impossible that an encrypted signature could contain those values).
Key.Bit0
The DSi BIOS contains two different RSA core modes (either one of them is used,
depending on whether BIT0 of the FIRST BYTE of the "key" is set or cleared).
The purpose & difference between those two modes is unknown. Also, dunno if
that BIT0 thing is something common in the RSA world?
RSA Basics
The RSA formulas are quite simple: Applying an exponent and modulus to the
source data. There are two formulas used for encryption/decryption. The first
formula requires only the Public Key (and an exponent, which is usually some
fixed constant; on the DSi it's always 10001h aka 65537 decimal). The second
formula is almost same, but requires the Private Key instead of the constant
exponent (and also requires the Public Key as modulus):
Public Key formula: dest = src^10001h mod pubkey
Private Key formula: dest = src^prvkey mod pubkey
That formulas can be used for encrypting secret messages, as so:
Recipient's Public Key --> Encrypt a message
Recipient's Private Key --> Decrypt a message
Or, using the formulas the other way around, to create digital signatures:
Sender's Private Key --> Encrypt/create a signature
Sender's Public Key --> Decrypt/verify a signature
The overall idea is that only the owner of the Private Key can decrypt
messages, or create signatures. The Public Key can be shared freely, so that
everybody can encrypt messages, or verify signatures.
RSA Padding
RSA can be weak if the message is a small number (especially very small values
like "0" or "1" obviously wouldn't work well with the "msg^exp" maths; other
small values can be also weak, eg. with the common/small public exponent
10001h). To avoid that problem, the MSBs of the message should be padded with
nonzero bytes, typically as so (as defined in RFC 2313):
00h 1 "00" Leading zero (00h)
01h 1 "BT" Block type (always 01h on DSi)
02h 8+n "PS" Padding (FFh-filled, min 8 bytes, usually 69h bytes on DSi)
0Ah+n 1 "00" Padding end (00h)
0Bh+n 75h-n "D" Data (max 75h bytes, usually a 14h-byte SHA1 value on DSi)
That, for 80h-byte messages. For other sizes replace "75h" by "F5h, 1F5h, etc."
rsa_mpi_mul_mod(dst,src):
rsa_mpi_mul(bigbuf,dst,src) ;-multiply
rsa_mpi_mod(bigbuf,pubkey) ;-modulus
[dst]=[bigbuf+0..rsa_number_size-1] ;-copy to dst
return
rsa_mpi_mul(dst,src1,src2): ;[dst]=[src1]*[src2]
[dst+0]=0, oldmsw=0 ;-init first word and oldmsw
for i=0 to rsa_number_size-4 step 4 ;\
call @@inner_loop ; compute LSWs of destination
src2=src2+4 ;
next i ;/
src2=src2-4
for i=rsa_number_size-8 to 0 step -4 ;\
src1=src1+4 ; compute MSWs of destination
call @@inner_loop ;
next i ;/
return
;---
@@inner_loop:
[dst+4]=oldmsw, oldmsw=0
for j=0 to i step 4
msw:lsw = [src1+j]*[src2-j]
[dst+0]=[dst+0]+lsw
[dst+4]=[dst+4]+msw+cy
oldmsw=oldmsw+cy
next j
dst=dst+4
ret
rsa_mpi_mulsub(dst,src,fac): ;[dst]=[dst]-[src]*fac
oldborrow=0, oldmsw=0 ;\
for i=0 to rsa_number_size-4 step 4 ; process
msw:lsw = [src+i]*fac, lsw=lsw+oldmsw, oldmsw=msw+carry ; rsa_number_size
[dst+i]=[dst+i]-lsw-oldborrow, oldborrow=borrow ; bytes, plus...
next i ;/
[dst+rsa_number_size]=[dst+rsa_number_size]-oldmsw-oldborrow ;-one extra word
return borrow ;(unlike "rsa_embedded" which returns INVERTED borrow)
Exception Vectors
The 3DS bootroms do mostly contain bootcode, unlike GBA/NDS without any public
functions, apart from some small stubs for redirecting the exception vectors to
RAM locations:
08000000h 8 arm9_irq ldr r15,[$+4] // dd vector ;\
08000008h 8 arm9_fiq ldr r15,[$+4] // dd vector ;
08000010h 8 arm9_svc ldr r15,[$+4] // dd vector ; ARM9
08000018h 8 arm9_undef ldr r15,[$+4] // dd vector ; exceptions
08000020h 8 arm9_prefetch_abort ldr r15,[$+4] // dd vector ;
08000028h 8 arm9_data_abort ldr r15,[$+4] // dd vector ;/
1FFFFFA0h 8 arm11_irq ldr r15,[$+4] // dd vector ;\
1FFFFFA8h 8 arm11_fiq ldr r15,[$+4] // dd vector ;
1FFFFFB0h 8 arm11_svc ldr r15,[$+4] // dd vector ; ARM11
1FFFFFB8h 8 arm11_undef ldr r15,[$+4] // dd vector ; exceptions
1FFFFFC0h 8 arm11_prefetch_abort ldr r15,[$+4] // dd vector ;
1FFFFFC8h 8 arm11_data_abort ldr r15,[$+4] // dd vector ;/
1FFFFFDCh 4 arm11_core1_entrypoint dd vector ;-CPU1 entry
(OVERLAY) 4 arm11_core23_entry dd vector ;-CPU2/3
The ARM11 exception vectors are shared for all CPU cores (so one must manually
redirect them to core specific handlers).
Alternately, instead of using the above RAM vectors, one could use ARM11
virtual memory or ARM9 ITCM for custom vectors.
Moreover, the CFG11_BOOTROM_OVERLAY_CNT/VAL feature allows to redirect ARM11
vectors on New3DS (mainly intended for booting CPU2/CPU3 cores).
SWI/SVC Functions
There aren't any built-in functions in the bootroms, however, SVC opcodes can
be used to obtain entrypoints to OS functions. That is, once when the OS is
booted (FIRM files are started without any OS functions, but .code files can
use OS functions).
Note: ARM has renamed SWI opcodes to SVC opcodes.
Below contains info about RAM contents at cartridge boot time (as initialized
by the BIOS/Firmware), plus info about RAM locations used by IRQ handlers and
SWI functions.
BIOS Dumping
------------
BIOSes
GBA BIOS 16K (fully dumpable, CRC32=81977335 on GBA with [3F0Ch]=00h)
GBA BIOS 16K (fully dumpable, CRC32=A6473709 on NDS/3DS with [3F0Ch]=01h)
NDS7 BIOS 16K (fully dumpable, CRC32=1280F0D5)
NDS9 BIOS 4K (fully dumpable, CRC32=2AB23573)
DSi7 BIOS 64K (about 41K dumpable) (new: fully dumped now)
DSi9 BIOS 64K (about 41K dumpable)
3DS9 BIOS 64K (fully dumpable)
3DS11 BIOS 64K (fully dumpable)
DSiWifi BIOS 80K on older DSi (fully dumpable)
DSiWifi BIOS Unknown size on newer DSi (fully dumpable)
3DSWifi BIOS Unknown size on 3DS (fully dumpable)
GBA BIOS
Contains SWI Functions and Bootcode (for starting cartridges, or booting via
Serial Port). The GBA BIOS can be read only by opcodes executed in BIOS area,
for example, via the MidiKey2Freq function (most other SWI Functions (like
CpuSet) are refusing source addresses within BIOS area).
NDS BIOSes
Contains SWI Functions and Bootcode (for booting from SPI Bus Firmware FLASH
memory). The NDS9 BIOS can be dumped without restrictions (eg. via CpuSet, or
via LDR opcodes in RAM). The NDS7 BIOS has same restrictions as GBA, ie.
reading works only by BIOS opcodes, and not by functions like CpuSet. The
GetCRC16 functions does work though (at least for memory at 1204h..3FFFh). As
an additional obstacle, memory at 0000h..1203h can be dumped only by opcodes
within 0000h..1203h (that memory does mainly contain data, but some of the data
values can serve as THUMB LDR opcodes). For details see:
--> DS Memory Control - BIOS
Note: DSi consoles are containing a copy of the NDS BIOSes, but with BIOSPROT
set to 0020h (even when running in NDS mode), so the first 20h bytes of the
DSi's NDS7 BIOS aren't dumpable (except via tracing, see below), that 20h bytes
should be just same as on original NDS7 though.
DSi BIOSes - Upper 32K-halves (Bootcode, for booting from eMMC memory)
The upper 32K of the DSi9 and DSi7 BIOSes are locked at some point during
booting, and there's no known way to dump them directly. However, portions of
that memory are relocated to RAM/TCM before locking, and that relocated copies
can be dumped.
On a DSi, the following DSi ROM data can be dumped (originally done via Main
Memory hacks, ie. with complex external hardware soldered to the mainboard, but
it's now also possible via Unlaunch.dsi exploit):
ROM:FFFF87F4h / TCM:1FFC400h (400h) (C3 02 93 DE ..) RSA keys (8x80h)
ROM:FFFF9920h / TCM:1FFC800h (80h) (30 33 26 D5 ..) Whatever
ROM:FFFF99A0h / TCM:1FFC894h (1048h) (99 D5 20 5F ..) Blowfish/NDS-mode
ROM:FFFFA9E8h / TCM:1FFD8DCh (1048h) (D8 18 FA BF ..) Blowfish/unused?
ROM:00008188h / RAM:3FFC400h (200h) (CA 13 31 79 ..) Whatever, 32x10h AES?
ROM:0000B5D8h / RAM:3FFC600h (40h) (AF 1B F5 16 ..) Whatever, "common key"?
ROM:0000C6D0h / RAM:3FFC654h (1048h) (59 AA 56 8E ..) Blowfish/DSi-mode
ROM:0000D718h / RAM:3FFD69Ch (1048h) (54 86 13 3B ..) Blowfish/unused?
On a 3DS, the following "DSi ROM data" can be dumped from the 2470h-byte DSi
key area in 3DS memory at ARM9 ITCM 01FFD000h..01FFF46F (via 3DS exploits that
are capable of executing code on ARM9 side):
ROM:FFFF87F4h / 3DS:01FFD000h 200h RSA keys 0..3 (4x80h)
ROM:00008308h / 3DS:01FFD200h 80h some AES keys
ROM:FFFF9920h / 3DS:01FFD280h 80h whatever
ROM:0000B5D8h / 3DS:01FFD300h 40h AES keys and values (common etc)
ROM:? / 3DS:01FFD340h A0h misc "Nintendo" string etc.
ROM:0000C6D0h / 3DS:01FFD3E0h 1048h Blowfish for DSi-mode
ROM:FFFF99A0h / 3DS:01FFE428h 1048h Blowfish for DS-mode
The 3DS does have only half of the DSi keys (the extra keys might be used for
DSi debug version, but aren't needed for normal DSi software).
The 40h-byte area for ROM:0000B5D8h can be fully dumped from 3DS ITCM, the same
vales should also exist in DSi ITCM, but the DSi zerofills a 10h-byte fraction
of that area after initialization, and it doesn't seem be possible to read that
values via Main Memory hacks (most of that erased values can be found in AES
keyslots though).
The A0h-byte area is found only in 3DS ITCM, it should also exist somewhere in
DSi ROM, but isn't relocated to DSi ITCM (however, the relevant values can be
found in AES keyslots, eg. the "Nintendo" string).
DSiWifi BIOS
The Wifi BIOS can be dumped by using the WINDOW_DATA register via SDIO CMD53.
External Connectors
-------------------
External Connectors
--> AUX GBA Game Pak Bus
--> AUX DS Game Card Slot
--> AUX Link Port
--> AUX Sound/Headphone Socket and Battery/Power Supply
--> AUX DSi SD/MMC Pin-Outs
The DS does also have a 32pin cartridge slot, that slot is used to run GBA
carts in GBA mode, it can be also used as expansion port in DS mode.
Normal Connection
Just connect the plugs to the two GBAs and leave the Middle Socket
disconnected, in this mode both GBAs may behave as master or slave, regardless
of whether using big or small plugs.
The GBA is (NOT ???) able to communicate in Normal mode with MultiPlay cables
which do not have crossed SI/SO lines.
Multi-Play Connection
Connect two GBAs as normal, for each further GBAs connect an additional cable
to the Middle socket of the first (or further) cable(s), up to four GBAs may be
connected by using up to three cables.
The GBA which is connected to a Small Plug is master, the slaves are all
connected to Large Plugs. (Only small plugs fit into the Middle Socket, so it's
not possible to mess up something here).
Multi-Boot Connection
MultiBoot (SingleGamepak) is typically using Multi-Play communication, in this
case it is important that the Small plug is connected to the master/sender (ie.
to the GBA that contains the cartridge).
GBA, GBA-Micro, NDS, and NDS-Lite: Stereo Sound Connector (3.5mm, female)
Tip Audio Left ___ ___ _____.-----------.
Middle Audio Right (___|___|_____| |
Base Ground L R GND '-----------'
The NDS socket doesn't fully match regular 3.5mm plugs, one needs to cut-off a
portion of the DS case to be able to fully insert the plug, which still
requires a lot of pressure, furthermore, when fully inserted, left/right become
shortcut to mono, so one needs to pull-back the plug a bit to gain stereo
output.
SD/MMC Pin-Outs
MMC MMCplus SD miniSD microSD SPI-Mode 1-bit-Bus 4-bit/8bit-Bus
1 1 1 1 2 /CS CardDetect Data3
2 2 2 2 3 DataIn CMD/REPLY CMD/REPLY
3 3 3 3 -- GND GND GND
4 4 4 4 4 VDD VDD VDD
5 5 5 5 5 CLK CLK CLK
6 6 6 6 6 GND GND GND
7 7 7 7 7 DataOut Data Data0
-- 8 8 8 8 /IRQ (SDIO) /IRQ (SDIO) Data1 or /IRQ (SDIO)
-- 9 9 9 1 NC NC Data2
-- 10 -- -- -- NC NC Data4 ;\
-- 11 -- -- -- NC NC Data5 ; MMCplus
-- 12 -- -- -- NC NC Data6 ; 8bit
-- 13 -- -- -- NC NC Data7 ;/
-- -- -- 10 -- Reserved Reserved Reserved
-- -- -- 11 -- Reserved Reserved Reserved
Moreover, the card sockets (not the cards themselves) are usually containing a
Card Detect switch, and, for SD card sockets, also a write protect switch:
-- -- CD CD CD Card Detect (senses if card is inserted)
-- --- WP -- -- Write Protect (senses position of LOCK tab)
Note that the LOCK tab on SD cards is just a small piece of plastic without any
electronics attached to it, the actual switch/sensor is located in the SD card
socket (ie. the LOCK works much like the write-protect tabs on audio tapes,
video tapes, and floppy discs).
Card detect can be an actual switch (however, some sockets are simply having
dual contacts for Pin 3 (GND), one being GND, and the other becoming GNDed when
a cartridge is inserted).
Soldering Notes
Connect CLK/CMD to the pins on right side of R113/R94 (as shown in the
drawing). Connect Data3/0/1/2 to the LOWER pins of RA4 (unlike as shown in the
drawing, ie. NOT to the upper pins), or alternately, connect them to the four
vias below of RA4. Connect GND somewhere to shielding plate, for example.
My own setup is: A 8pin ribbon cable soldered to a spare SD-to-SDmicro adapter
(used as connector for SD/MMC slots), the ribbon cable is wired to a small
circuit board, which is soldered to the shielding of the DSi's game cartridge
slot (just for mechanical stability). Next, some fragile wires are forwarded
from the circuit board to the actual mainboard pins.
Software Notes
Remove the DSi wifiboard (not absolutely required, but doing so will hang the
DSi before accessing the eMMC, which ensures that the eMMC won't be accessed
simultaneously by the DSi and PC). Switch on the DSi. Connect it to SD/MMC card
reader. Under Windows, the eMMC should show up as MMC-storagedevice in Windows
Explorer (alongsides with your HDD drives), due to the encryption it isn't
possible to access the filesystem or logical partitions of the chip. However,
the physical sectors can be accessed.
For example, using HxD hex editor: Click Extras, Open Disk, and select the MMC
(in HxD it shows up under Physical Discs: as Removeable Disk). Click Edit,
Select All, Copy. Click File, New. Then Edit, Paste. And finally File, Save As
for saving an image of the whole 240MByte FLASH chip.
I've tried accessing the eMMC on two PCs, one worked, the other didn't:
Win98 with External Card reader: Windows didn't recognize the MMC chip
Win7 with External Card reader: Okay (recognized as "unformatted" disk)
Win7 with Internal Card reader: Okay (recognized as "unformatted" disk)
For testing the Operating System/Card Reader side: Connect a normal SD card to
the card reader. If HxD is showing it as both Logical Disc and Physical Disc,
then you are fine. If it shows up as Logical Disc only, then your setup won't
work for accessing the eMMC chip.
Since Nintendo uses special screws with Y-shaped heads to seal the GBA (as well
as older 8bit gameboys), it's always a bit difficult to loosen these screws.
Using Screwdrivers
One possible method is to use a small flat screwdriver, which might work, even
though it'll most likely damage the screwdriver.
Reportedly, special Y-shaped screwdrivers for gameboys are available for sale
somewhere (probably not at your local dealer, but you might find some in the
internet or elsewhere).
AUX Mainboard
-------------
FIQ Signal
The FIQ (Fast Interrupt) signal (labeled FIQ on the mainboard) could be used as
external interrupt (or debugging break) signal.
Caution: By default, the FIQ input is directly shortcut to VDD35 (+3V or +5V
power supply voltage), this can be healed by scratching off the CL1 connection
located close to the FIQ pin (FIQ still appears to have an internal pull-up, so
that an external resistor is not required).
The GBA BIOS rejects FIQs if using normal ROM cartridge headers (or when no
cartridge is inserted). When using a FIQ-compatible ROM header, Fast Interrupts
can be then requested by pulling FIQ to ground, either by a push button, or by
remote controlled signals.
RESET Signal
The RESET signal (found on the mainboard) could be used to reset the GBA by
pulling the signal to ground for a few microseconds (or longer). The signal can
be directly used (it is not shortcut to VDD35, unlike FIQ).
Note: A reset always launches Nintendo's time-consuming and annoying boot/logo
procedure, so that it'd be recommend to avoid this "feature" when possible.
Joypad Signals
The 10 direction/button signals are each directly shortcut to ground when
pressed, and pulled up high otherwise (unlike 8bit gameboys which used a 2x4
keyboard matrix), it'd be thus easy to connect a remote keyboard, keypad,
joypad, or read-only 12bit parallel port.
DSi Upper Screen with Speakers & Cameras & LED & Microphone
Orange Ribbon Cable: Video Signals, Backlight, and Speakers
Black Ribbon Cable: Cameras and Camera LED
Shielded Orange 2pin Wire: Microphone
Shielded White 2pin Wire: Wifi PCB Antenna
LCD "LS033A1DG38R, BX16Q L0005532"
The speakers use red/black wires, which connect to the orange ribbon cable
DSi Upper Screen Area Extra Components: Speakers & Cameras & LED & Microphone
DSi Lower Case (SD Slot, L/R and VOL+/- Buttons, and screen calibration)
Whatever, not checked yet
P1 - 19pin - NDS/DSi cartridge slot (17pin slot + 2pin switch at right side)
1 GND
2 MC1_CLK
3 -
4 MC1_CS
5 MC1_RES
6 MC1_CS2
7 MC1_IREQ
8 MC1_VDD via Q6 to VDD33 (cpu signal preamplified from Q7)
9 MC1_IO0
10 MC1_IO1
11 MC1_IO2
12 MC1_IO3
13 MC1_IO4
14 MC1_IO5
15 MC1_IO6
16 MC1_IO7
17 GND
18 MC1_DET ;\switch closed when cart inserted
19 GND ;/
Shield GND
P9 - 25pin - To UPPER lcd screen (signals for both cameras, and camera led)
GND 1 2 CAM_LED
VDD42 3 4 GND
R100 RCLK 5 6 GND
GND 7 8 HSYNC
VSYNC 9 10 CAM_D5 RA7
RA7 CAM_D6 11 12 CAM_D4 RA7
CAM_RST 13 14 SCL
SDA 15 16 CAM_D7 RA7
RA6 CAM_D0 17 18 CAM_D3 RA6
RA6 CAM_D1 19 20 CAM_D2 RA6
VDD28 21 22 GND
CKI 23 24 GND
VDD18 25
A photo of the DSi mainboard (with extra text layer on vias and solderpads) can
be found at:
http://problemkaputt.de/twl-core.jpg
DSi U1 - TWL-CPU (19x19 pin grid) (352 pins, aka 19x19 minus middle 3x3 pins)
Wifi MC2 maybe MC1 SD/MMC eMMC SPI RTC IRQs
.---.---.---------------.---------------.-------.---.-------.-------.---.---.
|NC |wif|NC NC NC NC |D7 D3 IRQ CLK|D0 CLK|CLK|CS3 SCK|CS SCK|R7 |NC |
+---' | | | | | | .---' '---+
|wif wif|NC NC NC NC |D6 D2 DET CS |D1 CMD|D0 |CS2 MIS|SIO|PEN NC WIF|
| | | | | | +---+---. .---+
|wif wif|NC NC NC NC |D5 D1 PWR CS2|D2 CD |D1 |CS1 MOS|R00 R01|RTC|P09|
| '---. .---+ .---' .---' '---.---+ '---' |
|wif wif wif|NC NC |V33|D4 D0 RES|D3 WP |D3 D2 CMD| ? |P08 P07 P06 P05|
| '---+---' '-----------'-------'-----------'---+ |
|wif wif RXP TXP|GND V12 V33 GND V12 V33 G? V12 V33 GND V33|P04 P03 P02 P01|
| . . | +-----------. |
|DT3|wif wif ? |GND V33 V12 GND GND GND V33 G? GND V33 V12| ? RES NC |P00|
| '. . . . . .| | '---+
|CLK DT2 DT1 DT0|V33 GND V12 V33 GND V12 G? V12 GND GND V33|PMO VC5 PMS X |
+-----------. | '-----------. |
|V33 NC GND|CMD|V12 GND V33 GND V12 V33 GND V33 V12 V12 V33 GND GND GND|X |
| '---' .-----------. .-----------' |
|V33 NC V33 V33 GND V33 GND V33|- - - |GND GND GND GND|HP# IRQ ? GND|
+---. .---. | | | |
|B15|V33|NC |V33 V12 GND V12 V12|- - - |V12 V18 GND V12|NC NC NC GP |
| '---'---'---. | | +---------------+
|B14 B13 B12 B11|V33 GND V33 GND|- - - |V18 GND V18 GND|A1 D1 A0 D0 |
| | '-----------' | |
|B10 G15 G14 G13|GND V33 V12 GND V18 V12 V18 GND V18 V12 V18|A3 D3 A2 D2 |
| | | |
|G12 G11 G10 R15|V33 V12 GND V12 GND V18 GND V12 GND V18 GND|A5 D5 A4 D4 |
| | | |
|R14 R13 R12 R11|GND V33 V18 GND V18 V12 V18 GND V18 V12 V18|A7 D7 A6 D6 |
+-----------. | | |
|DCK GSP SPL|R10|V33 V12 GND V18 GND V18 GND V12 GND V18 GND|A9 D9 A8 D8 |
| .---'---'-------.-------.---.---.-------.-----------' |
|LS REV|B22 G24 G20 R22|D7 D3 |NC |RST|SCK WS |CE1 /OE A20 A11 D11 A10 D10|
| .---' | | | | | |
|GCK|B25 B21 G23 R25 R21|D6 D2 |NC |VSY|MCK SDO|NC CE2 A19 A13 D13 A12 D12|
| | | | | +---. | |
|INI|B24 B20 G22 R24 R20|D5 D1 |NC |HSY|SDA|SDI|/LB CLK A18 A21 A14 D15 D14|
+---+ .---+ '---' | +---' .---+
|NC |B23 G25 G21 R23|NC |D4 D0 CKI RCK|SCL|/UB ADV /WE A15 A17 A22 A16|NC |
'---'---------------'---'---------------'---'---------------------------'---'
LCD CAM I2C SND RAM o
DSi U6 - "BPTWL" - I2C bus(ses), LEDs, volume, power, wifi (6x6 grid)
GND WL_TXPE P02(button) SDA'33 ADPO GND o
ATH_TX_H BLUE(LED) RED(LED) SCL'33 V33 GND
YELLOW(LED) VOLP button VOLN button PM_SLP V33' /WIFI_RST
SDA1 RESET SCL1 to C46 GND to U17
VDD28 GND CAM_LED PWSWO mFE /mRST
GND AOUT mFE'(R79) WL_RXPE /IRQ_O GND
DSi U12 - 5pin, VDD33 to VDD28 converter? (near upper screen socket)
DSi U13 - 5pin, Backlight 1, near power managment chip
DSi U14 - 5pin, Backlight 2, near power managment chip
DSi U15 - 4pin, something near external power input
DSi U16 - N/A
DSi U17 - 6pin, something near headphone socket, connects to U6, and MUTE
DSi U18 - 6pin, something near headphone socket, MIC/LIN related
DSi U19 - 5pin, something near dpad socket
Smaller misc chips.
DSi LEDs:
CAM_LED (via R68 and Q13) ;\
BLUE (via R21 and Q11) ; from U6
YELLOW (via R22 and Q12) ;/
RED (via R20) ;-from U6 (or to U6 ?)
ORANGE (via R2) ;-from U11
Atheros AR6014 chip (on 3DS DWM-W028 Wifi Daughterboard) (and J27H023?)
Pinouts unknown.
There is a 3rd part number, J27H020, made by hon hai (Foxconn) instead of
Mitsumi.
NDS - National Semiconductor LM4880M Dual 250mW Audio Power Amplifier (U12)
1-OUT A 2-IN A 3-BYPASS 4-GND 5-SHUTDOWN 6-IN B 7-OUT A 8-VDD.VQ5
NDS-Lite: No external amplifier (Mitsumi 3205B Powermanagment Device contains
internal amplifier).
Advance Gameboy Power Switch (2-position slider, with two common pins)
GBA SP Power Switch (same as GBA)
1 via resistor to GND (OFF)
2 VS (BT+) (ON)
C VCC (to board)
Pinouts - Wifi
--------------
NDS-Lite RFU Daughter Board DWM-W006 (Firmware FLASH, Wifi BB/RF Chip)
1 GND 6 GND 11 BB.RF.WR 16 VDD3.3 21 RF.SLEEP 26 FMW.Q
2 TXPE 7 TRCLK 12 BB.RF.CLK 17 GND 22 FMW./RES 27 FMW./WP
3 RXPE 8 TRDATA 13 GND 18 RF./CS 23 GND 28 FMW./CS
4 CCA 9 GND 14 MCLK 19 BB.SLEEP 24 FMW.CLK 29 LD ;hi?
5 TRRDY 10 BB.RF.RD 15 GND 20 BB./CS 25 FMW.D 30 GND
https://fccid.io/EW4DWMW006/Label/ID-label-format-and-location-706511.pdf
Below describes how to connect a PC parallel port to the GBA link port,
allowing to upload small programs (max 256 KBytes) from no$gba's Utility menu
into real GBAs.
This is possible because the GBA BIOS includes a built-in function for
downloading & executing program code even when no cartridge is inserted. The
program is loaded to 2000000h and up in GBA memory, and must contain cartridge
header information just as for normal ROM cartridges (nintendo logo, checksum,
etc., plus some additional multiboot info).
Transmission Speed
The first transfer will be very slow, and the GBA BIOS will display the boot
logo for at least 4 seconds, even if the transfer has completed in less time.
Once when you have uploaded a program with burst boot backdoor, further
transfers will be ways faster. The table below shows transfer times for 0KByte
- 256KByte files:
Boot Mode_____Delay 0_______Delay 1_______Delay 2_____
Double Burst 0.1s - 1.8s 0.1s - 3.7s 0.1s - 5.3s
Single Burst 0.1s - 3.6s 0.1s - 7.1s 0.1s - 10.6s
Normal Bios 4.0s - 9.0s 4.0s - 12.7s 4.0s - 16.3s
All timings measured on a 66MHz computer, best possible transmission speed
should be 150KBytes/second. Timings might slightly vary depending on the CPU
speed and/or operating system. Synchronization is done by I/O waitstates, that
should work even on faster computers. Non-zero delays are eventually required
for cables without pull-ups.
Requirements
Beside for the cable and plugs, no special requirements.
The cable should work with all parallel ports, including old-fashioned
one-directional printer ports, as well as modern bi-directional EPP ports.
Transfer timings should work stable regardless of the PCs CPU speed (see above
though), and regardless of multitasking interruptions.
Both no$gba and the actual transmission procedure are using some 32bit code, so
that either one currently requires 80386SX CPUs or above.
Connection Examples
As far as I can imagine, there are four possible methods how to connect the
cable to the GBA. The first two methods don't require to open the GBA, and the
other methods also allow to connect optional power supply and reset signal.
1) Connect it to the GBA link port. Advantage: No need to
open/modify the GBA. Disadvantage: You need a special plug,
(typically gained by removing it from a gameboy link cable).
2) Solder the cable directly to the GBA link port pins. Advantages:
No plug required & no need to open the GBA. Disadvantages:
You can't remove the cable, and the link port becomes unusable.
3) Solder the cable directly to the GBA mainboard. Advantage: No
plug required at the GBA side. Disadvantage: You'll always
have a cable leaping out of the GBA even when not using it,
unless you put a small standard plug between GBA and cable.
4) Install a Centronics socket in the GBA (between power switch
and headphone socket). Advantage: You can use a standard
printer cable. Disadvantages: You need to cut a big hole into
the GBAs battery box (which cannot be used anymore), the big
cable might be a bit uncomfortable when holding the GBA.
Personally, I've decided to use the lastmost method as I don't like ending up
with hundreds of special cables for different purposes, and asides, it's been
fun to damage the GAB as much as possible.
Note
The above used PC parallel port signals are typically using 5V=HIGH while GBA
link ports deal with 3V=HIGH. From my experiences, the different voltages do
not cause communication problems (and do not damage the GBA and/or PC
hardware), and after all real men don't care about a handful of volts, however,
use at own risk.
Flashcard Upload
Allows to write data to flashcards which are plugged into GBA cartridge slot,
cartridge is automatically started after writing. On initial power-up, hold
down START+SELECT to prevent the GBA from booting the old program in the
flashcard.
The Upload function in Utility menu uses flashcard mode for files bigger than
256KB (otherwise uses multiboot mode automatically). Also, there's a separate
Upload to Flashcard function in Remote Access submenu, allowing to write files
of 256KB or less to flashcard if that should be desired.
Supported Flashcards
Function currently tested with Visoly Flash Advance (FA) 256Mbit (32MB) Turbo
cartridge. Should also work with older FA versions. Please let me know if you
are using other flashcards which aren't yet supported.
Flashcard Performance
Writing to flashcards may become potentially slow because of chip erase/write
times, cable transmission time, and the sheer size of larger ROM-images.
However, developers whom are testing different builts of their project usually
won't need to rewrite the complete flashcard, Xboo uses a highspeed checksum
mechanism (16MB/sec) to determine which flashcard sector(s) have changed, and
does then re-write only these sector(s).
To eliminate transmission time, data transfer takes place in the erase phases.
Erase/write time depends on the flashcard type, should be circa 1-2 seconds per
256KB sector. Because the cartridge is programmed directly in the GBA there's
no need to remove it from the GBA when writing to it.
Developers Advice
Locate your program fragments at fixed addresses, for example, code and data
blocks each aligned to 64K memory boundaries, so that data remains at the same
location even when the size of code changes. Fill any blank spaces by value FFh
for faster write time. Reduce the size of your ROM-image by efficient memory
use (except for above alignment trick). Include the burst boot backdoor in your
program, allowing to re-write the flashcard directly without resetting the GBA.
Lamers Advice
Xboo Flashcard support does not mean to get lame & to drop normal multiboot
support, if your program fits into 256KB then make it <both> flashcard <and>
multiboot compatible - multiboot reduces upload time, increases your flashcard
lifetime, and will also work for people whom don't own flashcards.
When writing Xboo compatible programs, always include a burst boot "backdoor",
this will allow yourself (and other people) to upload programs much faster as
when using the normal GBA BIOS multiboot function. Aside from the improved
transmission speed, there's no need to reset the GBA each time (eventually
manually if you do not have reset connect), without having to press
Start+Select (if cartridge inserted), and, most important, the time-consuming
nintendo-logo intro is bypassed.
DSi Emulation
-------------
Nothing working?
Depends on what you want: If you want to play games, then, yes, I don't know of
any DSi games that are working/playable yet. If you want to do
programming/debugging, then you might find out that almost everything is more
or less working. I don't know of any other active DSi devrs though - not too
surprising since the DSi is definitely the most complicated and most
unattractive console that I've ever seen.
Notes on New NDS Emulation
--------------------------
Hello to newer no$gba version(s) with NDS support. Most of it is working fine
by now, a few details are still under construction. The most important
(missing) things to be aware of are:
Note
Use Ctrl+T in debug mode to toggle between the two CPUs.
Pocketstation Emulation
-----------------------
The Sony Pocketstation is a memory card with ARM processor and 32x32 pixel LCD
screen for Sony Playstation consoles. As such, it doesn't have much to do with
GBA/NDS.
Anyways, as I haven't got around to implement ARM emulation in no$psx yet, the
Pocketstation is currently emulated as part of the no$gba project (eventually
it might be moving from no$gba to no$psx someday in future).
Pocketstation BIOS
For using a copy of the original 16Kbyte BIOS: store it as file POCKSTAT.ROM in
no$gba directory. If that file isn't present, then no$gba will use it's own
built-in BIOS clone.
Pocketstation Specs
For tech info on memory map, I/O ports, bios, file formats, see:
http://problemkaputt.de/psx-spx.htm#pocketstation
For info on the ARM processor, see:
--> ARM CPU Reference
Installation
------------
Required Hardware
Miminum requirement would be a 32bit CPU (eg. 80386SX and up). No$gba has been
programmed on a 66MHz 80486DX2, smaller games (eg. simple 2D games, text
output) are working relative smoothly at 100% speed on that computer. Larger
games (eg. 3D games, plasma demos) may require a CPU speed of up to
400..500MHz.
Emulation performance mainly depends on whether (and how much) the game is
using the low power Halt/IntrWait GBA bios functions in idle mode, or not.
Installing No$gba
Just copy the executable to harddisk, preferably into a new/blank folder, below
text will refer to this folder as the 'No$gba' folder, you may use any other
name though. The program will automatically create some subdirecties. For
example, the Slot directory is the suggested location for rom-images.
You will eventually also need some additional files - see below!
Installing Updates
Just overwrite the old executable by the newer version. The setup file from the
older version may be used, any unrecognized options will be set to the default
value.
Uninstalling No$gba
The program does not infect the windows registry. If you wish to uninstall it
just delete the 'No$gba' folder and all sub-directories.
Of course excluding any important files which you may have stored in these
directories and which you may want to keep (ie. source code, binaries, game
positions, and/or your registration key).
Optional Files
NO$GBA.ROM
No$gba includes a built-in BIOS clone which is used if the BIOS ROM-image(s)
are not found. However, the emulation accuracy (eg. exact execution time) of
BIOS SWI-functions increases when using the original BIOS ROM-images. BIOS
images are loaded if the following file(s) exist in your no$gba folder.
NO$GBA.ROM GBA+NDS7+NDS9 BIOS-images (16K+16K+4K)
Alternately, the images can be split into separate files, with filenames:
BIOSNDS.ROM NDS7+NDS9 BIOS-images (16K+4K)
BIOSNDS7.ROM NDS7 BIOS-image (16K)
BIOSNDS9.ROM NDS9 BIOS-image (4K) (or 32K padded with zero's)
BIOSGBA.ROM GBA BIOS-image (16K)
GBA.ROM Same as BIOSGBA.ROM (16K)
For DSi emulation,
BIOSDSI.ROM DSi7+DSi9 BIOS-images (64K+64K) ;\these are only 66% dumpable
BIOSDSI7.ROM DSi7 BIOS-image (64K) ; yet (please pad undumped
BIOSDSI9.ROM DSi9 BIOS-image (64K) ;/regions with 00h-bytes)
For 3DS emulation,
BIOS3DS.ROM 3ds9+3ds11 BIOS-images (64K+64K) ;\
BIOS3DS9.ROM 3ds9 BIOS-image (64K) ; these are filly dumpable
BIOS3DS11.ROM 3ds11 BIOS-image (64K) ;/
The no$gba utility menu (and the Xboo tool on the no$gba webpage) includes a
function for downloading the BIOS from GBA/NDS to file (by simple cable
connection).
Be careful when downloading the BIOSes from internet, there seems to be a very
popular GBA BIOS in the net (probably a very old prototype version), which is
NOT compatible with the actual GBA release version, also some NDS7 BIOS-images
may be incomplete dumps (with first 4K zero-filled), no$gba outputs a warning
message if using an incorrect, incomplete, damaged, or patched BIOS version.
FIRMWARE.BIN
A copy of the original NDS firmware in Wifi FLASH. This file increases
emulation accuracy only by means of delaying the boot process. The no$gba setup
default setting is to start the cartridge directly, without executing the
BIOS/Firmware boot code, so the presence of the firmware image doesn't actually
disturb emulation performance.
Debugging
---------
Most debug functions are available via hotkeys and via mouse accessible popup
boxes. The popup boxes generally also show the corresponding hotkey.
The functions that are marked by (*) are not shown in the popup menues of the
menu bar. Vice versa, not all functions can be accessed through hotkeys, so to
be able to access all functions you must use both hotkeys and menu bars.
See also:
--> Hotkeys in Emulation Mode
See Also:
--> Hotkeys in Debug Mode
Breakpoints
-----------
Run-to-Cursor (F4-key)
Hitting F4-key directly starts emulation, and stops when reaching the code
window cursor. The break address is not memorized, ie. it is used only once.
Profiling Features
--> Profiler Window
--> Profiler Compatibility
--> Clock Cycle Comments
--> Cycle Counters
Related Specifications...
--> ARM CPU Instruction Cycle Times
--> GBA Memory Map
--> GBA System Control
--> LCD Dimensions and Timings
--> BIOS Halt Functions
Profiler Window
---------------
The Profiler Window (Alt+P key in debug mode) displays execution time and
number of calls of all executed procedures. The window is split into Tree,
Path, and List tabs. Double-clicking an item in a tab moves the debuggers code
window to the selected procedure.
For more information on how to use the profiler, and how to avoid possible
problems, please also read the next chapter,
--> Profiler Compatibility
Profiler Compatibility
----------------------
Re-synchronization
The profiler may shortly lose track of the program flow if it has overseen a
return opcode from a child procedure to its parent. It will then assume that it
is still executing the child (and any further cycles and sub-routines will be
incorrectly counted to the child).
However, the profiler will re-synchronize itself to program flow once when it
locates a return opcode which jumps to a higher parent procedure, the child
routine which didn't have a return opcode will be then shown with a "(?)"
question mark in the tree/list tabs.
Multitasking
The profiler memory is organized similar as a stack, and it should be actually
running synchronous to the return addresses on the CPU stack. That means that
it'd be currently not working with any 'multitasking' programs, ie. programs
that switch between different threads, each with a separate stack.
Please let me know if you are doing any such things! I'd love to support it -
if anybody wants it. The feature would probably work automatically (without you
having anything much more to do than to say "hello, I use multitasking, what I
am doing is..."), and it would nicely display each thread as separate root
entry in the tree tab, allowing to determine time being spent in each thread
(and its sub-routines) very easily...
The normal execution time for one GBA opcode ranges between 1 and 100 (!) clock
cycles, or more. Unfortunately, opcode execution time depends on various of
circumstances (bus widths, waitstates, etc.), which is making it rather
difficult to count cycles by hand, or just to a get feeling for efficient GBA
code.
The no$gba Clock Cycle Comments feature displays the execution time for each
opcode in disassembler window. Four different view modes (selectable in setup)
are available:
Even though these features are making it much easier to count cycles, there are
still some restrictions which should be kept in mind:
Prefetch
Game-Pak Prefetch isn't yet understood or supported. If it is enabled in
WAITCNT register, access to cartridge ROM may take up less cycles as displayed
in clock cycle comments.
Conditional Opcodes
Conditional opcodes are always assumed to be true (unless if the program
counter points to the opcode, in that case the actual execution time is
displayed, ie. 1S if the condition is false).
Sums
The Cycles & Sums features simply adds one execution time to another, useful
for fragments of code, but of course not aware of loops or skips.
Jumps
Execution time for branch opcodes is incorrectly displayed by using local
waitstates for local code area (rather than target area). However, intersegment
jumps (from one memory area to another) are typically consisting of a
call-return combination (ie. the overall execution time would be correct, but
the execution times of the call and return opcodes would be exchanged).
VRAM Waitstates
VRAM Waitstates are not displayed (the real hardware would occasionally add 1
cycle for accesses to video memory).
Cycle Counters
--------------
User Counter
The user counter (located in Timers page of I/O map window) is incremented
during emulation execution and tracing, the counter can be easily reset to zero
by pushing the reset button which is displayed next to it.
NB. Cycle counters are 32bit values and will overflow (restart at zero) after
4G cycles (256 seconds), which is probably more than enough in most cases.
Debug Messages
--------------
Debug Messages can be defined in source code. When the emulator 'executes' a
message opcode, the message text will be output to the debug message window and
to file DEBUGMSG.TXT. Debug Messages will not disturb execution on real
hardware (the branch opcode just skips the data definition, wastes a few clock
cycles though).
See also
Aside from use "mov r12,r12", debug messages can be also output via pseudo I/O
ports:
--> DS Debug Registers (Emulator/Devkits)
If debug info (.SYM or .ELF files) has been loaded, labels will be displayed in
disassembled code. And input boxes will recognize labels (eg. for Ctrl+G). TAB
in code window toggles symbolic display on and off. Moving the code windows
cursor onto a line with a symbol displays the value that hides behind the
symbol in the upper left corner of the screen (DOS) or in the status bar
(Windows).
Also, if source-level debug info is present, no$gba allows the user to view
his/her source code in 'stacked' view mode, ie. disassembled opcodes shown
below of each source line, this would be important for HLL programs.
.SYM Files
When not using ELF files, symbolic Information may be stored in file
<cartname>.SYM in the same directory than <cartname>.GBA. The A22i assembler
produces ready-for-use SYM files. When using another assembler, you may convert
any debug information into .SYM format.
There is no need to sort the entries in any way. Empty lines are allowed. Lines
starting with ";" are ignored as comments. Lines are terminated by LF or CRLF
or EOF or filesize. The file is terminated by EOF or filesize.
XED Editor
----------
XED About
---------
About XED
XED is a text editor, the executable is fast and small, and it includes
comfortable editing functions. It is both intended for standard .TXT files (or
any other ASCII files, such like .ASM for assembler source code). Also, the
line-wrapping support (.XED files) can be used for authoring stories,
specifications, etc. Most of the features are much the same as for other text
editors, some special functions are pointed out below:
Block Selection
XED supports good old quality block mechanisms, allowing to copy/move the
selection directly to cursor position by Ctrl+K,C/V hotkeys (without needing to
use paste). For data exchange with other programs or text files, the block can
be directly written to (or loaded from) file by Ctrl+K,R/W. And, mainstream
copy/cut/paste functions are supported as well, by Ctrl+Ins, Shift+Del,
Shift+Ins.
Note: The block remains selected even when typing text, and it won't get
deleted when touching Del-key.
Blank Space
Unlike most other editors, XED allows to move the cursor to any screen
location, including at horizontal positions after the end of the current line.
Entering space characters at such locations advances the cursor position, but
does not actually store space characters in the file.
When typing text, spaces are automatically inserted between line-end and cursor
position. Respectively, ending spaces are automatically deleted (eg. assume
that the line contains "Hello !", deleting "!" will also remove the space
character, internally).
That is of course all happening behind your back, you won't have to care about
it - but you can be sure that there'll be no hidden spaces filling up disk
space.
Line Wrapping
Line wrapping is enabled/disabled by "F5+W" key combination. Wrapping is
automatically enabled when loading a file with extension ".XED".
In the file, wrapped lines are using CR characters as soft linebreaks,
paragraphs are terminated by normal CR,LF characters.
Note: It'd be recommended to convert .XED files into 'standard' formats such
like .TXT or .HTM before releasing them, but preferably NOT into disliked
bloated file formats such like .PDF or .DOC.
Word Processing
Aside from the above line-wrapping support, no other 'word processing' features
are included, the program provides normal 'type writer' functions, not more,
not less. In particular, any overload such like bold or colored text, big and
small fonts, bitmaps and different fonts are disliked.
XED Hotkeys
-----------
XED recognizes both CP/M Wordstar hotkeys (also used by Borland PC compilers),
and Norton editor hotkeys (NU.EXE). The "Ctrl+X,Y" style hotkeys are wordstar
based, particulary including good block functions. The F4,X and Alt/Ctrl+X type
hotkeys are norton based, particulary very useful for forwards/backwards
searching.
Editor Keys
Ctrl+Y Delete line (or Alt+K)
Alt+L Delete to line end (or Ctrl+Q,Y)
Alt+V Caseflip to line end
Ctrl+V Caseflip from line beginning
Disk Commands
F3,E Save+exit
F3,S Save (or Ctrl+K,S)
F3,N Edit new file
F3,A Append a file
See also: Block commands (read/write block).
Block Selection
Shift+Cursor Select block begin..end
Ctrl+K,B Set block begin (or F4,S)
Ctrl+K,K Set block end (or F4,S)
Ctrl+K,H Remove/hide block markers (or F4,R)
F4,L Mark line including ending CRLF (or Ctrl+K,L)
F4,E Mark line excluding ending CRLF
Ctrl+K,T Mark word
Ctrl+K,N Toggle normal/column blocktype
Clipboard Commands
Shift+Ins Paste from Clipboard
Shift+Del Cut to Clipboard
Ctrl+Ins Copy to Clipboard
Ctrl+Del Delete Block
Block Commands
Ctrl+K,C Copy block (or F4,C)
Ctrl+K,V Move block (or F4,M)
Ctrl+K,Y Delete block (or F4,D)
Ctrl+K,P Print block (or F7,B)
Ctrl+Q,B Find block begin (or F4,F)
Ctrl+Q,K Find block end (or F4,F)
Ctrl+K,R Read block from disk towards cursor location
Ctrl+K,W Write block to disk
Ctrl+K,U Unindent block (delete one space at begin of each line)
Ctrl+K,I Indent block (insert one space at begin of each line)
F5,F Format block (with actual x-wrap size) (or ;Ctrl+B)
F8,A Add values within column-block
Setup Commands
F11 Setup menu (or F8,S)
F5,S Save editor configuration
F5,L Set line len for word wrap (or Ctrl+O,R)
F5,W Wordwrap on/off (or Ctrl+O,W) (*)
F5,I Auto indent on/off (or Ctrl+O,I)
F5,T Set tab display spacing
(*) Wrapped lines will be terminated by CR, paragraphs by CRLF.
Other
F1 Help
F2 Status (displays info about file & currently selected block)
F8,M Make best fill tabs
F8,T Translate all tabs to spaces
SrcLock Freeze cursor when typing text ("useful" for backwards writing)
Ctrl+O,C Center current line
Ctrl+K,# Set marker (#=0..9)
Ctrl+Q,# Move to marker (#=0..9)
Ctrl+Q,P Move to previous pos
F6,C Condensed display mode on/off (*)
Ctrl+G Go to line nnnn (or F6,G) (or commandline switch /l:nnnn)
(*) only lines starting with ':' or ';:' will be displayed. cursor and block
commands can be used (e.g. to copy a text-sequence by just marking it's
headline)
Printer Commands
F7,P Print file
F7,B Print block (or Ctrl+K,P)
F7,E Eject page
F7,S Set page size
More printer options can be found in setup. Printing was working well (at least
with my own printer) in older XED versions, but it is probably badly bugged (at
least untested) for years now.
XED Assembler/Debugger Interface
--------------------------------
Nocash Debuggers
The XED editor provides simple but very useful interaction with the various
nocash debuggers/emulators (no$gba, no$gmb, no$cpc, no$msx, no$c64, no$2k6,
no$zx, no$nes, no$sns, no$x51).
The editor can be launched from inside of the debugger (by Alt+E hotkey, by
retaining the recently edited line number when re-launching the editor).
And, when editing assembler source code files, F9-key can used to launch the
assembler from inside of XED. That is, the file is saved to disk, the A22i
assembler is started (built-in in all debuggers), and, in case of successful
assembly, the program is loaded & started in the emulator. Otherwise, the
assembler displays a list of errors, and the editor is moved directly to the
source code line number in which the first error has occured.
Online Assembler
In the debuggers code window, you can directly enter assembler instructions and
modify the program code. The assembler input box shows up automatically when
typing the first character of the new instruction.
The most basic purpose would be to overwrite an opcode by typing "NOP", but you
could also enter any other instruction, such like "ADD R0,R0,4" when having
debug info (.sym file) loaded, you may also use labels as parameters, eg. "B
mainloop". The pseudo opcode "LDR Rd,=Imm" can be used only under certain
circumstances:
--> Using LDR Rd,=Imm in Online Assembler
Note: Aside from translating machine code instructions, the assembler input box
can be also used to change the value of CPU registers, by typing "r0=12345678",
or "sp=3007FF0" for example. For curiosity, it also parses simple commands such
like: run, reload, help, exit, date, etc.
A22i Advantages
It's easy to use, very fast, produces ready-for-use debug info .sym files, it
understands official ARM syntax, as well as more reasonable cleaned-up syntax,
and also different assembler dialects, directives, and numeric formats, it can
be used directly from inside of the debugger (and from inside of the editor),
and vice-versa: it's able call the editor in case of assembly errors.
A22i Disadvantages
The main disadvantage is that A22i isn't supporting macros (yet).
Sample Code
For a source code example, have a look at the Magic Floor game at the no$gba
webpage, the package includes the binary, source code, with comments, and .sym
debug info file.
http://problemkaputt.de/magicflr.htm
2) If the cursor does NOT point to an existing LDR=IMM, then no$gba will search
nearby memory for usable addresses - A) a 32bit value that matches the desired
immediate, B) a word-aligned 32bit value containing ascii letters "fREE", which
you may want to insert here and there in your code, or C) a presumably unused
blank memory area of at least 256 bytes which is 00h- or FFh-filled.
3) If the debugged program was written in C or C++ then you can probably
replace some of the meaningless opcodes by hand. For example, to load a 16bit
immediate with ARM code: MOV Rd,LSB, ADD Rd,MSB.
About
GBATEK written 2001-2014 by Martin Korth, programming specs for the GBA and NDS
hardware, I've been trying to keep the specs both as short as possible, and as
complete as possible. The document is part of the no$gba debuggers built-in
help text.
Updates
The standalone docs in TXT and HTM format are updated when having added any
major changes to the document. The no$gba built-in version will be updated more
regularly, including for minor changes, along with all no$gba updates.
Homepage
http://problemkaputt.de/gba.htm - no$gba emulator homepage (freeware)
http://problemkaputt.de/gba-dev.htm - no$gba debugger homepage
http://problemkaputt.de/gbapics.htm - no$gba debugger screenshots
http://problemkaputt.de/gbatek.htm - gbatek html version
http://problemkaputt.de/gbatek.txt - gbatek text version
Feedback
If you find any information in this document to be misleading, incomplete, or
incorrect, please say something! My spam-shielded email address is found at:
http://problemkaputt.de/email.htm - contact
Mail from programmers only, please. No gaming questions, thanks.
Credits
Thanks for GBATEK fixes, and for info about GBA and NDS hardware,
- Jasper Vijn
- Remi Veilleux (DS video details)
- Randy Linden
- Sebastian Rasmussen
- Stephen Stair (DS Wifi)
- Cue (DS Firmware bits and bytes)
- Tim Seidel (DS Wifi RF2958 datasheet)
- Damien Good (DS Bios Dumping, and lots of e-Reader info)
- Kenobi and Dualscreenman (lots of ARDS/CBDS cheat info)
- Flubba (GBA X/Y-Axis tilt sensor, and GBA Gameboy Player info)
- DarkFader (DS Key2)
- Dstek by neimod (DS Sound)
- Christian Auby
- Jeff Frohwein
- NDSTech Wiki, http://www.bottledlight.com/ds/ (lots of DS info)
- wwylele (xpertteak cpu and mmio findings)
Formatting
TXT is 80 columns, TXT is 80 columns, TXT is 80 columns.
Don't trust anything else. Never.
Index
-----
--> Contents
--> GBA Reference
--> GBA Technical Data
--> GBA Memory Map
--> GBA I/O Map
--> GBA LCD Video Controller
--> LCD I/O Display Control
--> LCD I/O Interrupts and Status
--> LCD I/O BG Control
--> LCD I/O BG Scrolling
--> LCD I/O BG Rotation/Scaling
--> LCD I/O Window Feature
--> LCD I/O Mosaic Function
--> LCD I/O Color Special Effects
--> LCD VRAM Overview
--> LCD VRAM Character Data
--> LCD VRAM BG Screen Data Format (BG Map)
--> LCD VRAM Bitmap BG Modes
--> LCD OBJ - Overview
--> LCD OBJ - OAM Attributes
--> LCD OBJ - OAM Rotation/Scaling Parameters
--> LCD OBJ - VRAM Character (Tile) Mapping
--> LCD Color Palettes
--> LCD Dimensions and Timings
--> GBA Sound Controller
--> GBA Sound Channel 1 - Tone & Sweep
--> GBA Sound Channel 2 - Tone
--> GBA Sound Channel 3 - Wave Output
--> GBA Sound Channel 4 - Noise
--> GBA Sound Channel A and B - DMA Sound
--> GBA Sound Control Registers
--> GBA Comparison of CGB and GBA Sound
--> GBA Timers
--> GBA DMA Transfers
--> GBA Communication Ports
--> SIO Normal Mode
--> SIO Multi-Player Mode
--> SIO UART Mode
--> SIO JOY BUS Mode
--> SIO General-Purpose Mode
--> SIO Control Registers Summary
--> GBA Wireless Adapter
--> GBA Wireless Adapter Games
--> GBA Wireless Adapter Login
--> GBA Wireless Adapter Commands
--> GBA Wireless Adapter Component Lists
--> GBA Infrared Communication
--> GBA Keypad Input
--> GBA Interrupt Control
--> GBA System Control
--> GBA GamePak Prefetch
--> GBA Cartridges
--> GBA Cartridge Header
--> GBA Cartridge ROM
--> GBA Cart Backup IDs
--> GBA Cart Backup SRAM/FRAM
--> GBA Cart Backup EEPROM
--> GBA Cart Backup Flash ROM
--> GBA Cart Backup DACS
--> GBA Cart I/O Port (GPIO)
--> GBA Cart Real-Time Clock (RTC)
--> GBA Cart Solar Sensor
--> GBA Cart Tilt Sensor
--> GBA Cart Gyro Sensor
--> GBA Cart Rumble
--> GBA Cart e-Reader
--> GBA Cart e-Reader Overview
--> GBA Cart e-Reader I/O Ports
--> GBA Cart e-Reader Dotcode Format
--> GBA Cart e-Reader Data Format
--> GBA Cart e-Reader Program Code
--> GBA Cart e-Reader API Functions
--> GBA Cart e-Reader VPK Decompression
--> GBA Cart e-Reader Error Correction
--> GBA Cart e-Reader File Formats
--> GBA Cart Unknown Devices
--> GBA Cart Protections
--> GBA Flashcards
--> GBA Cheat Devices
--> GBA Cheat Codes - General Info
--> GBA Cheat Codes - Codebreaker/Xploder
--> GBA Cheat Codes - Gameshark/Action Replay V1/V2
--> GBA Cheat Codes - Pro Action Replay V3
--> GBA Gameboy Player
--> GBA Unpredictable Things
--> NDS Reference
--> DS Technical Data
--> DS I/O Maps
--> DS Memory Maps
--> DS Memory Control
--> DS Memory Control - Cache and TCM
--> DS Memory Control - Cartridges and Main RAM
--> DS Memory Control - WRAM
--> DS Memory Control - VRAM
--> DS Memory Control - BIOS
--> DS Memory Timings
--> DS Video
--> DS Video Stuff
--> DS Video BG Modes / Control
--> DS Video OBJs
--> DS Video Extended Palettes
--> DS Video Capture and Main Memory Display Mode
--> DS Video Display System Block Diagram
--> DS Files - 2D Video
--> DS Files - 3D Video (mostly unknown)
--> DS Files - 3D Video BMD0 (Model Data)
--> DS Files - 3D Video BTX0 (Texture)
--> DS Files - 3D Video BCA0 (Character Skeletal Animation)
--> DS Files - 3D Video BTP0/BTA0/BMA0/NVA0 (Unknown Animations)
--> DS 3D Video
--> DS 3D Overview
--> DS 3D I/O Map
--> DS 3D Display Control
--> DS 3D Geometry Commands
--> DS 3D Matrix Load/Multiply
--> DS 3D Matrix Types
--> DS 3D Matrix Stack
--> DS 3D Matrix Examples (Projection)
--> DS 3D Matrix Examples (Rotate/Scale/Translate)
--> DS 3D Matrix Examples (Maths Basics)
--> DS 3D Polygon Attributes
--> DS 3D Polygon Definitions by Vertices
--> DS 3D Polygon Light Parameters
--> DS 3D Shadow Polygons
--> DS 3D Texture Attributes
--> DS 3D Texture Formats
--> DS 3D Texture Coordinates
--> DS 3D Texture Blending
--> DS 3D Toon, Edge, Fog, Alpha-Blending, Anti-Aliasing
--> DS 3D Status
--> DS 3D Tests
--> DS 3D Rear-Plane
--> DS 3D Final 2D Output
--> DS Sound
--> DS Sound Channels 0..15
--> DS Sound Control Registers
--> DS Sound Capture
--> DS Sound Block Diagrams
--> DS Sound Notes
--> DS Files - Sound (SDAT etc.)
--> DS Sound Files - SDAT (Sound Data Archive)
--> DS Sound Files - SSEQ (Sound Sequence)
--> DS Sound Files - SSAR (Sound Sequence Archive)
--> DS Sound Files - SBNK (Sound Bank)
--> DS Sound Files - SWAR (Sound Wave Archive)
--> DS Sound Files - SWAV (Sound Wave Data)
--> DS Sound Files - STRM (Sound Wave Stream)
--> DS System and Built-in Peripherals
--> DS DMA Transfers
--> DS Timers
--> DS Interrupts
--> DS Maths
--> DS Inter Process Communication (IPC)
--> DS Keypad
--> DS Absent Link Port
--> DS Real-Time Clock (RTC)
--> DS Serial Peripheral Interface Bus (SPI)
--> DS Touch Screen Controller (TSC)
--> DS Power Control
--> DS Power Management Device
--> DS Main Memory Control
--> DS Backwards-compatible GBA-Mode
--> DS Debug Registers (Emulator/Devkits)
--> DS Cartridges, Encryption, Firmware
--> DS Cartridge Header
--> DS Cartridge Secure Area
--> DS Cartridge Icon/Title
--> DS Cartridge Protocol
--> DS Cartridge Backup
--> DS Cartridge NAND
--> DS Cartridge I/O Ports
--> DS Cartridge NitroROM and NitroARC File Systems
--> DS Cartridge Unknown Commands
--> DS Cartridge PassMe/PassThrough
--> DS Cartridge GBA Slot
--> DS Cart Rumble Pak
--> DS Cart Slider with Rumble
--> DS Cart Expansion RAM
--> DS Cart Infrared/Pedometers
--> DS Cart Infrared Cartridge SPI Commands
--> DS Cart Infrared Cartridge Memory Map
--> DS Cart Infrared Activity Meter IR Commands
--> DS Cart Infrared Activity Meter Memory Map
--> DS Cart Infrared P-Walker IR Commands
--> DS Cart Infrared P-Walker Memory Map
--> DS Cart Infrared P-Walker Ports LCD Controller
--> DS Cart Infrared P-Walker Ports Accelerometer BMA150
--> DS Cart Infrared Component Lists
--> H8/386 SFRs
--> H8/386 Exception Vectors
--> H8/300H Operands
--> H8/300H Opcodes
--> DS Cart Unknown Extras
--> DS Cart Cheat Action Replay DS
--> DS Cart Cheat Codebreaker DS
--> DS Cart DLDI Driver
--> DS Cart DLDI Driver - Guessed Address-Adjustments
--> DS Encryption by Gamecode/Idcode (KEY1)
--> DS Encryption by Random Seed (KEY2)
--> DS Firmware Serial Flash Memory
--> DS Firmware Header
--> DS Firmware Wifi Calibration Data
--> DS Firmware Wifi Internet Access Points
--> DS Firmware User Settings
--> DS Firmware Extended Settings
--> DS File Formats
--> DS Files - Text Messages (MESG)
--> DS Files - Text Manuals
--> DS Wireless Communications
--> DS Wifi I/O Map
--> DS Wifi Control
--> DS Wifi Interrupts
--> DS Wifi Power-Down Registers
--> DS Wifi Receive Control
--> DS Wifi Receive Buffer
--> DS Wifi Receive Statistics
--> DS Wifi Transmit Control
--> DS Wifi Transmit Buffers
--> DS Wifi Transmit Errors
--> DS Wifi Status
--> DS Wifi Timers
--> DS Wifi Multiplay Master
--> DS Wifi Multiplay Slave
--> DS Wifi Configuration Ports
--> DS Wifi Baseband Chip (BB)
--> DS Wifi RF Chip
--> DS Wifi RF9008 Registers
--> DS Wifi Unknown Registers
--> DS Wifi Unused Registers
--> DS Wifi Initialization
--> DS Wifi Flowcharts
--> DS Wifi Hardware Headers
--> DS Wifi Nintendo Beacons
--> DS Wifi Nintendo DS Download Play
--> DS Wifi IEEE802.11 Frames
--> DS Wifi IEEE802.11 Managment Frames (Type=0)
--> DS Wifi IEEE802.11 Control and Data Frames (Type=1 and 2)
--> DS Wifi WPA/WPA2 Handshake Messages (EAPOL)
--> DS Wifi WPA/WPA2 Keys and MICs
--> DS Wifi WPA/WPA2 Encryption
--> DS Wifi FFC ID
--> DS Wifi Dslink/Wifiboot Protocol
--> DS Xboo
--> DSi Reference
--> DSi Basic Differences to NDS
--> DSi I/O Map
--> DSi Control Registers (SCFG)
--> DSi XpertTeak (DSP)
--> DSi Teak Misc
--> DSi Teak I/O Ports (on ARM9 Side)
--> DSi Teak MMIO - Register Summary
--> DSi Teak MMIO[8000h] - Misc Registers (JAM/GLUE)
--> DSi Teak MMIO[8020h] - Timers (TMR)
--> DSi Teak MMIO[8050h] - Serial Port (SIO)
--> DSi Teak MMIO[8060h] - Debug (OCEM, On-chip Emulation Module)
--> DSi Teak MMIO[8080h] - PLL and Power (PMU, Power Management Unit)
--> DSi Teak MMIO[80C0h] - Host Port Interface (APBP aka HPI)
--> DSi Teak MMIO[80E0h] - AHBM - Advanced High Performance Bus Master
--> DSi Teak MMIO[8100h] - Memory Interface Unit (MIU)
--> DSi Teak MMIO[8140h] - Code Replacement Unit (CRU)
--> DSi Teak MMIO[8180h] - Direct Memory Access (DMA)
--> DSi Teak MMIO[8200h] - Interrupt Control Unit (ICU)
--> DSi Teak MMIO[8280h] - Audio (Buffered Time Division Multiplexing Port)
--> DSi Teak CPU Registers
--> DSi Teak CPU Control/Status Registers
--> DSi Teak CPU Address Config/Step/Modulo
--> DSi TeakLite II Instruction Set Encoding
--> DSi TeakLite II Operand Encoding
--> DSi New Shared WRAM (for ARM7, ARM9, DSP)
--> DSi New DMA (NDMA)
--> DSi Microphone and SoundExt
--> DSi Advanced Encryption Standard (AES)
--> DSi AES I/O Ports
--> DSi AES Little-Endian High Level Functions
--> DSi AES Little-Endian Core Function and Key Schedule
--> DSi AES Little-Endian Tables and Test Values
--> DSi AES Big-Endian High Level Functions
--> DSi AES Big-Endian Core Function and Key Schedule
--> DSi AES Big-Endian Tables and Test Values
--> DSi ES Block Encryption
--> DSi Cartridge Header
--> DSi Touchscreen/Sound Controller
--> DSi Touchscreen Access
--> DSi Touchscreen/Sound Init Flowcharts
--> DSi TSC, Register Summary
--> DSi TSC[0:00h..1Ah], Basic PLL and Timing Control
--> DSi TSC[0:1Bh..23h], Codec Control
--> DSi TSC[0:24h..32h], Status and Interrupt Flags
--> DSi TSC[0:33h..3Bh], Pin Control
--> DSi TSC[0:3Ch..55h], DAC/ADC and Beep
--> DSi TSC[0:56h..7Fh], AGC and ADC
--> DSi TSC[1:xxh], DAC and ADC Routing, PGA, Power-Controls and MISC Logic
--> DSi TSC[3:xxh], Touchscreen/SAR Control and TSC[FCh:xxh], Buffer
--> DSi TSC[04h..05h:xxh], ADC Digital Filter Coefficient RAM
--> DSi TSC[08h..0Fh:xxh], DAC Digital Filter Coefficient RAM
--> DSi TSC[20h..2Bh:xxh], TSC[40h..5Fh:xxh] ADC/DAC Instruction RAM
--> DSi I2C Bus
--> DSi I2C I/O Ports
--> DSi I2C Signals
--> DSi I2C Device 4Ah (BPTWL chip)
--> DSi Autoload on Warmboot
--> DSi Aptina Camera Initialization
--> DSi Aptina Camera Registers: SYSCTL (0000h-0051h)
--> DSi Aptina Camera Registers: RX_SS, FUSE, XDMA (0100h-099Fh)
--> DSi Aptina Camera Registers: CORE (3000h-31FFh, 38xxh)
--> DSi Aptina Camera Registers: SOC1 (3210h-33FDh)
--> DSi Aptina Camera Registers: SOC2 (3400h-3729h)
--> DSi Aptina Camera Variables: RAM/SFR/MON (GPIO/Monitor) (MCU:0000h-20xxh)
--> DSi Aptina Camera Variables: SEQ (Sequencer) (MCU:21xxh)
--> DSi Aptina Camera Variables: AE (Auto Exposure) (MCU:22xxh)
--> DSi Aptina Camera Variables: AWB (Auto White Balance) (MCU:23xxh)
--> DSi Aptina Camera Variables: FD (Anti-Flicker) (MCU:24xxh)
--> DSi Aptina Camera Variables: MODE (Mode/Context) (MCU:27xxh)
--> DSi Aptina Camera Variables: HG (Histogram) (MCU:2Bxxh)
--> DSi Alternate Cameras from Unknown Manufacturer
--> DSi Cameras
--> DSi SD/MMC Protocol and I/O Ports
--> DSi SD/MMC I/O Ports: Command/Param/Response/Data
--> DSi SD/MMC I/O Ports: Interrupt/Status
--> DSi SD/MMC I/O Ports: Control Registers
--> DSi SD/MMC I/O Ports: Unknown/Unused Registers
--> DSi SD/MMC I/O Ports: Misc
--> DSi SD/MMC Protocol: Command/Response/Register Summary
--> DSi SD/MMC Protocol: General Commands
--> DSi SD/MMC Protocol: Block Read/Write Commands
--> DSi SD/MMC Protocol: Special Extra Commands
--> DSi SD/MMC Protocol: CSR Register (32bit Card Status Register)
--> DSi SD/MMC Protocol: SSR Register (512bit SD Status Register)
--> DSi SD/MMC Protocol: OCR Register (32bit Operation Conditions Register)
--> DSi SD/MMC Protocol: CID Register (128bit Card Identification)
--> DSi SD/MMC Protocol: CSD Register (128bit Card-Specific Data)
--> DSi SD/MMC Protocol: CSD Register (128bit Card-Specific Data) Version 2.0
--> DSi SD/MMC Protocol: EXT_CSD Register (4096bit Extended CSD Register) (MMC)
--> DSi SD/MMC Protocol: RCA Register (16bit Relative Card Address)
--> DSi SD/MMC Protocol: DSR Register (16bit Driver Stage Register) (Optional)
--> DSi SD/MMC Protocol: SCR Register (64bit SD Card Configuration Register)
--> DSi SD/MMC Protocol: PWD Register (128bit Password plus 8bit Password len)
--> DSi SD/MMC Protocol: State
--> DSi SD/MMC Protocol: Signals
--> DSi SDIO Special SDIO Commands
--> DSi SDIO Memory and I/O Maps
--> DSi SDIO Common Control Registers (CCCR)
--> DSi SDIO Function Basic Registers (FBR)
--> DSi SDIO Card Information Structures (CIS)
--> DSi SD/MMC Filesystem
--> DSi SD/MMC Partition Table (aka Master Boot Record aka MBR)
--> DSi SD/MMC Filesystem (FAT)
--> DSi SD/MMC Internal NAND Layout
--> DSi SD/MMC Bootloader
--> DSi SD/MMC Device List
--> DSi SD/MMC Complete List of SD/MMC Files/Folders
--> DSi SD/MMC Summary of SD/MMC Files/Folders
--> DSi SD/MMC Images
--> DSi SD/MMC DSiware Files on Internal eMMC Storage
--> DSi SD/MMC DSiware Files on External SD Card (.bin aka Tad Files)
--> DSi SD/MMC DSiware Files from Nintendo's Server
--> DSi SD/MMC DSiware Tickets and Title metadata
--> DSi SD/MMC Firmware dev.kp and cert.sys Certificate Files
--> DSi SD/MMC Firmware Certificate/Keys (DER)
--> DSi SD/MMC Firmware Font File
--> DS Cartridge Nitro Font Resource Format
--> LZ Decompression Functions
--> LZ Decompression Functions ASH0
--> ZIP Decompression
--> Inflate - Core Functions
--> Inflate - Initialization & Tree Creation
--> Inflate - Headers and Checksums
--> DS Encrypted Arika Archives with ALZ1 compression
--> DSi SD/MMC Firmware Log Files
--> DSi SD/MMC Firmware Misc Files
--> DSi SD/MMC Firmware Wifi Firmware
--> DSi SD/MMC Firmware System Settings Data Files
--> DSi SD/MMC Firmware Version Data File
--> DSi SD/MMC Firmware Nintendo DS Cart Whitelist File
--> DSi SD/MMC Camera Files - Overview
--> DSi SD/MMC Camera Files - JPEG's
--> DSi SD/MMC Camera Files - pit.bin
--> DSi SD/MMC Flipnote Files
--> DSi Atheros Wifi SDIO Interface
--> DSi Atheros Wifi SDIO Function 0 Register Summary
--> DSi Atheros Wifi SDIO Function 1 Register Summary
--> DSi Atheros Wifi - SDIO Function 1 I/O - mbox_wlan_host_reg
--> DSi Atheros Wifi Misc
--> DSi Atheros Wifi - Command Summary
--> DSi Atheros Wifi - Response Summary
--> DSi Atheros Wifi - Host Interest Area in RAM
--> DSi Atheros Wifi - BMI Bootloader Commands
--> DSi Atheros Wifi - MBOX Transfer Headers
--> DSi Atheros Wifi - WMI Misc Commands
--> DSi Atheros Wifi - WMI Misc Events
--> DSi Atheros Wifi - WMI Connect Functions
--> DSi Atheros Wifi - WMI Channel and Cipher Functions
--> DSi Atheros Wifi - WMI Scan Functions
--> DSi Atheros Wifi - WMI Bit Rate Functions
--> DSi Atheros Wifi - WMI Threshold Functions
--> DSi Atheros Wifi - WMI Error, Retry and Debug Functions
--> DSi Atheros Wifi - WMI Priority Stream Functions
--> DSi Atheros Wifi - WMI Roam Functions
--> DSi Atheros Wifi - WMI Power Functions
--> DSi Atheros Wifi - WMI Statistics Function
--> DSi Atheros Wifi - WMI Bluetooth Coexistence (older AR6002)
--> DSi Atheros Wifi - WMI Wake on Wireless (WOW) Functions
--> DSi Atheros Wifi - WMI General Purpose I/O (GPIO) Functions
--> DSi Atheros Wifi - Unimplemented WMI Misc Functions
--> DSi Atheros Wifi - Unimplemented WMI Bluetooth Coexistence (newer AR6002)
--> DSi Atheros Wifi - Unimplemented WMI Bluetooth Coexistence (AR6003)
--> DSi Atheros Wifi - Unimplemented WMI DataSet Functions
--> DSi Atheros Wifi - Unimplemented WMI AP Mode Functions (exists on 3DS)
--> DSi Atheros Wifi - Unimplemented WMI DFS Functions
--> DSi Atheros Wifi - Unimplemented WMI P2P Functions
--> DSi Atheros Wifi - Unimplemented WMI WAC Functions
--> DSi Atheros Wifi - Unimplemented WMI RF Kill and Store/Recall Functions
--> DSi Atheros Wifi - Unimplemented WMI THIN Functions
--> DSi Atheros Wifi - Unimplemented WMI Pyxis Functions
--> DSi Atheros Wifi I2C EEPROM
--> DSi Atheros Wifi Internal Hardware
--> DSi Atheros Wifi - Xtensa CPU Registers
--> DSi Atheros Wifi - Xtensa CPU Core Opcodes
--> DSi Atheros Wifi - Xtensa CPU Optional General Opcodes
--> DSi Atheros Wifi - Xtensa CPU Optional Exception/Cache/MMU Opcodes
--> DSi Atheros Wifi - Xtensa CPU Optional Floating-Point Opcodes
--> DSi Atheros Wifi - Xtensa CPU Optional MAC16 Opcodes
--> DSi Atheros Wifi - Xtensa CPU Opcode Encoding Tables
--> DSi Atheros Wifi - Internal Memory Map
--> DSi Atheros Wifi - Internal I/O Map Summary (hw2)
--> DSi Atheros Wifi - Internal I/O Map Summary (hw4)
--> DSi Atheros Wifi - Internal I/O Map Summary (hw6)
--> DSi Atheros Wifi - Internal I/O - Unknown and Unused Registers (hw2)
--> DSi Atheros Wifi - Internal I/O - 004000h - RTC/Clock SOC (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 00x000h - RTC/Clock WLAN (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 0xx240h - RTC/Clock SYNC (hw6)
--> DSi Atheros Wifi - Internal I/O - 006000h - WLAN Coex (MCI) (hw6)
--> DSi Atheros Wifi - Internal I/O - 00x000h - Bluetooth Coex (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 00x000h - Memory Control (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 00C000h - Serial UART (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 00E000h - UMBOX Registers (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 010000h - Serial I2C/SPI (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 014000h - GPIO 18/26/57 pin (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 018000h - MBOX Registers (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 01C000h - Analog Intf (hw2)
--> DSi Atheros Wifi - Internal I/O - 01C000h - Analog Intf (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 020000h - WMAC DMA (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 020080h - WMAC IRQ Interrupt (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 020800h - WMAC QCU Queue (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 021000h - WMAC DCU (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 028000h - WMAC PCU (hw2/hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 029800h - BB Baseband (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 0xxx00h - RDMA Registers (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 03x000h - EFUSE Registers (hw4/hw6)
--> DSi Atheros Wifi - Internal I/O - 034000h - More Stuff (hw6)
--> DSi GPIO Registers
--> DSi Console IDs
--> DSi Unknown Registers
--> DSi Notes
--> DSi Exploits
--> DSi Regions
--> 3DS Reference
--> 3DS Memory and I/O Map
--> 3DS MISC Registers
--> 3DS GPIO Registers
--> 3DS Crypto Registers
--> 3DS Crypto - AES Registers
--> 3DS Crypto - SHA Registers
--> 3DS Crypto - RSA Registers
--> 3DS Crypto - PRNG and OTP Registers
--> 3DS Crypto - AES Keyslots
--> 3DS Crypto - AES Key Generator
--> 3DS Crypto - RSA sighax
--> 3DS DMA Registers
--> 3DS DMA - NDMA Registers
--> 3DS DMA - Corelink DMA Peripheral IDs
--> 3DS DMA - Corelink DMA Register Summary
--> 3DS DMA - Corelink DMA - Interrupt and Fault Status Registers
--> 3DS DMA - Corelink DMA - Internal State Status Registers
--> 3DS DMA - Corelink DMA - Transfer Start (aka "Debug" Registers)
--> 3DS DMA - Corelink DMA - Fixed Configuration and ID Registers
--> 3DS DMA - Corelink DMA Opcode Summary
--> 3DS Config Registers
--> 3DS Config - CONFIG9 Registers
--> 3DS Config - CONFIG11 Registers
--> 3DS Config - AXI Registers
--> 3DS Config - L2C-310 Level 2 Cache Controller (New3DS)
--> 3DS Config - ARM7 Registers (GBA/NDS/DSi Mode)
--> 3DS SPI and I2C Bus
--> 3DS SPI Registers
--> 3DS SPI Devices
--> 3DS TSC, Register Summary
--> 3DS I2C Registers
--> 3DS I2C Device List
--> 3DS I2C MCU Register Summary
--> 3DS I2C MCU[00h-01h,05h-07h] - Firmware
--> 3DS I2C MCU[02h, 08h-0Fh, 27h, 58h-59h] - Status
--> 3DS I2C MCU[10h-1Fh] - Interrupt Flags
--> 3DS I2C MCU[03h-04h, 20h-24h] - Power Control
--> 3DS I2C MCU[28h-2Eh] - LED Control
--> 3DS I2C MCU[30h-3Fh] - Real-Time Clock (RTC)
--> 3DS I2C MCU[40h-51h] - Accelerometer/Pedometer
--> 3DS I2C MCU[60h-7Fh] - Misc Status
--> 3DS I2C MCU secondary I2C Devices (on MCU bus)
--> 3DS I2C MCU - RL78 Flash Programming via UART
--> 3DS I2C MCU - RL78 CPU Opcode List
--> 3DS I2C MCU - RL78 CPU Opcode Map
--> 3DS I2C MCU - RL78 CPU Registers and Flags
--> 3DS I2C MCU - RL78 SFR Registers (Special Function Registers) (I/O ports)
--> 3DS I2C MCU - RL78 Misc
--> 3DS I2C Gyroscope (old version)
--> 3DS I2C Gyroscope (new version)
--> 3DS I2C Infrared Receiver/Transmitter (IrDA)
--> 3DS I2C LCD Screen Controllers
--> 3DS I2C New3DS Near-Field Communication (NFC)
--> 3DS NFC Adapter
--> 3DS I2C New3DS C-Stick and ZL/ZR-Buttons
--> 3DS I2C New3DS 16bit IO Expander (aka QTM)
--> 3DS I2C Other/Unused/Debug Devices
--> 3DS Video
--> 3DS Video LCD Registers
--> 3DS GPU Memory and I/O Map
--> 3DS GPU External Register List Summary
--> 3DS GPU Internal Register List Summary
--> 3DS GPU External Registers - Memory Control/Status Registers
--> 3DS GPU External Registers - Top/Bottom Screen and Framebuffer Setup
--> 3DS GPU External Registers - Memfill and Memcopy
--> 3DS GPU Internal Register Overview
--> 3DS GPU Internal Registers - Command Lists
--> 3DS GPU Internal Registers - Finalize Interrupt registers
--> 3DS GPU Internal Registers - Geometry Pipeline registers
--> 3DS GPU Internal Registers - Shader registers
--> 3DS GPU Internal Registers - Rasterizer registers
--> 3DS GPU Internal Registers - Framebuffer registers
--> 3DS GPU Internal Registers - Texturing registers (Generic Textures)
--> 3DS GPU Internal Registers - Texturing registers (Procedural Texture)
--> 3DS GPU Internal Registers - Texturing registers (Environment)
--> 3DS GPU Internal Registers - Fragment Lighting registers
--> 3DS GPU Internal Registers - Unknown/Unused/Undocumented Registers
--> 3DS GPU Shader Instruction Set - Opcode Summary
--> 3DS GPU Shader Instruction Set - Blurp
--> 3DS GPU Geometry Pipeline
--> 3DS GPU Fragment Lighting
--> 3DS GPU Pitfalls
--> 3DS GPU Primitive Engine and Shaders
--> 3DS GPU Triangle Drawing Sample Code
--> 3DS Video CAM Registers (Camera Input)
--> 3DS Video Y2R Registers (YUV-to-RGBA Converter)
--> 3DS Video L2B Registers (RGB-to-RGBA Converter) (New3DS)
--> 3DS Video MVD Registers (Movie Decoder or so?) (New3DS)
--> 3DS Video LGY Registers (Legacy GBA/NDS Video to Framebuffer)
--> 3DS Video Texture Swizzling
--> 3DS Sound and Microphone
--> 3DS Cartridge Registers
--> 3DS Interrupts and Timers
--> 3DS ARM9 Interrupts
--> 3DS ARM9 Timers
--> 3DS ARM11 Interrupts
--> ARM11 MPCore Private Memory Region Register Summary
--> ARM11 MPCore - Snoop Control Unit (SCU)
--> ARM11 MPCore - Timer and Watchdog
--> ARM11 MPCore - Interrupt Configuration
--> ARM11 MPCore - Interrupt Handling
--> ARM11 MPCore Distributed Interrupt Controller (Blurb)
--> ARM Vector Floating-point Unit (VFP)
--> ARM VFP Floating Point Registers
--> ARM VFP Floating Point Control/Status Registers
--> ARM VFP Floating Point Opcode Encoding
--> ARM VFP Floating Point Maths Opcodes
--> ARM VFP Floating Point Load/Store Opcodes
--> 3DS Files - eMMC Partitions
--> 3DS Files - NCSD Format
--> 3DS Files - FIRM Format
--> 3DS Files - FIRM Encryption
--> 3DS Files - FIRM Versions
--> 3DS Files - FIRM Launch Parameters
--> 3DS Files - NCCH Format
--> 3DS Files - NCCH Extended Header
--> 3DS Files - NCCH ExeFS
--> 3DS Files - NCCH RomFS
--> 3DS Files - NCCH Encryption
--> 3DS Files - NCCH Logo
--> 3DS Files - Title Content Metadata (CMD)
--> 3DS Files - Title Metadata (TMD)
--> 3DS Files - Title Ticket (ticket.db)
--> 3DS Files - Title Certificates (certs.db)
--> 3DS Files - Title Database Files (title.db, import.db, etc.)
--> 3DS Files - Title Installation Archive (CIA)
--> 3DS Files - Title Homebrew Executables (3DSX)
--> 3DS Files - Client Cert/Key (ClCertA)
--> 3DS Files - CTCert
--> 3DS Files - Dictionary (NJDC)
--> 3DS Files - Guide (GBIN)
--> 3DS Files - Version (CVer and NVer)
--> 3DS Files - CRR0 and CRO0 Files
--> 3DS Files - Archive DARC
--> 3DS Files - Archive SARC
--> 3DS Files - Archive arcless
--> 3DS Files - Archive ZAR
--> 3DS Files - CCAL Format (Hardware calibration, HWCAL)
--> 3DS Files - Config Savegame
--> 3DS Files - Title IDs
--> 3DS Files - Title NS
--> 3DS Files - Savedata Extdata
--> 3DS Files - Savedata SAVE/BDRI/VSXE Formats
--> 3DS Files - Savedata DISA and DIFF
--> 3DS Files - Savedata DISA and DIFF - Data Pairs
--> 3DS Files - Savedata DISA and DIFF - Checksums
--> 3DS Files - Savedata Gamecard FLASH Encryption and Wear Leveling
--> 3DS Files - Messages (MsgStdBn)
--> 3DS Files - Video Icons (SMDH)
--> 3DS Files - Video Banner (CBMD)
--> 3DS Files - Video Banner (Extended Banner)
--> 3DS Files - Video Layout (CLYT/FLYT)
--> 3DS Files - Video Layout Animation (CLAN/FLAN)
--> 3DS Files - Video Layout Images (CLIM/FLIM)
--> 3DS Files - Video Archive (CGFX)
--> 3DS Files - Video Archive (CGFX Header, Blocks, DICTs)
--> 3DS Files - Video Archive (CGFX_00h - CMDL Models)
--> 3DS Files - Video Archive (CGFX_01h - TXOB Textures)
--> 3DS Files - Video Archive (CGFX_02h - LUTS Look-up Tables)
--> 3DS Files - Video Archive (CGFX_04h - SHDR Shaders)
--> 3DS Files - Video Archive (CGFX_05h - CCAM Cameras)
--> 3DS Files - Video Archive (CGFX_06h - CFLT/CHLT/CALT Lights)
--> 3DS Files - Video Archive (CGFX_08h - CENV Environments)
--> 3DS Files - Video Archive (CGFX_09h,0Ah,0Dh - CANM Animations)
--> 3DS Files - Video Archive (CGFX_0Eh,0Fh - PEMT Emitters/Particles)
--> 3DS Files - Video Shaders (DVLB and DVOB Format)
--> 3DS Files - Video Fonts (CFNT and FFNT Format)
--> 3DS Files - Video Texture Package (CTPK)
--> 3DS Files - Video Bitmap (BMP)
--> 3DS Files - BASE64 Encoding
--> 3DS Files - Video 3D Photos (MPO)
--> 3DS Files - Sound Archive (CSAR Format)
--> 3DS Files - Sound SEQ (CSEQ Format)
--> 3DS Files - Sound WSD (CWSD Format)
--> 3DS Files - Sound Bank (CBNK Format)
--> 3DS Files - Sound Wave Archive (CWAR Format)
--> 3DS Files - Sound Wave Data (CWAV Format)
--> 3DS Files - Sound Wave Streams (CSTM Format)
--> 3DS Files - Sound Group (CGRP Format)
--> 3DS Files - Sound IDs (CSID Format)
--> 3DS Files - Sound DSP Binary (DSP1 aka .cdc)
--> 3DS Files - Module NWM (Wifi Driver)
--> Non-DS Files - RARC Archives
--> Non-DS Files - U8 Archives
--> 3DS Console IDs
--> 3DS eMMC and MCU Images
--> 3DS Component Lists
--> 3DS Testpoints
--> 3DS Connector Pinouts
--> 3DS Chipset Pinouts
--> ARM CPU Reference
--> ARM CPU Overview
--> ARM CPU Register Set
--> ARM CPU Flags & Condition Field (cond)
--> ARM CPU 26bit Memory Interface
--> ARM CPU Exceptions
--> ARM CPU Memory Alignments
--> ARM Instruction Summary
--> ARM Opcodes: Branch and Branch with Link (B, BL, BX, BLX, SWI, BKPT)
--> ARM Opcodes: Data Processing (ALU)
--> ARM Opcodes: Multiply and Multiply-Accumulate (MUL, MLA)
--> ARM Opcodes: Special ARM9 Instructions (CLZ, QADD/QSUB)
--> ARM Opcodes: Special ARM11 Instructions (Misc)
--> ARM Opcodes: Special ARM11 Instructions (SIMD)
--> ARM Opcodes: PSR Transfer (MRS, MSR)
--> ARM Opcodes: Memory: Single Data Transfer (LDR, STR, PLD)
--> ARM Opcodes: Memory: Halfword, Doubleword, and Signed Data Transfer
--> ARM Opcodes: Memory: Block Data Transfer (LDM, STM)
--> ARM Opcodes: Memory: Single Data Swap (SWP)
--> ARM Opcodes: Coprocessor Instructions (MRC/MCR, LDC/STC, CDP, MCRR/MRRC)
--> THUMB Instruction Summary
--> THUMB Opcodes: Register Operations (ALU, BX)
--> THUMB Opcodes: Memory Load/Store (LDR/STR)
--> THUMB Opcodes: Memory Addressing (ADD PC/SP)
--> THUMB Opcodes: Memory Multiple Load/Store (PUSH/POP and LDM/STM)
--> THUMB Opcodes: Jumps and Calls
--> THUMB Opcodes: New THUMB Opcodes in ARM11
--> ARM Pseudo Instructions and Directives
--> ARM CP14 ICEbreaker Debug Communications Channel
--> ARM CP15 System Control Coprocessor
--> ARM CP15 Overview
--> ARM CP15 ID Codes
--> ARM CP15 Control Register
--> ARM CP15 Memory Managment Unit (MMU)
--> ARM CP15 Protection Unit (PU)
--> ARM CP15 Cache Control
--> ARM CP15 Tightly Coupled Memory (TCM)
--> ARM CP15 Misc
--> ARM CPU Instruction Cycle Times
--> ARM CPU Versions
--> ARM CPU Data Sheet
--> BIOS Functions
--> BIOS Function Summary
--> BIOS Differences between GBA and NDS functions
--> BIOS Arithmetic Functions
--> BIOS Rotation/Scaling Functions
--> BIOS Decompression Functions
--> BIOS Memory Copy
--> BIOS Halt Functions
--> BIOS Reset Functions
--> BIOS Misc Functions
--> BIOS Multi Boot (Single Game Pak)
--> BIOS Sound Functions
--> BIOS SHA1 Functions (DSi only)
--> BIOS RSA Functions (DSi only)
--> BIOS RSA Basics
--> BIOS RSA Pseudo Code
--> BIOS 3DS Exception Vectors
--> BIOS RAM Usage
--> BIOS Dumping
--> External Connectors
--> AUX GBA Game Pak Bus
--> AUX DS Game Card Slot
--> AUX Link Port
--> AUX Sound/Headphone Socket and Battery/Power Supply
--> AUX DSi SD/MMC Pin-Outs
--> AUX Opening the GBA
--> AUX Mainboard
--> AUX DSi Component Lists
--> AUX DSi Internal Connectors
--> AUX DSi Chipset Pinouts
--> Pinouts - CPU - Signal Summary
--> Pinouts - CPU - Pinouts
--> Pinouts - Audio Amplifiers
--> Pinouts - LCD Cables
--> Pinouts - Power Switches, DC/DC Converters, Reset Generators
--> Pinouts - Wifi
--> Pinouts - Various
--> AUX Xboo PC-to-GBA Multiboot Cable
--> AUX Xboo Flashcard Upload
--> AUX Xboo Burst Boot Backdoor
--> DSi Emulation
--> Notes on New NDS Emulation
--> Pocketstation Emulation
--> Installation
--> Debugging
--> Hotkeys in Debug Mode
--> Hotkeys in Emulation Mode
--> Breakpoints
--> Profiling & Performance Monitoring
--> Profiler Window
--> Profiler Compatibility
--> Clock Cycle Comments
--> Cycle Counters
--> Debug Messages
--> Symbolic Debug Info
--> XED Editor
--> XED About
--> XED Hotkeys
--> XED Assembler/Debugger Interface
--> XED Commandline based standalone version
--> The A22i Assembler
--> Using LDR Rd,=Imm in Online Assembler
--> About this Document