DS Video Information

Two backlit LCD screens made by Sharp. 256x192 resolution

NDS video timing information:

  • Both screens are updated simultaneously.
  • 355 pixels/line
  • 263 lines/frame
  • 2130 clocks/line
  • 6 clocks/pixel
  • H-blank signal is low for 264 pixels every scanline
  • V-blank signal is low for 193 scanlines + 8 pixels every frame
  • 560,190 clocks/frame
  • 59.8 frames/second
  • 15,727.4 lines/second
  • Note: this timing is identical to NTSC television.
  • The clock cycles at 33,499,362.6 Hz (timer input)

Note: these timings are based on a single program (with multiple overlapping methods of measuring some quantities), and on a single DS. Another DS may have a slightly different clock rate.

Although there are 256x192 visible pixels, the v-blank bit stays low for 193 scanlines and 8 pixels longer than that, and the h-blank bit stays low for 8 pixels longer than it should.

<Theory>

This is because of the way the DS renders graphics. It needs a full scanline at the beginning of the frame (more likely at the end of the previous frame) to scan OAM for sprites visible on the next scanline. Presumably the 8 pixels are for 8 vram fetches (one per layer, 4 layers per core) to prime the 2D cores.

</Theory>

<< | Video | >>

There are two nearly identical 2D cores in the Nintendo DS. The main core has an additional background mode.

NOTE: SOME OF THIS INFORMATION IS WRONG, BEWARE

Core-specific registers

Core Register offset
A 0x04000000
B 0x04001000
Offset:Width Mode Name
0x00:32 R/W DISPLAY_CR
0x08:16 R/W BG0_CR
0x0A:16 R/W BG1_CR
0x0C:16 R/W BG2_CR
0x0E:16 R/W BG3_CR
0x10:16 W BG0_X
0x12:16 W BG0_Y
0x14:16 W BG1_X
0x16:16 W BG1_Y
0x18:16 W BG2_X
0x1A:16 W BG2_Y
0x1C:16 W BG3_X
0x1E:16 W BG3_Y
0x20:16 W BG2_HDX
0x22:16 W BG2_HDY
0x24:16 W BG2_VDX
0x26:16 W BG2_VDY
0x28:32 W BG2_X0
0x2C:32 W BG2_Y0
0x30:16 W BG3_HDX
0x32:16 W BG3_HDY
0x34:16 W BG3_VDX
0x36:16 W BG3_VDY
0x38:32 W BG3_X0
0x3C:32 W BG3_Y0
0x40:16 W WIN0_X
0x42:16 W WIN1_X
0x44:16 W WIN0_Y
0x46:16 W WIN1_Y
0x48:16 R/W WIN_IN (3f3f)
0x4A:16 R/W WIN_OUT (3f3f)
0x4C:16 W MOSAIC
0x50:16 R/W BLEND_CR (3fff)
0x52:16 R/W BLEND_AB (1f1f)
0x54:16 W BLEND_Y
0x6C:16 R/W BRIGHT_CR (c01f)

DISPLAY_CONTROL

bit name
31 Extended sprite palette enable
30 Extended background palette enable
29..24 ?
23 ?
22..20 Extended sprite mode
19..18 Framebuffer select (extended mode 2)
17..16 Extended mode
15 Sprite window enable
14 Window 1 enable
13 Window 0 enable
12 Sprite enable
11 BG3 enable
10 BG2 enable
9 BG1 enable
8 BG0 enable
7 Forced blank
6..4 Sprite mode
3 0: BG0 is 2D layer, 1: BG0 is 3D layer
2..0 Display mode

Extended Mode:

  • 0: Framebuffer
  • 1: GBA-style (see display mode)
  • 2: acts like framebuffer
  • 3: ?

DISP_CR2

bit name
31 Extended sprite palette enable
30 Extended background palette enable
29..23 ?
22..20 Extended sprite mode
19..18 ?
17..16 Extended mode
15 Sprite window enable
14 Window 1 enable
13 Window 0 enable
12 Sprite enable
11 BG3 enable
10 BG2 enable
9 BG1 enable
8 BG0 enable
7 Forced blank
6..4 Sprite mode
3 ?
2..0 Display mode

Extended Mode:

  • 0: ?
  • 1: GBA-style (see display mode)
  • 2: ?
  • 3: ?

NOTE: THIS INFORMATION IS POSSIBLY WRONG Display Mode (ignored unless Extended Mode is 1):

  • 0: Mode 0 (4 text layers)
  • 1: Mode 1 (2 text layers, 1 rot/scale)
  • 2: Mode 2 (2 rot/scale)
  • 3: Mode 3 (15 bpp framebuffer, single page)
  • 4: Mode 4 (8 bpp indexed framebuffer, double buffered)
  • 5: Mode 5 (bg0 is text/3d, bg1 is text, bg2 is extended rot/scale background)
  • 6: Mode 6 ?

Extended rot/scale background in mode 5: Size fields: BG_BMP16_128x128 BG_BMP16_256x256 BG_BMP16_512x256 BG_BMP16_512x512

Each element in the background is a 16 bit direct-color entry A1B5G5R5. If the top bit is zero, the pixel is transparent, otherwise it is opaque.

Differences to the GBA:

  • Alpha bit (modes 3 and 5 were always opaque on GBA)
  • Multiple sizes
  • Rot/scale registers are *not* set to straight display by default

BRIGHT_CR

bit name
15..14 Mode
13..5 -
4..0 Amount

Mode:

  • 00, 11: Amount ignored, middle brightness
  • 01: Increase, brightness = middle + amount (0x8 and above are pretty much useless)
  • 10: Decrease, brightness = middle - amount (0x8 and above are pretty much useless)

Bits marked as - read as 0, and ignore writes.

 

3D Core Registers

Name Width Address
GFX_CONTROL 16 0x04000060
GFX_FIFO 32 0x04000400
GFX_STATUS 32 0x04000600
GFX_TEX_FORMAT 32 0x040004A8
GFX_CLEAR_COLOR 32 0x04000350
GFX_CLEAR_DEPTH 16 0x04000354
GFX_LIGHT_VECTOR 32 0x040004C8
GFX_LIGHT_COLOR 32 0x040004CC
GFX_DIFFUSE_AMBIENT 32 0x040004C0
GFX_SPECULAR_EMISSION 32 0x040004C4
GFX_SHININESS 32 0x040004D0
GFX_POLY_FORMAT 32 0x040004A4
GFX_ALPHA_TEST 16 0x04000340
GFX_FLUSH 32 0x04000540
GFX_VIEWPORT 32 0x04000580
GFX_TOON_TABLE 16 0x04000380
GFX_EDGE_TABLE 16 0x04000330
GFX_VERTEX_RAM_USAGE 16 0x04000606
GFX_POLYGON_RAM_USAGE 16 0x04000604

GFX_TEX_FORMAT

31..30 Texgen mode
29 ?
28..26 Texture Format
25..23 Texture Height
22..20 Texture Width
19 Flip T
18 Flip S
17 Wrap T
16 Wrap S
15..0 Texture address / 8

Texgen mode affects what texture coordinates are passed into the rasterizer.

00 Tex-coord passed through
01 Tex-coord * texture matrix
10 Normal * texture matrix
11 Vertex * texture matrix

Texture formats:

0 ?
1 RGB32_A3 - 32 color palette, 3 bits of alpha
2 RGB4 - 4 color palette (2 bpp)
3 RGB16 - 16 color palette (4 bpp)
4 RGB256 - 256 color palette (8 bpp)
5 Compressed
6 RGB8_A5 - 8 color palette, 5 bits of alpha
7 RGBA - 15 bpp RGB plus 1 bit alpha in MSB (16 bpp)

Texture sizes are powers of 2 from 8 to 1024 (0..7). A texture does not have to be square.

libnds function calls associated with this register:

  • glBindTexture
  • glTexImage2d

GFX_POLY_FORMAT

31..30 ?
29..24 Polygon ID
23..21 ?
20..16 Polygon alpha (31: opaque)
15..8 ?
7..6 Cull mode (00: front and back, 01: front, 10: back, 11: none)
5..4 Mode (00: Modulate, 01: Decal, 10: Toon shading, 11: Shadow)
3 Light 3 enable
2 Light 2 enable
1 Light 1 enable
0 Light 0 enable

libnds function calls associated with this register:

  • glPolyFmt

GFX_LIGHT_VECTOR

31..30 Light ID #
29..20 z component of normal (.10 fixed)
19..10 y component of normal (.10 fixed)
9..0 x component of normal (.10 fixed)

libnds function calls associated with this register:

  • glLight

GFX_LIGHT_COLOR

31..30 Light ID #
14..10 RGB color

libnds function calls associated with this register:

  • glLight

GFX_DIFFUSE_AMBIENT

31..16 Ambient color
15..0 Diffuse color

GFX_SPECULAR_EMISSION

31..16 Emission color
15..0 Specular color

libnds function calls associated with this register:

  • glMaterialf

GFX_CONTROL

15..14 ?
13 Polygon / vertex memory overflow (write 1 to reset)
12 Line buffer overflow (write 1 to reset)
11..6 ?
5 Outlining (1: enabled)
4 Antialiasing (1: enabled)
3 Alpha blending (1: enabled)
2 Alpha test (1: enabled)
1 Shading mode (0: toon, 1: highlighting)
0 Texture-mapping (1: enabled)

GFX_ALPHA_TEST

15..5 -
4..0 Alpha threshold

If enabled (see GFX_CONTROL or glEnable), fragments are discarded if their post-blend alpha value is below the threshold set in this register.

libnds function calls associated with this register:

  • glAlphaFunc

 

 

Geometry Engine

 

Name Width Address Description
NOP 32 0x04000400 No-operation
MATRIX_CONTROL 32 0x04000440 Matrix control register
MATRIX_PUSH 32 0x04000444 Matrix push
MATRIX_POP 32 0x04000448 Matrix pop
MATRIX_STORE 32 0x0400044C Matrix store
MATRIX_RESTORE 32 0x04000450 Matrix restore
MATRIX_IDENTITY 32 0x04000454 Load identity matrix
MATRIX_LOAD4x4 32 0x04000458 Load 4x4 matrix write port
MATRIX_LOAD4x3 32 0x0400045C Load 4x3 matrix write port
MATRIX_MULT4x4 32 0x04000460 Multiply 4x4 matrix write port
MATRIX_MULT4x3 32 0x04000464 Multiply 4x3 matrix write port
MATRIX_MULT3x3 32 0x04000468 Multiply 3x3 matrix write port
MATRIX_SCALE 32 0x0400046C Scale matrix write port
MATRIX_TRANSLATE 32 0x04000470 Translate matrix write port
MATRIX_READ_PROJECTION 32 0x04000640 Read port for projection matrix
MATRIX_READ_ROTATION 32 0x04000680 Read port for ?rotation? matrix
POINT_RESULT 32 0x04000620 .
VECTOR_RESULT 16 0x04000630 .
GFX_COLOR 32 0x04000480 Set color
GFX_NORMAL 32 0x04000484 Set normal
GFX_TEX_COORD 32 0x04000488 Set texture coordinate
GFX_VERTEX16 32 0x0400048C Vertex write port
GFX_VERTEX10 32 0x04000490 Vertex write port
GFX_VERTEX_XY 32 0x04000494 Vertex write port
GFX_VERTEX_XZ 32 0x04000498 Vertex write port
GFX_VERTEX_YZ 32 0x0400049C Vertex write port
GFX_VERTEX_DIFF 32 0x040004A0 Vertex write port
GFX_BEGIN 32 0x04000500 Begin a primitive
GFX_END 32 0x04000504 End a primitive
GFX_BOX_TEST 32 0x040005C0 .

GFX_BEGIN

Starts the processing of primitives.

31..2 ?
1..0 Type (00: Triangles, 01: Quads, 10: Triangle Strip, 11: Quad Strip)

GFX_END

Stops the processing of primitives / finalizes them.

Just like OpenGL, you should only issue vertex commands in between a begin / end pair.

libnds function calls associated with these registers:

  • glBegin
  • glEnd

MATRIX_TRANSLATE

Three writes multiples the current matrix with a translate matrix of the form:

1.0 0.0 0.0 write1
0.0 1.0 0.0 write2
0.0 0.0 1.0 write3
0.0 0.0 0.0 1.0

libnds function calls associated with these registers:

  • glTranslatev
  • glTranslate3f32
  • glTranslatef32
  • glTranslatef

MATRIX_SCALE

Three writes multiples the current matrix with a scale matrix of the form:

write1 0.0 0.0 0.0
0.0 write2 0.0 0.0
0.0 0.0 write3 0.0
0.0 0.0 0.0 1.0

libnds function calls associated with these registers:

  • glScalev
  • glScalef32
  • glScalef

MATRIX_MULT3x3

After 9 writes, the current matrix is multipled by a 3x3 matrix formed from the writes.

MATRIX_MULT4x3

After 12 writes, the current matrix is multipled by a 4x3 matrix formed from the writes.

MATRIX_MULT4x4

After 16 writes, the current matrix is multipled by a 3x3 matrix formed from the writes.

libnds function calls associated with these registers:

  • glMultMatrix3x3
  • glMultMatrix4x3
  • glMultMatrix4x4

MATRIX_LOAD4x4

Write port to the 4x4 matrix hardware (f32 format).

MATRIX_LOAD4x3

Write port to the 4x4 matrix hardware (f32 format). After 12 writes, the last 4 elements of the matrix are set to 0.0 0.0 0.0 1.0.

libnds function calls associated with these registers:

  • glLoadMatrix4x3
  • glLoadMatrix4x4
  • Various other routines use them behind the scenes.

libnds fixed point / floating point / integer conversion routines:

  • intof32 (integer -> f32)
  • floatof32 (float -> f32)
  • inttot16 (integer -> t16)
  • floattot16 (float -> t16)
  • inttov16 (integer -> v16)
  • floattov16 (float -> v16)
  • inttov10 (integer -> v10)
  • floattov10 (float -> v10)

 

 

Sprites

OAM Entry Attribute 0,1
7..0 Y
9..8 Rot/scale (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale)
11..10 Mode (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap?)
12 Mosaic (1: Enabled)
13 Color depth (0: 16, 1: 256)
15..14 Shape (00: Square, 01: Wide, 10: Tall, 11: Illegal)
24..16 X
29..25 Rot/scale matrix index
28 HF
29 VF
31..30 Size
OAM Entry Attribute 2
9..0 Tile index
11..10 Priority
15..12 Palette index

Attribute 3 is actually a part of the rotation/scale parameters for sprites.

Each core commands 128 sprites, taking up 768 bytes, the other 256 bytes (interspersed between sprites) form 32 rot/scale matricies.

OAM locations:

  • 0x07000000 for 2D Core A
  • 0x07000400 for 2D Core B

 

Palettes in a nutshell

  • There are 4 palettes, two per display.
  • Sprites get one palette, and background layers another.
  • Each palette has 256 halfword entries.
  • Each entry contains 5 bits of red, 5 bits of green, 5 bits of blue, and an unused bit.
  • PALETTE_BG1 is at 0x05000000 (background palette for 2D core A)
  • PALETTE_FG1 is at 0x05000200 (sprite palette for 2D core A)
  • PALETTE_BG2 is at 0x05000400 (background palette for 2D core B)
  • PALETTE_FG2 is at 0x05000600 (sprite palette for 2D core B)

Color structure

15 14..10 9..5 4..0
pad blue green red

 

 

Video Modes

Video Modes

Name Value to write to CR
Mode 0 0x00010000
Mode 1 0x00010001
Mode 2 0x00010002
Mode 3 0x00010003
Mode 4 0x00010004
Mode 5 0x00010005
Mode 6 0x00010006
Framebuffer 0x00020000

VRAM Banks

Name Define Register Size Location
Core A ? ? 256 KB 0x06000000
Core B ? ? 256 KB 0x06040000
Bank A VRAM_A_CR 0x04000240:8 128 KB 0x06800000
Bank B VRAM_B_CR 0x04000241:8 128 KB 0x06820000
Bank C VRAM_C_CR 0x04000242:8 128 KB 0x06840000
Bank D VRAM_D_CR 0x04000243:8 128 KB 0x06860000
Bank E VRAM_E_CR 0x04000244:8 64 KB 0x06880000
Bank F VRAM_F_CR 0x04000245:8 16 KB 0x06890000
Bank G VRAM_G_CR 0x04000246:8 16 KB 0x06894000
Bank H VRAM_H_CR 0x04000248:8 32 KB 0x06898000
Bank I VRAM_I_CR 0x04000249:8 16 KB 0x068A0000

VRAM_A_CR (128 KB)

7 1: Enabled
4..3 Offset
1..0 Mode

Modes:

Bits Name ARM9 address, offset effect
00 Framebuffer 0x06800000, offset ignored?
01 Main BG 0x06000000, 0x06020000, 0x06040000, 0x06060000
10 Main sprites 0x06400000 if offset=0x, 0x06420000 if offset=1x
11 Textures bank 0..3, *

VRAM_B_CR (128 KB)

7 1: Enabled
4..3 Offset
1..0 Mode

Modes:

Bits Name ARM9 address, offset effect
00 Framebuffer 0x06820000, offset ignored?
01 Main BG 0x06000000, 0x06020000, 0x06040000, 0x06060000
10 Main sprites 0x06400000 if offset=0x, 0x06420000 if offset=1x
11 Textures bank 0..3, *

VRAM_C_CR (128 KB)

7 1: Enabled
4..3 Offset
2..0 Mode

Modes:

Bits Name ARM9 address, offset effect
000 Framebuffer 0x06840000, offset ignored?
001 Main BG 0x06000000, 0x06020000, 0x06040000, 0x06060000
010 ARM7 *, arm7: 0x06000000 if offset=0x, 0x06020000 if offset=1x
011 Textures bank 0..3, *
100 Sub BG 0x06200000, offset ignored?
101 ? ?
110 ? ?
111 ? ?

VRAM_D_CR (128 KB)

7 1: Enabled
4..3 Offset
2..0 Mode

Modes:

Bits Name ARM9 address, offset effect
000 Framebuffer 0x06860000, offset ignored?
001 Main BG 0x06000000, 0x06020000, 0x06040000, 0x06060000
010 ARM7 *, arm7: 0x06000000 if offset=0x, 0x06020000 if offset=1x
011 Textures bank 0..3, *
100 Sub BG 0x06600000, offset ignored?
101 ? ?
110 ? ?
111 ? ?

retains 0x87

VRAM_E_CR (64 KB)

7 1: Enabled
2..0 Mode

Modes:

Bits Name ARM9 address
000 Framebuffer 0x06880000
001 Main BG 0x06000000
010 Main sprites 0x06400000
011 Textures palettes 0..3 *
100 Extended main BG palettes 0..3
101 ? ?
110 ? ?
111 ? ?

VRAM_F_CR (16 KB)

7 1: Enabled
4..3 Offset
2..0 Mode

Modes:

Bits Name ARM9 address, offset effect
000 Video core 0x06890000, offset ignored?
001 Main BG 0x06000000, 0x06004000, 0x06100000, 0x06140000
010 Main sprites 0x06400000, 0x06404000, 0x06410000, 0x06414000
011 Texture palette *, palette 0,1,4,5
100 Extended BG palettes *, 0..1, 2..3, ?, ?
101 Extended sprite palettes *, offset ignored
110 ? ?
111 ? ?

VRAM_G_CR (16 KB)

7 1: Enabled
4..3 Offset
2..0 Mode
Bits Name ARM9 address, offset effect
000 Video core 0x06894000, offset ignored?
001 Main BG 0x06000000, 0x06004000, 0x06100000, 0x06140000
010 Main sprites 0x06400000, 0x06404000, 0x06410000, 0x06414000
011 Texture palette *, palette 0,1,4,5
100 Extended BG palettes *, 0..1, 2..3, ?, ?
101 Extended sprite palettes *, offset ignored
110 ? ?
111 ? ?

--- 0x248: retains 8383

VRAM_H_CR (32 KB)

7 1: Enabled
1..0 Mode
Bits Name ARM9 address
00 Video core 0x06898000
01 Sub BG 0x06200000
10 Extended sub sprite palettes 0..3 *
11 ? ?

VRAM_I_CR (16 KB)

7 1: Enabled
1..0 Mode
Bits Name ARM9 address
00 Video core 0x068A0000
01 Sub BG 0x06208000
10 Sub sprites 0x06600000
11 Extended sub BG palettes 0..3 *

* Not mapped in ARM9 CPU address space.

The 2D cores can use extended palettes, which are an additional 16 palettes of 256 colors each (8 KB per set). There is one set for each background (BG0..BG3).

For the main core, you can use bank E (all 4 sets loaded) or banks F or G (sets 0,1 and/or sets 2,3) to store the extended palettes.

For the sub core, you can only use bank H (all 4 sets loaded).

You need to set the VRAM bank owner bits correctly, and enable extended palettes in the DISPLAY_CONTROL register.


ARM9:

   0x240: retains 9b9b  0x242: retains 9f9f  0x244: retains 9f87  0x246: retains 039f  0x248: retains 8383    

On the ARM7: reads 0300

Thanks to Mic for some information on this page.