Graphic modes

From DSWiki

Jump to: navigation, search

Contents

[edit] Dual Screen

You should have noticed that your DS has two screens: a top screen and a bottom screen. When programming we also have a main screen and a sub screen. The top screen can be either the main or the sub screen. The bottom screen will be the sub screen if the top screen is the main screen, and vice versa.

[edit] Graphic Modes

graphic modes
mode main screen sub screen
MODE_0_2D

MODE_0_3D

BG0: text / 3D

BG1: text

BG2: text

BG3: text

BG0: text

BG1: text

BG2: text

BG3: text

MODE_1_2D

MODE_1_3D

BG0: text / 3D

BG1: text

BG2: text

BG3: rotation

BG0: text

BG1: text

BG2: text

BG3: rotation

MODE_2_2D

MODE_2_3D

BG0: text / 3D

BG1: text

BG2: rotation

BG3: rotation

BG0: text

BG1: text

BG2: rotation

BG3: rotation

MODE_3_2D

MODE_3_3D

BG0: text / 3D

BG1: text

BG2: text

BG3: extended rotation

BG0: text

BG1: text

BG2: text

BG3: extended rotation

MODE_4_2D

MODE_4_3D

BG0: text / 3D

BG1: text

BG2: rotation

BG3: extended rotation

BG0: text

BG1: text

BG2: rotation

BG3: extended rotation

MODE_5_2D

MODE_5_3D

BG0: text / 3D

BG1: text

BG2: extended rotation

BG3: extended rotation

BG0: text

BG1: text

BG2: extended rotation

BG3: extended rotation

MODE_6_2D

MODE_6_3D

BG0: 3D

BG1: -

BG2: large bitmap

BG3: -

not available

MODE_FB0

MODE_FB1

MODE_FB2

MODE_FB3

framebuffer not available

There are 8 graphic modes for the main screen and 6 graphic modes for the sub screen, you can combine them as you like. Each graphic mode has one, two or four backgrounds, which can be used. You can think of them as (on some spots transparent) layers in a graphic application. This way you can have a background with some image, another background with your animated character and another background with some text on top.

MODE_n_2D means, we use BG0 as text, MODE_n_3D means, we use BG0 as an OpenGL 3D surface (not availabe on sub screen). You can do 3D only on one screen this way. 3D on both screens at the same time is possible, but a bit more complicated (look for display capture below).

You can choose which modes you want to use with videoSetMode() for the main screen and videoSetModeSub() for the sub screen. Parameters are the wanted mode and the backgrounds you want to use (you can use just one or up to all four backgrounds).


 videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE);
 videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);

In this example, we want two extended rotation backgrounds on our main screen and one text background on our sub screen. The main screen is the top screen of our DS, if we want it to be the bottom screen, we can switch the screens with

 lcdSwap();

If we don't want to use a screen at all, we just use 0 as the parameter.

[edit] Background Types

We have six types of backgrounds:

  • framebuffer - The framebuffer is the simplest background, here we manipulate every pixel on our own. We have a region of memory which gets printed to the screen directly. It is 256*192 pixels in size and has 16 bit/pixel color (5 bits red, green and blue - bit 15 gets ignored).
  • 3D - We paint to a 3D background with OpenGL like commands, so we can't manipulate the pixels of the screen directly.
  • text - A text background (aka tile background) is divided into small blocks of 8x8 pixels. We can say, what these tiles should look like and say, what tile should get printed in a block. The largest amount of tiles that this mode supports is 64x64 tiles (512x512 pixels). Maps are arranged in 32x32 blocks(i.e. when using BG_64x64 the first forth of the map defines a 32x32 chunk of the map in the top left).
  • rotation - similar to text backgrounds, but you can also scale and rotate these layers. Rotation backgrounds support up to 128x128 tiles (1024x1024 pixels) and use 8bit maps instead of 16bit maps like text backgrounds. Rotation maps are arranged sequentially.
  • extended rotation - Can be used like the framebuffer, but also supports 8 bit images. The size of this buffers can be smaller or bigger that the actual resolution, but we can scroll, zoom, rotate etc. very easily in hardware here. If you use 16 bit per pixel, bit 15 will be the alpha bit.
  • large bitmap - a large 512*1024 or 1024*512 pixel image with 8 bit/pixel (this is already 512KiB, so we will need VRAM banks A-D!).


text variants
Resolution Defined Map Size Layout
256x256 BG_32x32 2 KiB 32x32
256x512 BG_32x64 4 KiB 32x64
512x256 BG_64x32 4 KiB (32x32)+(32x32)
512x512 BG_64x64 8 KiB (32x32)+(32x32)+(32x32)+(32x32)


rotation variants
Resolution Defined Map Size Layout
128x128 BG_RS_16x16 256 Bytes 16x16
256x256 BG_RS_32x32 1 KiB 32x32
512x512 BG_RS_64x64 4 KiB 64x64
1024x1024 BG_RS_128x128 16KiB 128x128


extended rotation variants
Resolution Size @ 8bit/pixel Size @ 16bit/pixel
128x128 16 KiB

BG_BMP8_128x128

32 KiB

BG_BMP16_128x128

256x256 64 KiB

BG_BMP8_256x256

128 KiB

BG_BMP16_256x256

512x256 128 KiB

BG_BMP8_512x256

256 KiB

BG_BMP16_512x256

512x512 256 KiB

BG_BMP8_512x512

512 KiB

BG_BMP16_512x512

(How to use these defines (BG_BMP8_512x512 etc.) will be explained later)

[edit] VRAM

VRAM
bank control register size what it can be used for
VRAM

VRAM_A

VRAM_A_CR 128 KiB
VRAM_A_LCD
VRAM_A_MAIN_BG_0x06000000 = VRAM_A_MAIN_BG
VRAM_A_MAIN_BG_0x06020000
VRAM_A_MAIN_BG_0x06040000
VRAM_A_MAIN_BG_0x06060000
VRAM_A_MAIN_SPRITE
VRAM_A_TEXTURE_SLOT0 = VRAM_A_TEXTURE
VRAM_A_TEXTURE_SLOT1
VRAM_A_TEXTURE_SLOT2
VRAM_A_TEXTURE_SLOT3
VRAM_B VRAM_B_CR 128 KiB
VRAM_B_LCD
VRAM_B_MAIN_BG_0x06000000
VRAM_B_MAIN_BG_0x06020000 = VRAM_B_MAIN_BG
VRAM_B_MAIN_BG_0x06040000
VRAM_B_MAIN_BG_0x06060000
VRAM_B_MAIN_SPRITE_0x06400000
VRAM_B_MAIN_SPRITE_0x06420000 = VRAM_B_MAIN_SPRITE
VRAM_B_TEXTURE_SLOT0
VRAM_B_TEXTURE_SLOT1 = VRAM_B_TEXTURE
VRAM_B_TEXTURE_SLOT2
VRAM_B_TEXTURE_SLOT3
VRAM_C VRAM_C_CR 128 KiB
VRAM_C_LCD
VRAM_C_MAIN_BG_0x06000000
VRAM_C_MAIN_BG_0x06020000
VRAM_C_MAIN_BG_0x06040000 = VRAM_C_MAIN_BG
VRAM_C_MAIN_BG_0x06060000
VRAM_C_ARM7_0x06000000 = VRAM_C_ARM7
VRAM_C_ARM7_0x06020000
VRAM_C_SUB_BG_0x06200000 = VRAM_C_SUB_BG
VRAM_C_SUB_BG_0x06220000
VRAM_C_SUB_BG_0x06240000
VRAM_C_SUB_BG_0x06260000
VRAM_C_TEXTURE_SLOT0
VRAM_C_TEXTURE_SLOT1
VRAM_C_TEXTURE_SLOT2 = VRAM_C_TEXTURE
VRAM_C_TEXTURE_SLOT3
VRAM_D VRAM_D_CR 128 KiB
VRAM_D_LCD
VRAM_D_MAIN_BG_0x06000000
VRAM_D_MAIN_BG_0x06020000
VRAM_D_MAIN_BG_0x06040000
VRAM_D_MAIN_BG_0x06060000 = VRAM_D_MAIN_BG
VRAM_D_ARM7_0x06000000
VRAM_D_ARM7_0x06020000 = VRAM_D_ARM7
VRAM_D_SUB_SPRITE
VRAM_D_TEXTURE_SLOT0
VRAM_D_TEXTURE_SLOT1
VRAM_D_TEXTURE_SLOT2
VRAM_D_TEXTURE_SLOT3 = VRAM_D_TEXTURE
VRAM_E VRAM_E_CR 64 KiB
VRAM_E_LCD
VRAM_E_MAIN_BG
VRAM_E_MAIN_SPRITE
VRAM_E_TEX_PALETTE
VRAM_E_BG_EXT_PALETTE
VRAM_E_OBJ_EXT_PALETTE
VRAM_F VRAM_F_CR 16 KiB
VRAM_F_LCD
VRAM_F_MAIN_BG
VRAM_F_MAIN_SPRITE_0x06000000 = VRAM_F_MAIN_SPRITE
VRAM_F_MAIN_SPRITE_0x06004000
VRAM_F_MAIN_SPRITE_0x06010000
VRAM_F_MAIN_SPRITE_0x06014000
VRAM_F_TEX_PALETTE
VRAM_F_BG_EXT_PALETTE
VRAM_F_OBJ_EXT_PALETTE
VRAM_G VRAM_G_CR 16 KiB
VRAM_G_LCD
VRAM_G_MAIN_BG
VRAM_G_MAIN_SPRITE_0x06000000 = VRAM_G_MAIN_SPRITE
VRAM_G_MAIN_SPRITE_0x06004000
VRAM_G_MAIN_SPRITE_0x06010000
VRAM_G_MAIN_SPRITE_0x06014000
VRAM_G_TEX_PALETTE
VRAM_G_BG_EXT_PALETTE
VRAM_G_OBJ_EXT_PALETTE
VRAM_H VRAM_H_CR 32 KiB
VRAM_H_LCD
VRAM_H_SUB_BG
VRAM_H_SUB_BG_EXT_PALETTE
VRAM_I VRAM_I_CR 16 KiB
VRAM_I_LCD
VRAM_I_SUB_BG
VRAM_I_SUB_SPRITE
VRAM_I_SUB_SPRITE_EXT_PALETTE

(See also Dev-Scene VRAM Table and gbatek)

Now we have to tell our DS, which VRAM banks it should use. The 656 KiB VRAM are accessable as nine banks with different sizes and purposes, if we need a bigger block of VRAM, we can use multiple banks together. This banks are available.

Note: VRAM is an alias for VRAM_A, not an extra bank. To use VRAM banks, we have to map them to special adresses begining at 0x06000000.

We have ten functions to set VRAM banks:

 void vramSetBankA(VRAM_A_TYPE a);
 (...)
 void vramSetBankI(VRAM_I_TYPE i);
 uint32 vramSetMainBanks(VRAM_A_TYPE a, VRAM_B_TYPE b, VRAM_C_TYPE c, VRAM_D_TYPE d);

vramSetMainBanks(a,b,c,d); does the same as vramSetBankA(a); vramSetBankB(b); vramSetBankC(c); vramSetBankD(d); but gives you the previously used config as a return parameter. This way you can easily restore the first four banks with

 void vramRestoreMainBanks(uint32 vramTemp);

Note: void vramRestorMainBanks(uint32 vramTemp); has been deprecated.

The VRAM_X_TYPE values are printed in the last column of the table. But what do these values mean?

  • VRAM_X_LCD: This is used for 3D and framebuffer mode.
  • VRAM_X_MAIN_BG_0x060n0000: Use this VRAM for the main screen. If we want 256 KiB, we have to map one screen to 0x06000000 and one to 0x06020000.
  • VRAM_X_SUB_BG_0x062n0000: Same with the sub screen.
  • VRAM_X_MAIN_SPRITE: Use this VRAM for sprites. It is mapped to 0x06400000 for bank A, 0x06420000 for bank B etc. up to bank D.
  • VRAM_X_SUB_SPRITE: Same with the sub screen at offset 0x06600000 to 0x06660000 for bank A to D.
  • VRAM_X_TEXTURE_SLOTn:
  • VRAM_X_ARM7:
  • VRAM_X_TEX_PALETTE:
  • VRAM_X_BG_EXT_PALETTE:
  • VRAM_X_SUB_BG_EXT_PALETTE:
  • VRAM_X_OBJ_EXT_PALETTE:
  • VRAM_X_SUB_SPRITE_EXT_PALETTE:

[edit] Background Control Register

[edit] One CR for each background

The DS has eight background control registers, one for each background for the main and sub screen. They are called REG_BGnCNT for the main screen and REG_BGnCNT_SUB for the sub screen. We use these registers to tell the DS where it can find the content of a background and what image format it will be. Let's look at an example:

 videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
 vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
 REG_BG3CNT = BG_BMP16_256x256 | BG_WRAP_ON;

We use MODE_5 on the main screen, but we only need background 3 (extended rotation). Then we map VRAM bank A to the address 0x06000000, so the main screen can use it. In the last line we tell the DS that background 3 is a 16 bit bitmap of size 256*256 pixels and will wrap around.

[edit] Parameters for the CR

Here is a list of parameters for REG_BGnCNT:

  • BG_{32x32|32x64|64x32|64x64}; used for text backgrounds
  • BG_RS_{16x16|32x32|64x64|128x128}; used for rotation backgrounds
  • BG_BMP{8|16}_{128x128|256x256|512x256|512x512}: extended rotation background variants, bit per pixel and resolution
  • BG_BMP8_1024x512 and BG_BMP8_512x1024: is used only for MODE 6
  • BG_WRAP_ON: if you scroll to the end of the image, it will wrap. This way, you can "scroll forever".This bit is for "extended rotation" backgrounds only. Other backgrounds automatically wrap when scrolling past their size.
  • BG_PRIORITY(n) or BG_PRIORITY_n: the priority of the background: 0 is the highest priority, 3 the lowest. A background with a higher priority will be printed on top of backgrounds with lower priorities. If there is a sprite with the same priority, it will be printed on top of the background.
  • BG_TILE_BASE(n): We have 16 blocks of RAM for tile data, each 16KiB big. This parameter selects which block we want to use. To get block n address, use BG_TILE_RAM(n) for main screen and BG_TILE_RAM_SUB(n) for sub screen.
  • BG_MAP_BASE(n): We have 32 blocks of RAM for tile data, each 2KiB big. This parameter selects which block we want to use. To get block n address, use BG_MAP_RAM(n) for main screen and BG_MAP_RAM_SUB(n) for sub screen.
  • BG_MOSAIC_ON: You have to set this flag if you want to use the mosaic effect (see below).

[edit] Other background registers

With n = 0, 1, 2 or 3:

  • REG_BGnHOFS: this controls where the left origin of the screen maps to the background
  • REG_BGnVOFS: this controls where the top of the screen maps to the background

These registers also have sub-screen equivalents (REG_BGnHOFS_SUB and REG_BGnVOFS_SUB).

[edit] Other extended rotation background registers

  • REG_BGnPA: this controls the x-axis scaling, it's a 0.8.8 fixed point number. If you don't want to scale at all, set it to 1.0 (which is 1 << 8). Increase the value to "zoom out", for example 2.0 (1 << 9) will show the background at half it's width.
  • REG_BGnPB: this is for rotating and shearing
  • REG_BGnPC: this is for rotating and shearing
  • REG_BGnPD: this controls the y-axis scaling, works the same as REG_BGnPA.

These registers specify a matrix which is used to map (either screen pixels to background pixels or the other way around - the GBA uses screen pixels to background pixels and has a similar system - please edit this if you know which). The resulting matrix is:

  A  B
  C  D

new x value = A*old x value + B*old y value new y value = C*old x value + D*old y value

  • REG_BGnX: this controls where the left origin of the screen maps to the background (in 0.8.8 fixed point too).
  • REG_BGnY: this controls where the top of the screen maps to the background (in 0.8.8 fixed point too).

When using a rotation background or extended rotation background, the BGn_CX and BGn_CY registers replace BGn_X0 and BGn_Y0. All of these registers also have sub-screen equivalents, formed by appending _SUB to the register name (eg REG_BGnPA_SUB)

[edit] Special registers

We have some more registers, which aren't specific for one background:

  • REG_MOSAIC / REG_MOSAIC_SUB: This controls the mosaic effect (looks like bigger pixels). You have to enable the effect for each background individually, as well as setting it here. The lower 4 bit define the mosaic size of the X-axis, bit 4-7 define the mosaic size of the Y-axis.
  • REG_BLDCNT / REG_BLDCNT_SUB: This register defines, what backgrounds we want to blend, or what background we want to fade to white/black (see examples below).
  • REG_BLDALPHA / REG_BLDALPHA_SUB: If we blend two backgrounds, bits 0-4 will define the blending coefficient of background A, bits 8-12 will define the blending coefficient of background B. The rest of this 16bit register seems to be unused. For a 50/50 blending you will just say: BLEND_AB = 0x0F | (0x0F << 8);
  • REG_BLDY / REG_BLDY_SUB: If we fade a background to white/black, the lowest 5 bits of this register tell the DS, how much white/black we want. 0x00 is the background, 0x1F is white/black.

Examples:

 // blend BG2 and BG3 on the main screen
 REG_BLDCNT = BLEND_ALPHA | BLEND_SRC_BG2 | BLEND_DST_BG3;
 // fade BG2 to black on the sub screen
 REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG2;

We have the following blending defines:

  • BLEND_NONE: no blending
  • BLEND_ALPHA: blend two backgrounds
  • BLEND_FADE_WHITE: fade to white
  • BLEND_FADE_BLACK: fade to black
  • BLEND_SRC_BGn: (n = 0,1,2,3) which background will be the source
  • BLEND_SRC_SPRITE:
  • BLEND_SRC_BACKDROP:
  • BLEND_DST_BGn: (n = 0,1,2,3) which background will be the destination
  • BLEND_DST_SPRITE:
  • BLEND_DST_BACKDROP:

Back to our registers:

Note that these registers are *not* prefixed with REG_

  • WINn_X0 / SUB_WINn_X0: (n = 0,1)
  • WINn_X1 / SUB_WINn_X1: (n = 0,1)
  • WINn_Y0 / SUB_WINn_Y0: (n = 0,1)
  • WINn_Y1 / SUB_WINn_Y1: (n = 0,1)
  • WIN_IN / SUB_WIN_IN:
  • WIN_OUT / SUB_WIN_OUT:

Side Notes:

  1. the source layer(s) must be over destination layer(s) to have some blending displayed. that means the priority of source layers should be numerically lower than the the priority of destination layers.
  2. the source layer is what is going to be translucent, the destination(s) is what is going to be seen through.
  3. if you have something white to be translucent (ghost, cloud, ...), make sure you pick an alpha value <15 or the white value will "eat up" the color on the other layer

[edit] Display Capture

There is a 32 bit Display capture control register REG_DISPCAPCNT and the following parameters:

  • DCAP_ENABLE BIT(31)
  • DCAP_MODE(n):
  • DCAP_DST(n):
  • DCAP_SRC(n):
  • DCAP_SIZE(n):
  • DCAP_OFFSET(n):
  • DCAP_BANK(n):
  • DCAP_B(n):
  • DCAP_A(n):

Here's an example of setting the capture register with comments

 // Comments taken from http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
 REG_DISPCAPCNT = DCAP_ENABLE |
 	DCAP_MODE(2) |	// Capture Source    (0=Source A, 1=Source B, 2/3=Sources A+B blended)
 	DCAP_DST(0) |	// VRAM Write Offset (0=00000h, 0=08000h, 0=10000h, 0=18000h)
 	DCAP_SRC(0) |	// Source A          (0=Graphics Screen BG+3D+OBJ, 1=3D Screen)
 	DCAP_SIZE(3) |	// Capture Size      (0=128x128, 1=256x64, 2=256x128, 3=256x192 dots)
 	DCAP_OFFSET(0)|	// VRAM Read Offset  (0=00000h, 0=08000h, 0=10000h, 0=18000h)
 	DCAP_BANK(2) |	// VRAM Write Block  (0..3 = VRAM A..D) (VRAM must be allocated to LCDC)
 	DCAP_B(0) |	// EVB (0..16, or 0..31 ?) Blending Factor for Source A (or B ?)
 	DCAP_A(14);	// EVA (0..16, or 0..31 ?) Blending Factor for Source B (or A ?)

[edit] Other Resources

Graphics Modes chart at Dev-Scene

Personal tools