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 > Text + bitmaps = grief (hey I fixed it yay)

#144116 - HyperHacker - Mon Oct 29, 2007 6:17 am

After a lot of struggling and searching around I finally managed to get both screens having a text layer and a 16-bit bitmap layer, but it involved an ugly hack in which the top 64 pixels of the bitmap are overwritten by the tilemap and character set and just get scrolled off the top of the screen. I'd like to put a second text layer (using the same character set and palettes) on each screen and a second bitmap on the main screen. I have no idea how to go about doing this.

Only 256x192 of each layer is used, so the top or bottom 64 rows of each bitmap and the top or bottom 8 rows of each text layer can get overwritten.

Right now each screen uses BG0 as text and BG3 as bitmap. Bank A is VRAM_A_MAIN_BG_0x06000000, C is VRAM_C_SUB_BG_0x06200000, everything else is unused. It looks like there should be enough VRAM left to pull this off:

Main text 1: 1.5k
Main text 2: 1.5k
Main character set: 16k
Main bitmap 1: 96k
Main bitmap 2: 96k
=211K

Sub text 1: 1.5k
Sub text 2: 1.5k
Sub character set: 16k
Sub bitmap: 96k
=115K, for a total of 326K. I could shave 16K from that if I could use the same character set for both screens, but it looks like there's no way to do that. :-/

If it's really necessary I could probably get away with only showing 8 pixels of the main screen's second bitmap at a time. It'd be a bit of a pain, though. Or I could use a single 512x256 or 256x512 bitmap and scroll it around, but that seems like it'd eat up even more VRAM.

So is this configuration possible? It sure looks like I can just use A and B for the main screen and C for the subscreen, but every time I try to change this stuff, I just break it. <_<

The idea here is the main screen has a menu on it with a background. The second bitmap gets turned on and off (actually scrolled on and off the screen) in HBlank so that it only appears behind the currently selected option, so only 8 rows of it are visible at a time. However I want to be able to choose between two different ways that this would work:
#1: The top 8 rows of the image are shown behind the selected option (like Moonshell's file list). The rest of the image is never used.
#2: Whatever 8 rows of the image line up with the selected option are displayed. (That is, if the option is at the very top of the screen, rows 0 to 7 are shown; if it's the next line, rows 8 to 15 are shown, etc.) The bitmap doesn't scroll (except to turn it on/off), just different parts of it are displayed depending which option is selected. (The reason for this is so that you can, for example, copy the background image to it, darkening it in the process, so you have a fake translucent black cursor.)

This essentially means all 256x192 of it may be displayed at one time or another. If I have to, I could simulate method 2 by using method 1 and copying 8 rows of an image from main RAM into the bitmap each frame. I fear to think how much this would slow things down though.

If you don't understand this maybe a screenshot (OK, photo <_<) would help. Main screen is the bottom. See the blue bar highlighting "BG3.BMP"? Right now it's done by turning off the bitmap and changing the background colour in HBlank, but this only allows you one colour per scanline. I want to use a bitmap layer for that instead, so I can do things like this (fake translucency by duplicating and darkening the background on the second layer), this or this. Notice all three of these would use method 2, but if you just wanted a solid image (like in the actual screenshot) you would use method 1.

Another idea that just came to mind is using sprites instead of a second bitmap. Any good?

I really have no idea what I'm doing when it comes to DS VRAM so any help is certainly appreciated. v?v;
_________________
I'm a PSP hacker now, but I still <3 DS.


Last edited by HyperHacker on Thu Nov 01, 2007 5:31 am; edited 1 time in total

#144130 - M3d10n - Mon Oct 29, 2007 1:01 pm

I'm not too knowledgeable in the DS 2D yet, but I'm sure what you want to use is the window feature. You can change settings for the inside and outside of the window, like enable/disable: BG layers, sprites and blend effects. By the looks of it you can easily use it to make a rectangle which darkens your background inside it, without using extra VRAM.

Details here:
http://nocash.emubase.de/gbatek.htm#lcdiowindowfeature
(It's in the GBA section, but the addresses and bit settings are the same)

#144182 - HyperHacker - Mon Oct 29, 2007 11:48 pm

Interesting, but I don't see where it explains how to use the windows' effects, unless it's related to that blending stuff listed afterward? Anyway that wouldn't allow for examples 2 or 3.
_________________
I'm a PSP hacker now, but I still <3 DS.

#144237 - edwdig - Tue Oct 30, 2007 4:24 pm

Just set up some sprites with a priority lower than that of the text but higher than that of the background. Set the blend target to be the background layer, and mark the sprites as transparent sprites. Or, if you need blend elsewhere, use bitmap sprites, which will eat more memory but have their own alpha values. It looks like you'd be fine by just repeating a small black box and adjusting the alpha appropriately.

#144262 - HyperHacker - Tue Oct 30, 2007 11:33 pm

Are you guys looking at #2 or #3? V_v
_________________
I'm a PSP hacker now, but I still <3 DS.

#144285 - edwdig - Wed Oct 31, 2007 3:49 am

I looked at 2 and 3 but wasn't quite sure exactly what I was looking at.

I reread what you're trying to do and think I understand it better now. Looks like M3d10n was right, you want to use a window. You can specify a rectangle for the window and set it so that a certain background layer is only visible inside the window.

One catch to remember - the maximum width of a window is 255 pixels, so you'll need 2 windows if you want to span the entire screen width.

#144288 - HyperHacker - Wed Oct 31, 2007 4:03 am

Well, I can toggle the second layer on and off no problem. The problem is how do I have 2 background layers and 2 (or even one) text layers?

I guess it might not be clear either: in #2 the image is inverted behind that line, in #3 there's a red-to-yellow translucent gradient over it. These effects would be achieved by duplicating the image onto the second layer, altering it in the process.
_________________
I'm a PSP hacker now, but I still <3 DS.

#144291 - edwdig - Wed Oct 31, 2007 5:27 am

HyperHacker wrote:
Well, I can toggle the second layer on and off no problem. The problem is how do I have 2 background layers and 2 (or even one) text layers?


Make sure you're using BG Mode 5. It's the only mode that can do 2 bitmap layers. Not sure what else to say about where you could be going wrong.

#144292 - HyperHacker - Wed Oct 31, 2007 5:31 am

I am. I just don't know how to go about setting up the VRAM to accommodate the extra layers. :-/ My experience with VRAM mapping has basically been like this: common sense tells me to do one thing, so I try it and it doesn't work. Logic tells me to do something else, so I try it and it doesn't work. I carefully analyze the numbers, addresses, sizes, etc and plan out exactly how it should all fit together, and it doesn't work. Finally, I give up and find the answer posted here somewhere that relies on an ugly hack.
_________________
I'm a PSP hacker now, but I still <3 DS.

#144372 - HyperHacker - Thu Nov 01, 2007 5:30 am

Well I managed to figure it out, it ended up being quite a bit easier than I expected (just copy what I did last time ;-p). Now if I could just get sound working I'd be good to go.

I just had to add bank B to the mix:
Code:
vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000,
   VRAM_C_SUB_BG_0x06200000, VRAM_D_LCD);


And then find a base for BG1 and BG2 that didn't overlap BG0 or BG3:
Code:
BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(1);
BG1_X0 = -1;
BG1_Y0 = -1;

BG2_CR = BG_BMP16_256x256 | BG_BMP_BASE(8);
BG2_XDX = 1 << 8;
BG2_XDY = 0;
BG2_YDX = 0;
BG2_YDY = 1 << 8;
BG2_CX = 0 << 8;
BG2_CY = 256 << 8; //off screen by default

Easy enough. :-p
_________________
I'm a PSP hacker now, but I still <3 DS.