LiraNuna's Development Blog

Nintendo DS 2D HW Tutorials
By LiraNuna

Lesson 5: Extended Palettes and Rotation

Table of content

Introduction
Extended Palettes
Extended backgrounds
Background rotation
Lesson demo


Introduction
This lesson is going to be the last covering backgrounds, simply because there are no more background specific subjects to be taught. If you have come this far, you should know that the DS is not a frightening hardware, and most of it is designed to make you, the programmer, easy coding life when approaching the low level.
Extended palettes are a new hardware feature introduced on the DS, and is fairly undocumented in homebrew land. Even though using extended palettes on the DS is fairly simple, homebrew developers are trying to avoid using them because of the said lack in documentations. This tutorial will do it’s best covering this subject.
Another subject to be covered in this lesson, is background rotation, which might look intimidating for some programmers, but if you have followed the previous lessons, you already know the DS’s HW is programmer-friendly.
This lesson will also touch extended backgrounds in bitmap mode for the sack of compilation.

Extended Palettes
Lesson 3 went through on using several 16col palettes on the same tile graphics, showing up to 16×16 color on screen. Extended palettes are a new feature not presented on the GBA, that enables a background to use up to 256 colors per tile across 16 different palettes, showing up to 256×16 colors on screen (4096 colors). Since the default palette that is located in 0x05000000 (aka BG_PALETTE as a libnds define) can only hold 256 colors for the main BG layers, we will have to allocate a VRAM bank to save our palette info in them.
This is where the catch comes – there is no static address that holds extended palettes data, so the data itself is being stored in the VRAM bank itself (unlike tile/map data where the VRAM allocates itself to a fixed address).
To write data to an extended palette, we’ll have to write the data directly to VRAM while it’s set as VRAM_LCD mode (0x00) and enabled (VRAM_ENABLE – 0x80) before writing, copy the data inside the VRAM and then set the VRAM as an extended palette holder.

	// Set VRAM x to LCD mode - unlock it for writing
VRAM_x_CR = VRAM_ENABLE | VRAM_LCD;
 
// Copy our palette over
memcpy(VRAM_x, extPaletteToCopy, SIZE_OF(extPaletteToCopy));
 
	// Lock VRAM x back to extended palette
VRAM_x_CR = VRAM_ENABLE | VRAM_x_BG_EXT_PALETTE;

Now that the hard part is behind us, all we have to do is to enable the extended palettes. This is done in three simple steps:
First, is to enable the extended palette bit in the main display register of the screen we want to use (In this lesson, we’ll use the main core). This is done by setting bit 30 on the display register, predefined as DISPLAY_BG_EXT_PALETTE on libnds.

DISPLAY_CR = ... | DISPLAY_BG_EXT_PALETTE;

Next step, is to set the background to use 256 colors (Because extended palettes are 4096 colors total, each 256 colors spread along 16 palettes). This is a totally logical step which you will probably won’t consider as one.

REG_BGxCNT = ... | BG_COLOR_256;

Final step, would be using the same approach of using more then one palette on 16 color mode – setting map palette attribute to the palette entry we desire to use. This is usually done by graphics converters such as gfx2gba, as explained on Lesson 4.
Of course if you want to use more then 256 colors per tiled background, using meta-palettes is also an option, but will be discussed on later lessons.

Extended backgrounds
Another HW feature that got introduced on the DS is the direct bitmap backgrounds noticeable in use in modes 3-5. Similar to the GBA’s frame buffer modes (which were actually single background modes), we got a new set of video modes on the DS, capable of (theoretically) showing up to two text backgrounds and two direct bitmap backgrounds simultaneously. Since extended background can be either a normal background with rotation attributes, an 8bit (256col) direct bitmap background or a 16bit direct bitmap background, I will only cover the two direct bitmap modes.
A direct bitmap mode is said to be the most friendly to learn for beginners – this is why I teach it in the end – so you will see how wrong that assumption is.
The mode is considered friendly because of it’s ability to ‘plot pixels’ directly to the background’s buffer, making it easier for novice programmers to get a hold on embedded systems. This is of course a bad way to teach low level programming, because once the novice programmer has his ‘plot pixel’ routine, he will only use it for his needs, building a bridge between low level and his own higher level architecture.
Extended backgrounds have no special attribute set on their control register – they use the exact same ‘scheme’ for normal roto-scale backgrounds, but are treated different (on different video modes). libnds has several defines regarding extended backgrounds, which treats them as ‘BMP’ backgrounds.
Those set of defines can be generalized by BG_BMPp_WIDTHxHEIGHT, where ‘p’ is either 8 or 16 (8bit or 6bit color mode), WIDTH and HEIGHT are either 256 or 512, depending on buffer size. On this lesson we will use an 8bit (256 colors) 256×256 sized background.
Extended backgrounds in bitmap mode do not have maps – because they have a linear buffer treated as a virtual 2D array, starting from their BMP base, which is exactly just like a tile base – a 16kb block of memory, just named differently.

To convert data for an 8bit bitmap background, we just eliminate the two -m and -t8 options with additional -c256 flag, and gfx2gba will automatically adjust itself to ‘raw’ output in addition to a palette.

Background rotation
Background rotation can only occur on backgrounds 2 or 3, if video mode allows it.
Rotation is done by a 2×2 rotation matrix, also called P. Since this is not a math lesson, I will not cover anything about it – this is Wikipedia’s job.
What you can see from this article, is mostly the image regarding rotation:


Rotation matrix
Since the DS has no floating point support, and matrices rely on fractions, the DS uses four 16bit registers for each rotate-able background (BG2 and BG3), as a set of 8.8 fixed-point numbers.
libnds provides us with a precalced look up table for sine and cosine values, pre-calculated as 4.12 fixed points, so to convert those to usable data for our matrix, all we need to do is shift right 4 times.
The four registers that are reserved for the rotation matrix for each rotation enabled background are called:

// x is either 2 or 3
REG_BGxPA // First matrix entry
REG_BGxPB // Second matrix entry
REG_BGxPC // Third matrix entry
REG_BGxPD // Last matrix entry

For more information regarding the sine/cosine look up tables, please refer to this lesson’s demo.

Lesson demo
This lesson’s demo is combined of two backgrounds – one is a normal text background that uses the first extended palette on VRAM F, and the second background is an 8bit roto-scale background, rotating in a sine wave.

Download full project source and binary HERE.