The knowledge is scattered, in simple examples, unfinished tutorials and tables. Here an effort to put it all together.
Our goal: getting a tiled background and a bitmap together, the bitmap serving as a frame around a game like chess, or minesweeper....without mixing up the memory by overlapping.
Most of the times the examples (see devkitPro) are clear while so simple. But combining some ideas immediately shows the complexity of the memory mappings the videorams and the BG registers.
The starting tile example is from Liranuna's blog: (lesson 3 and 4)
But we want to combine a bmp-background with the tiles, and we get into the trouble of mem overlapping, resulting in bad graphics.
Here a table and registers from:
http://www.dspassme.com/programmers_guide/tutorial/registers.html#bg0_cr
For the main screen:
Background Tile/Map Addresses Care must be taken in choosing the map and graphic addresses as they overlap. (Indeed!)
| Address | Map Addresses | Graphic Addresses | |||||||
| 0x06000000 | BG_MAP_RAM(0) | BG_TILE_RAM(0) | |||||||
| 0x06000800 | BG_MAP_RAM(1) | ||||||||
| 0x06001000 | BG_MAP_RAM(2) | ||||||||
| 0x06001800 | BG_MAP_RAM(3) | ||||||||
| 0x06002000 | BG_MAP_RAM(4) | ||||||||
| 0x06002800 | BG_MAP_RAM(5) | ||||||||
| 0x06003000 | BG_MAP_RAM(6) | ||||||||
| 0x06003800 | BG_MAP_RAM(7) | ||||||||
| 0x06004000 | BG_MAP_RAM(8) | BG_TILE_RAM(1) | |||||||
| 0x06004800 | BG_MAP_RAM(9) | ||||||||
| 0x06005000 | BG_MAP_RAM(10) | ||||||||
| 0x06005800 | BG_MAP_RAM(11) | ||||||||
| 0x06006000 | BG_MAP_RAM(12) | ||||||||
| 0x06006800 | BG_MAP_RAM(13) | ||||||||
| 0x06007000 | BG_MAP_RAM(14) | ||||||||
| 0x06007800 | BG_MAP_RAM(15) | ||||||||
| 0x06008000 | BG_MAP_RAM(16) | BG_TILE_RAM(2) | |||||||
| 0x06008800 | BG_MAP_RAM(17) | ||||||||
| 0x06009000 | BG_MAP_RAM(18) | ||||||||
| 0x06009800 | BG_MAP_RAM(19) | ||||||||
| 0x0600A000 | BG_MAP_RAM(20) | ||||||||
| 0x0600A800 | BG_MAP_RAM(21) | ||||||||
| 0x0600B000 | BG_MAP_RAM(22) | ||||||||
| 0x0600B800 | BG_MAP_RAM(23) | ||||||||
| 0x0600C000 | BG_MAP_RAM(24) | BG_TILE_RAM(3) | |||||||
| 0x0600C800 | BG_MAP_RAM(25) | ||||||||
| 0x0600D000 | BG_MAP_RAM(26) | ||||||||
| 0x0600D800 | BG_MAP_RAM(27) | ||||||||
| 0x0600E000 | BG_MAP_RAM(28) | ||||||||
| 0x0600E800 | BG_MAP_RAM(29) | ||||||||
| 0x0600F000 | BG_MAP_RAM(30) | ||||||||
| 0x0600F800 | BG_MAP_RAM(31) | ||||||||
DISPLAY_CR (0x04000000)
| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
| 31 | BGExtPal | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | FBBank | ExtMode | ||
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| SprWin | Win1 | Win0 | Obj | BG3 | BG2 | BG1 | BG0 | BlnkScr | U6 | OAMHorzBlank | ObjMapMode | 3D | Mode | ||
BG0_CR (0x04000008)
This 16 bit register controls the features related to background #0 on the main display. To activate this register, this background must be enabled in the DISPLAY_CR (0x04000000).| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Size | Wrap | Map | Color | Mosaic | Tile | Pri | |||||||||
So, in this example:
http://www.dspassme.com/programmers_guide/tutorial/using_tiles.html#tile02
for the main screen:
POWER_CR = POWER_ALL_2D;PS, so this works for the main screen, but don't think that you can copy this frame right away to the sub screen. The subscreen mem is much smaller, as you can see further on, of course an image can be displayed, as can be text, even from your own 16x8 font, but the red frame poses more problems!
vramSetBankA(VRAM_A_MAIN_BG);
DISPLAY_CR = MODE_0_2D | DISPLAY_BG0_ACTIVE;
BG0_CR = BG_256_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(20);
These last three lines form a chain, combining a memory location to the videoram
tile base on 0 and map base on (a safe???) 20.
In Liranuna's example, apparently the map is smaller and put in front:
BG0_CR = BG_32x32 | BG_COLOR_16 | BG_MAP_BASE(0) | BG_TILE_BASE(1);
the map first and the tiles behind it.
Then we have to copy the tiles and palettes
memcpy((void*)BG_TILE_RAM(1), arrowTile_bin, arrowTile_bin_size);
u16* bg0Map = (u16*)BG_TILE_RAM(0);//making a pointer to the map we can calculate where to put tiles.
Adding another background? A bitmap this time, two tile-bg's would be too much :-)
vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000);
and now
either this going for 0x06010000
BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(4) ; //this is 0x06010000
u16* backBuffer = (u16*)(0x06000000 + 256 * 256 * 1 );
or this aiming at 0x06020000
BG3_CR = BG_BMP16_256x256 | BG_BMP_BASE(8) ; //this is 0x06020000
u16* backBuffer = (u16*)(0x06000000 + 256 * 256 * 2 );
is possible....
BG3_XDX = 1 << bg3_xdy =" 0;" bg3_ydx =" 0;" bg3_ydy =" 1" bg3_cx =" 0;" bg3_cy =" 0;" class="mw-headline">Map Entries
from
http://dev-scene.com/NDS/Tutorials_Day_4
of course also this example is explaining the same procedure, only it gives the tiles as a matrix.
(The last entry of this excelent tutorial.....)
The complete main.c of lesson 3 of Liranuna, but with an extra background becomes:
// Including libnds’ set of defines
#include0x06000800
// Include basic memory functions
#include
// Including our converted graphics
#include "arrowTile_bin.h"
// Macro to translate 2D coord into 1D map array
#define POS2IDX(x, y) (x + (y*32))
// Set of defines for tile flipping
#define TILE_FLIP_NONE (0 << reg_powercnt =" POWER_ALL_2D;" display_cr =" MODE_5_2D" bg0_cr =" BG_32x32" vram_a_cr =" VRAM_ENABLE" bg0map =" (u16*)BG_TILE_RAM(0);" bg0map =" (u16*)BG_MAP_BASE(0);" bg3_cr =" BG_BMP16_256x256" backbuffer =" (u16*)(0x06000000" bg3_cr =" BG_BMP16_256x256" backbuffer =" (u16*)(0x06000000" bg3_xdx =" 1" bg3_xdy =" 0;" bg3_ydx =" 0;" bg3_ydy =" 1" bg3_cx =" 0;" bg3_cy =" 0;" colormask =" 0x1F;" iy =" 0;" ix =" 0;" iy =" 186;" ix =" 0;" iy =" 0;" ix =" 240;" iy =" 0;" ix =" 0;">which gives the tiles in a frame of red, located on another background layer
Liranuna gives a lesson 4 exemple with two backgrounds.
Very usefull.
I redesigned the frame exemple above with the arrows and a tiled image background.
Because the arrows are 16 colors and this tiled background 256 colors i had to shift
the colors of the tiled background, using gfx2gba, shifting 64 = 4 x 16 colors.
//gfx2gba -c256 -St.tls -t8 -St.tls -C64 -v0 -pback.pal -m back.bmp
then loading also shifted:
void *paletteBuffer = (void *)&BG_PALETTE[64] ;
(and dmaCopy(paletteData, paletteBuffer, paletteSize); of course)
This is how the palette looks, with four 16 color palettes and behind it the colors of the tiled background:This is the 256 color map at 0x0610000, = BG_TILE_RAM(4), and map BG_MAP_RAM(1) =
arrows at: BG_TILE_BASE(3) = 0x0600C000 , tiles and BG_MAP_BASE(0), map (see table above )
These examples about background organization can be found here:
Above example,using the Liranuna's arrows and adding a red frame
Second example, 2 tiled background 16/256 color (arrows and image) example
If you wonder why Liranuna used a 16x8 arrow in his example, read the following blog!
Main backgrounds: 0x06000000 - 0x06400000
Sub backgrounds: 0x06020000 - 0x06021000 which is much smaller
This is a useful link with all kinds of register definitions, and here you can see the differences between VRAM_A VRAM_C and for instance VRAM_B:
http://takuto.info/libnds/arm9/video_8h.html#3bce26742d17eb8c77cf7338089f3ccf7cb3c69e848e7b5f045e932ee1e41f94
So the frame drawing (in the example red) on a bitmap can be done on the MAIN in mode 5.
double tile - backgrounds can be done, both on MAIN and SUB, in mode 0
on the SUB drawing on a bitmap (the red frame example) does not seem to be possible, in mode 5?
Yes, this is possible, but you can only use one background (apparently)
This is the example:
simple script to see drawing on both screen in mode 5



