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 > Banks assignement on main- and sub-screens

#148663 - nipil - Tue Jan 08, 2008 2:26 pm

"Disclaimer" :
i do apologize for the length of this post. I write lots of stuff, as it helps
me be sure i'm not confusing while writing it, and provides all the info i
managed to gather, which (i hope) helps to find the answers to the
questions i ask ;)


Right now, i've been doing my stuff on main screen, using console output on sub to debug (both mode5). I was setting VRAM A&B to main background.

I'm currently using :
- BG_MAP_BASE(0) (16k of maps available)
- BG_TILE_BASE(1) (16k of sprites available)
- an extended 256x256@16 BG3 (128k of memory available)

I just realize i was "wasting" memory by assigning B, which i might use for something else later.
So i decided to change the setting from A+B to A(128k)+F(16k)+G(16k) :
Code:
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
vramSetBankF(VRAM_F_MAIN_BG);
vramSetBankG(VRAM_G_MAIN_BG);

Then i realized banks F & G didn't specify adresses to map to. So i took a look at gbatek's VRAM memory control. There i found:
Code:
VRAM    SIZE  MST  OFS   ARM9, 2D Graphics Engine A, BG-VRAM (max 512K)
A,B,C,D 128K  1    0..3  6000000h+(20000h*OFS)
E       64K   1    -     6000000h
F,G     16K   1    0..3  6000000h+(4000h*OFS.0)+(10000h*OFS.1)

What i understand from this is that contrary to A, for F&G, OFS is not a counter :
- A can be mapped to 600:0000, and "ends" at 601:FFFFh.
- F can be mapped to 4 different adresses using the 2 lower bits of the 4-bits OFS
- G is the same as F

Possible base F addresses are then :
- 600:0000h (OFS=0) ending at 600:3FFFh
- 600:4000h (OFS=1) ending at 600:7FFFh
- 601:0000h (OFS=2) ending at 601:3FFFh
- 601:4000h (OFS=3) ending at 601:7FFFh

I thought i would have mapped it as shown below (each letter being a 16k block) :
Code:
|<- VRAM base 600:0000h

Target placement
|AAAAAAAA........
|........F.......
|.........G......

Possible F & G placements using OFS
|AAAAAAAA........
|FF..FF..........
|GG..GG..........

As you can see, A overlaps F or G no matter OFS. So i guess i cannot achieve target placement.
In turn, i *could* invert the positions of the banks, as shown below :
Code:
Potential solution by moving A to 602:0000h
|........AAAAAAAA
|FF..FF..........
|GG..GG..........

Let's say i retain this one :
|..uuuuuu........ unused adresses
|........AAAAAAAA
|F............... (OFS=0)
|.G.............. (OFS=1)

Now we reached this point, i have, as you can guess, some questions :
- Can we really order the mapping as we want ?
- Is there a problem with the 6 unused (u) 16k adresse blocks ?
- There's a define for A on 602:0000h, but i don't seeany define to place F or G (ie using OFS lower bits), how do i do it ?
- I'm currently using the first code-block (F & G without adresses). I fell there's a problem with it, but it works (in no$gba). Is it normal ?



The next thing i plan to do is to display exactly the same thing on both screens.
As such, i have to configure banks for the sub engine. The same page from gbatek gives me and the associate placement :
Code:
GbaTek:
VRAM    SIZE  MST  OFS   ARM9, 2D Graphics Engine B, BG-VRAM (max 128K)
C       128K  4    -     6200000h
H       32K   1    -     6200000h
I       16K   1    -     6208000h

Associated placement :
|........CCCCCCCC
|........H.......
|..........G.....

As stated, max usable memory is 128k (ie, no using C plus another bank). Anyway, H and G overlap with C.

Final question is :
- What are my options for sub-engine configuration ?

#148710 - knight0fdragon - Wed Jan 09, 2008 4:00 am

looks to me like the best solution for you is to map it like so

FGXXXXXXAAAAAAAA
but, unfortunately you can only use a max of 128k for the sub screen, so this is not possible.

now in the method you have mentioned above, you would set the BG3 BMP_BASE to 8, so that it goes to memory A

then you want to set TILE_BASE to 0, and set MAP_BASE to 15

this will give you 30720Bytes of tile memory to deal with, with the last 2048 bytes for map memory.

now, another trick you can pull determines on how large the BMP image is.

if you are only going to use an image of 256x192 at 16bpp, that leaves you 32K at the end of VRAM A to do the exact same thing you would be doing in VRAM F and G, but instead you would set your TILE_BASE to 0, your MAP_BASE to 15, and set the BMP_BASE to 2
_________________
http://www.myspace.com/knight0fdragonds

MK DS FC: Dragon 330772 075464
AC WW FC: Anthony SamsClub 1933-3433-9458
MPFH: Dragon 0215 4231 1206

#148725 - nipil - Wed Jan 09, 2008 11:59 am

knight0fdragon wrote:
now in the method you have mentioned above, you would set the BG3 BMP_BASE to 8, so that it goes to memory A
then you want to set TILE_BASE to 0, and set MAP_BASE to 15

So i should have for main screen :
- VRAM_A_MAIN_BG_0x06020000, as BMP_BASE(8) maps to 602:0000h
- BG3_CR = ... | BMP_BASE(8)
- VRAM_F_MAIN_BG ... mapped where? Presumably 600:0000h. Confirmation ?
- VRAM_G_MAIN_BG ... mapped where ? How to specifiy to map it at 600:4000h ?
- BG0_CR = ... | BG_MAP_BASE(15) | BG_TILE_BASE(0)

=> And i have a block space :
- used from 600:0000h to 600:7FFFh
- empty from 600:8000h to 601:FFFFh
- usd from 602:0000h to 603:FFFFh

Then :
BMP_BASE_RAM(8) is then ok (602:0000h to 603:FFFFh) in A
BG_TILE_BASE(0) is then ok (600:0000h to 600:77FFh) in F
BG_MAP_BASE(15) is then ok (600:7800h to 600:7FFFh) if G is mapped at 600:4000h !

Is it ok ? What about G placement (bold above) ?

knight0fdragon wrote:
if you are only going to use an image of 256x192 at 16bpp, that leaves you 32K at the end of VRAM A to do the exact same thing you would be doing in VRAM F and G right now

i'm using all the 256x256 pixels (rot/scrolling BG3) so this is not quite posible right now.
To solve the problem on sub engine, i'll try and use 8bpp instead of 16 (so only half the C-bank is used)

#148748 - knight0fdragon - Wed Jan 09, 2008 7:16 pm

it looks like there are no macros for F and G right now to do what you want, so you will have to add the following lines

VRAM_F_MAIN_BG_0x06000000 = 1;
VRAM_F_MAIN_BG_0x06004000 = 1 | VRAM_OFFSET(1);
VRAM_F_MAIN_BG_0x06010000 = 1 | VRAM_OFFSET(2);
VRAM_F_MAIN_BG_0x06014000 = 1 | VRAM_OFFSET(3);

VRAM_G_MAIN_BG_0x06000000 = 1;
VRAM_G_MAIN_BG_0x06004000 = 1 | VRAM_OFFSET(1);
VRAM_G_MAIN_BG_0x06010000 = 1 | VRAM_OFFSET(2);
VRAM_G_MAIN_BG_0x06014000 = 1 | VRAM_OFFSET(3);
_________________
http://www.myspace.com/knight0fdragonds

MK DS FC: Dragon 330772 075464
AC WW FC: Anthony SamsClub 1933-3433-9458
MPFH: Dragon 0215 4231 1206

#148749 - nipil - Wed Jan 09, 2008 8:50 pm

Aw, it's that simple ? ;)

I thought that if it did not appear in the libnds defines,
it was for some reasons not possible. Thanks a lot mate !

#150440 - krozen - Mon Feb 04, 2008 4:39 pm

Thanks for the interesting posts guys. Helping me get my head around these things!

Quote:

PostPosted: Wed Jan 09, 2008 6:16 pm Post subject:
it looks like there are no macros for F and G right now to do what you want, so you will have to add the following lines

VRAM_F_MAIN_BG_0x06000000 = 1;
VRAM_F_MAIN_BG_0x06004000 = 1 | VRAM_OFFSET(1);
VRAM_F_MAIN_BG_0x06010000 = 1 | VRAM_OFFSET(2);
VRAM_F_MAIN_BG_0x06014000 = 1 | VRAM_OFFSET(3);


This is indeed helpful. One question though. There's a gap of 16k between VRAM_F_MAIN_BG_0x06000000 and VRAM_F_MAIN_BG_0x06004000, and another 16k gap between VRAM_F_MAIN_BG_0x06010000 and VRAM_F_MAIN_BG_0x06014000. Why is there a 48k gap between VRAM_F_MAIN_BG_0x06004000 and VRAM_F_MAIN_BG_0x06010000? Is this due to the VRAM_OFFSET call?
I've used this code to assign F and G to contigious parts of memory. It works fine if they are offset beteen 0 and 1, and again between 2 and 3. But there is a big gap between 1 and 2! Is there any way of addressing the data from VRAM_F_MAIN_BG_0x06004000 in 16k gaps using VRAM_OFFSET?

One more thing: If I use VRAM_OFFSET(4) in bank G, it seems to map to memory bank to the start of video memory again back to the start of video memory again (i.e VRAM_F_MAIN_BG_0x06000000).

Cheers!

#150525 - Cydrak - Wed Feb 06, 2008 3:34 am

Yeah, offsets 4,8,12... are indeed the same as 0. I guess it's only 2 bits.

The best way to understand banks, IMHO:
1) Fill them all with different colors, so you can recognize each one.
2) Throw BG2 or 3 into a huge bitmap mode (512x512 8bit for 256K, 16bit for 512K).
3) Scroll around, or scale so you can see the whole thing.
4) Similar tricks can be done with sprites, palettes and textures.

Now you have a little VRAM viewer, and can play around with the bank values. If you do that, you should find the reason for the "gap"--there isn't any, exactly. I was surprised to see F and G show up in _two_ places, 32 KB apart!

Here's what I get for different banks. Behavior is largely the same, regardless of what the banks are mapped to:
Code:
A-D, VRAM_OFFSET(n): maps at 128KB*n
E                    [EEEE....] (fixed)
F/G, VRAM_OFFSET(0): [X.X.....] ( 0KB,  32KB)
F/G, VRAM_OFFSET(1): [.X.X....] (16KB,  48KB)
F/G, VRAM_OFFSET(2): [....X.X.] (64KB,  96KB)
F/G, VRAM_OFFSET(3): [.....X.X] (80KB, 112KB)
C/D, subscreen       [XXXXXXXX] (mirrors every 128KB)
H, sub BG            [HH..HH..] (every other 32KB)
I, sub BG            [..II..II] (twice every other 32KB)
I, sub OBJ           [IIIIIIII] (every 16KB)

So, F and G can map anywhere in the first 128 KB. Maybe something like:
Code:
// n = 0..7 (* 16 KB)
#define VRAM_F_G_OFFSET(n)  ( ((n)>>1 & 2) | ((n) & 1) )


I know nobody asked about bank E, but the fixed location bugs me, leaving a gap if you add bank A and such. I thought of a possible solution to that. Fussing around a bit more, I noticed main BG addressing wraps around at 512 KB, and main OBJs wrap at 256 KB. The ARM9 0x06xxxxxx ranges do it, too.

By shifting the BG base or OBJ index, this should allow A..D to be contiguous with E:
Code:
0x6000000 + 0 KB     128      256      384      0
BG:        [EEEE.... ........ CCCCCCCC DDDDDDDD EEEE....]
                              ^ add 256 KB to all BG base

DISPLAY_CR has global map/tile offsets that might be useful here. I don't think there's a bitmap offset, probably as unlike the others, BG_BMP_BASE covers the whole range.