gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > How to set different backgrounds to use different palettes?

#154605 - Polaris - Sat Apr 19, 2008 1:43 am

I'm having some trouble to make two different backgrounds use different parts of the BG_PALETTE (SUB in this case).

This is what I got so far.

Code:

u16 *mapMemorySub = (u16*)BG_MAP_RAM_SUB(2);
u8 *tileMemorySub = (u8*)BG_TILE_RAM_SUB(1);

u16 *controlsMapMemory = (u16*)BG_MAP_RAM_SUB(4);
u8 *controlsTileMemory = (u8*)BG_TILE_RAM_SUB(5);

BACKGROUND_SUB.control[0] = BG_32x64 | BG_COLOR_16 | BG_MAP_BASE(2) | BG_TILE_BASE(1) | BG_PRIORITY(1);
BACKGROUND_SUB.control[2] = BG_32x32 | BG_COLOR_16 | BG_MAP_BASE(4) | BG_TILE_BASE(5) | BG_PRIORITY(0);
      
dmaCopy(BGTilesPal, BG_PALETTE_SUB, BGTilesPalLen);
dmaCopy(ControlsPal, &BG_PALETTE_SUB[16], ControlsPalLen);

dmaCopy(BGTiles, tileMemorySub, BGTilesLen);
dmaCopy(ControlsTiles, controlsTileMemory, ControlsTilesLen);

for(u16 i=0; i<sizeof(BGMap)/2; i++){
   mapMemorySub[i] = 0;
}
for(u16 i=0; i<sizeof(ControlsMap); i++){
   controlsMapMemory[i] = Controls_map[i];
}


Anyone that understands a bit of what's going on in here will probably figure out that what is happening is that both backgrounds get painted using only the first 16 palette values. So the second image Controls.png in this case shows up, but with the wrong colors.

I looked around a bit on the forums first and found that each tile has 15 bits that describe it, or something like that. And that if I want to tell each tile of a given background to use a specific 16 color palette I should do so by modifying bit 12-15.Theory is fine and I almost understand it, but I can't for the love of god make it work in practice!

In my specific case, where should I apply 1 << 12 in order for the tiles of Background 2 to use the values starting from BG_PALETTE_SUB[16]?

Since i'm in the bit 12-15 range, I have another question :P

Each tile has 4 bits to tell it which palette it should use, if all bits are set to 0 it uses the first palette. I'm assuming that setting each bit separately gives the tile access to the 2nd, 3rd, 4th and 5th palettes respectively. But how should I set those bits if I want to use from the sixth palette onwards?


Last edited by Polaris on Sat Apr 19, 2008 4:27 pm; edited 1 time in total

#154610 - eKid - Sat Apr 19, 2008 4:53 am

No, :P .. The top 4 bits are a 4-bit binary number. It goes like this:
0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
Thats 0->15 in binary. Setting each bit separately would give you the 2nd, 3rd, 5th, and 9th palette.
To use palette 1 for the 'controls' BG, add "(1<<12)" to Controls_map. For other palettes it is simply (palette_number<<12).
Code:

for(u16 i=0; i<sizeof([b]ControlsMap[/b]); i++){
   controlsMapMemory[i] = Controls_map[i] | (1<<12); // 'or' the palette number to each tile entry
}


Each background tile has a palette setting, so one background can use many palettes. There's also a couple bits in each background tile that allows flipping horizontally or vertically.

#154617 - TwentySeven - Sat Apr 19, 2008 6:56 am

See here

http://liranuna.drunkencoders.com/nds-2d-tuts/lesson-3/

#154635 - Polaris - Sat Apr 19, 2008 4:42 pm

This was highly enleightening! I'm sure it will be very usefull to others bumping into the same problem. I was smelling the binary setup, maybe I should learn those values by heart. Seems like they are usefull to know for other things too.

I checked Liranuna's blog repeteadly before making this thread but what was confusing me was the line that says:

Code:
// Setting a pointer to the BG0’s map base
 u16* bg0Map = (u16*)BG_TILE_RAM(0);


bg0Map gets it's bits changed to achieve the palette swap. The confusing part is that in what I'm doing I have to change the bits of BG_MAP_RAM_SUB.

Are TILE_RAM and MAP_RAM interchangable in this case? Or is it just that TILE_RAM is a pointer to MAP_RAM? Hence, if I change the first i'm affecting the second one?

#154638 - eKid - Sat Apr 19, 2008 5:18 pm

Hmm, that has to be a mistake. TILE_RAM is for selecting 'character base blocks' which are aligned by 16kB. MAP_RAM is for selecting a tilemap block, which is aligned by 2kB. From background.h:
Code:
#define BG_MAP_RAM(base)      (((base)*0x800) + 0x06000000)
#define BG_MAP_RAM_SUB(base)   (((base)*0x800) + 0x06200000)

#define BG_TILE_RAM(base)      (((base)*0x4000) + 0x06000000)
#define BG_TILE_RAM_SUB(base)   (((base)*0x4000) + 0x06200000)

The code works fine because it uses a zero value so it gives the same value as if it used the BG_MAP_RAM definition.

You should use BG_MAP_RAM(_SUB) for selecting map data blocks and BG_TILE_RAM(_SUB) for selecting tile/graphical data blocks.