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.

Beginners > Mode 0 backgrounds

#14468 - WillyWonka - Wed Jan 07, 2004 5:07 am

I'm having trouble trying to copy sonic where they use Mode 0 to display bitmap backgrounds with transparencies, but I can't seem to get the backgrounds displaying properly. I think it's something to do with the char and screen base blocks but I'm not sure. (I'm following the GBA Junkie tutorials)

Code:
   bg2.number = 2;
   bg2.charBaseBlock = 0;
   bg2.screenBaseBlock = 28;
   bg2.colorMode = BG_COLOR_256;
   bg2.size = TEXTBG_SIZE_512x256;
   bg2.mosaic = 0;
   bg2.x_scroll = 0;
   bg2.y_scroll = 0;

   EnableBackground( &bg2 );

   // Palette
   for(loop = 0; loop < 256; loop++) {
      BGPaletteMem[loop] = eightlinesPalette[loop];
   }

   // Tiles
   for(loop = 0; loop < eightlines_width * eightlines_height * 0.5; loop++)  {
      bg2.tileData[loop] = eightlinesData[loop];
   }

   temp = (u16*)eightlinesMap;
   for(loop = 0; loop < 16*16/2; loop++) {
      bg2.mapData[loop] = temp[loop];
   }

   while(1) {
      GetInput();
      WaitForVsync();
      UpdateBackground(&bg2);
   }
}


The palette is coming in fine. I'm getting some of the tiles in (I'm not sure they're in the right order, but I can see them there). The problem is all I'm seeing on the screen is tile #0.

I generated the map file and it looks like this:

Code:
const u8 eightlinesMap[ 64 * 32 ] = {
0x00,0x01,...};


Anyone have any idea as to why I'm not seeing any tiles other then 0 on the screen?

#14477 - sgeos - Wed Jan 07, 2004 5:47 am

Have you copied your map "file" to the screen base block you want your bg to use? There are a lot of functions that are called but not posted.

Will this help any? temp is a pointer to u16, right?
Code:
temp = (u16 *)(&eightlinesMap[0]);


-Brendan

#14479 - WillyWonka - Wed Jan 07, 2004 6:03 am

The functions that I'm calling are from the tutorial (I know they work).

These are the first couple lines of EnableBackground. It's pointing bg2.mapData array to the background....

Code:

void EnableBackground(Bg* bg)
{
   u16 temp;

   bg->tileData = (u16*)CharBaseBlock(bg->charBaseBlock);
   bg->mapData = (u16*)ScreenBaseBlock(bg->screenBaseBlock);
   temp = bg->size | (bg->charBaseBlock<<CHAR_SHIFT) | (bg->screenBaseBlock<<SCREEN_SHIFT)
      | bg->colorMode | bg->mosaic | bg->wraparound;


The update function just updats the x, y offsets of the background every frame.

As for temp, yes it is a pointer to a u16, no that code didn't help. I did try moving the enablebackground to below where the information is copied into it and now I get a white screen and no tiles in the tile memory. I think the screen might be overwriting the tile data in this case... dunno.

#14521 - sajiimori - Wed Jan 07, 2004 11:40 pm

Quote:

The functions that I'm calling are from the tutorial (I know they work).

It's not so much about whether they work, it's a matter of whether they will do what you expected given the code you posted. If we can't see the actual work that is being done, there is no way for us to know what is wrong.
Code:

temp = (u16 *)(&eightlinesMap[0]);

That code is exactly equivalent to the original. '&arrayname[0]' is the same as 'arrayname'.
Quote:

I did try moving the enablebackground to below where the information is copied into it and now I get a white screen and no tiles in the tile memory.

Well sure, the pointers in the bg struct are garbage (or null) until you call EnableBackground(), so writing to those addresses wouldn't do anything useful.

How are you setting the video mode? Are any other backgrounds enabled in REG_DISPCNT? If BG0 or BG1 are enabled, you could get the result you describe.

#14620 - WillyWonka - Fri Jan 09, 2004 11:11 pm

Quote:
How are you setting the video mode? Are any other backgrounds enabled in REG_DISPCNT? If BG0 or BG1 are enabled, you could get the result you describe.


The video mode is getting set fine. Only background 2 is enabled.

Essentially it's this that is enabling it...
Code:

#define BG2_ENABLE   0x400
REG_DISPCNT |= BG2_ENABLE;


I've reworked things and I believe my problem lies with the format of the map files. I can't seem to find a map editor that works. They all seem to produce different code when outputting and I can't figure out what code works with any particular editor.

Anyone have a good map editor? I tried that beta 4 one but it's buggy and I can't figure which mode to use 8x8 or 16x16
[/quote]

#14621 - dagamer34 - Fri Jan 09, 2004 11:37 pm

This line...
Code:

for(loop = 0; loop < eightlines_width * eightlines_height * 0.5; loop++)


You are getting junk (and this is SOO SLOW) because it uses a floating point number. Actually, nothing is loaded (wow, I think I solved your problem), because the number is represented as 0. Maybe you tried to optimize this routine, but there is a reason why we all do this.

By the way, there is a certain way text backgrounds. It works in blocks... Check the Pern Project tutorials Day 4 and READ all of it. I think floating somewhere around here is the code.

You're welcome!!!!
_________________
Little kids and Playstation 2's don't mix. :(

#14624 - WillyWonka - Sat Jan 10, 2004 12:45 am

Oh oh! I got something!!!

Thank you! I put * 0.5 because I heard that there was no divide in the gameboy and it made it slow. I guess decimal is worse to use then divide :)

#14625 - yaustar - Sat Jan 10, 2004 12:50 am

I use Map editor by nessie...

http://nessie.gbadev.org/
_________________
[Blog] [Portfolio]

#14626 - sajiimori - Sat Jan 10, 2004 12:51 am

Yeah, multiplying by 0.5 will require fp emulation, so you'll normally want to divide by 2 instead (which will compile to a bit shift). Anyway, the speed is not really important here.

dagamer34, you're getting ahead of yourself (and full of yourself as usual). What makes you think this expression evaluates to zero? Of course I can't say it doesn't -- Willy never posted the definitions of those variables.
Code:

eightlines_width * eightlines_height * 0.5

Besides, the OP said the tiles were being loaded correctly. It's just that the screen was being filled with tile 0. Also, the fact that BG maps are paged cannot explain the problem because it looks like this map is only 16x16 characters.

WillyWonka, I can't tell what's wrong with your code unless you post more. Until then, you can take your program apart and use VBA to find the code where things aren't happening the way you expected.

#14628 - yaustar - Sat Jan 10, 2004 1:02 am

How is the map a
Code:

bg2.size = TEXTBG_SIZE_512x256;

and 16x16
Code:

for(loop = 0; loop < 16*16/2; loop++) {
      bg2.mapData[loop] = temp[loop];
   }

at the same time?

;)

edit: is it also a rotation map as well?
_________________
[Blog] [Portfolio]

#14707 - WillyWonka - Sun Jan 11, 2004 9:42 pm

Well the background is set to 512x256 but I've found out that I can only draw 256 tiles (16 * 16). I'm trying to change the CharBaseBlock so that I can draw the entire screen, but I wind up getting the 3rd set of tiles displayed 3 times on the screen. Anyone know what I'm doing wrong this time?

Code:

   for (tileSet = 0; tileSet < 3; tileSet++) {
      bg2.charBaseBlock = tileSet;
      updateCharBaseBlock( &bg2 );
      for(loop = 0; loop < 16*16; loop++) {
         bg2.mapData[(tileSet * 256) + loop] = temp[(tileSet * 256) + loop];
      }

   }


And here is my copy & paste crap code (That could probably be cut down to 1 line) for updateCharBaseBlock

Code:

void updateCharBaseBlock(Bg* bg) {
   u16 temp;
   bg->tileData = (u16*)CharBaseBlock(bg->charBaseBlock);
   temp = bg->size | (bg->charBaseBlock<<CHAR_SHIFT) | (bg->screenBaseBlock<<SCREEN_SHIFT)
                   | bg->colorMode | bg->mosaic | bg->wraparound;

   switch(bg->number) {
      case 0:
         {
            REG_BG0CNT = temp;
         } break;
      case 1:
         {
            REG_BG1CNT = temp;
         } break;
      case 2:
         {
            REG_BG2CNT = temp;
         } break;
      case 3:
         {
            REG_BG3CNT = temp;
         } break;

   default:break;

   }
}

#14708 - dagamer34 - Sun Jan 11, 2004 10:02 pm

Full of myself??? That's a new one. So far I have helped about 10 people so give me some credit.

There isn't any need for the updateCharBaseBlock function. In Enablebackground (), all it does it set the correct location of memory for the pointer for you to copy data correctly.

This line:
Code:

for(loop = 0; loop < 16*16; loop++) {
         bg2.mapData[(tileSet * 256) + loop] = temp[(tileSet * 256) + loop];
      }


I'm not exactly sure what you are trying to do but I will help if possible. THe 256 should be changed to a 32 because you are working with tiles, not pixels. Otherwise, yeah, I think you are good to go!![/quote]
_________________
Little kids and Playstation 2's don't mix. :(

#14710 - WillyWonka - Sun Jan 11, 2004 10:12 pm

I'm trying to display a photo that is full screen. The problem is I can only use 256 tiles and then the charBaseBlock needs to be increased by one (At least that's what I understand).

To fill the screen with tiles it looks like I have to draw around 256 + 256 + 128 tiles.

When I setup the loop to draw 32 * 32 I wind up with the same 1/3rd of the image drawn on the screen 3 times.

#14717 - yaustar - Sun Jan 11, 2004 11:55 pm

First thing's first, we are in mode_0 so lets sort out the bg size
Code:
bg2.size = TEXTBG_SIZE_256x256;

Where are we calling
Code:

for (tileSet = 0; tileSet < 3; tileSet++) {
      bg2.charBaseBlock = tileSet;
      updateCharBaseBlock( &bg2 );
      for(loop = 0; loop < 16*16; loop++) {
         bg2.mapData[(tileSet * 256) + loop] = temp[(tileSet * 256) + loop];
      }

   }

in the while(1) loop or before?

The 256 unique tile restriction is when you are using rotation maps which is not the case here.

I have done a similar thing on my code and mine set out to
Code:

        str_bgLayer[0].charBaseBlock = 3;//tile data target block 3
        str_bgLayer[0].bgPriority = 3;
        str_bgLayer[0].colorMode = BG_COLOR_16;//colour mode is 16 colour tiles
        str_bgLayer[0].mosaic = 0;//mosiac mode off
        str_bgLayer[0].number = 0;//first layer (0)
        str_bgLayer[0].screenBaseBlock = 0;//target block for map data. MUST be in
                                           //a different Char block to tile & palette data
        str_bgLayer[0].size = TEXTBG_SIZE_256x256;//size of map is 512x512
        str_bgLayer[0].x_scroll = 0;
        str_bgLayer[0].y_scroll = 0;


The char base block was enough to hold over 800 unique 16 colour tiles.

Unless you have a reason for the loop, it should be possible to process it normally.

If I am wrong, give me a slap round the head and correct me please.
_________________
[Blog] [Portfolio]

#14718 - sajiimori - Mon Jan 12, 2004 12:00 am

It seems like your code is only getting more complicated. There is still no way to tell what you're doing wrong.

If you still have trouble, I'd say start over and try to do things as simply as possible, without trying to conform to somebody else's functions and data structures (like all that bg stuff). Do some smaller experiments, and make sure you understand each concept before moving on.

I think you'll find that your task is much simpler than you think, and you can accomplish what you're going for with a fraction of the code -- which is a very satisfying feeling. =)

For starters, why don't you use a bitmap mode if you're displaying a bitmap?

dagamer34, it's a "new one" because, in my experience, people around here are very polite. On the other hand, I'm not polite at all, so I don't mind telling you that considering how great you think you are, you're one of the least helpful and least informed people I've encountered on this board.

Cheers!

#14719 - WillyWonka - Mon Jan 12, 2004 12:04 am

I'm in 256 colour mode. Not 16. Is that a problem?
Code:
bg2.colorMode = BG_COLOR_256;


It's called before the while loop.

Quote:
Unless you have a reason for the loop, it should be possible to process it normally.


Is there some way to copy the chunk of memory all at once?


Mode 0
Background 2
Colours 256
CharBaseBlock 0
The loaded Tiles span over 3 base blocks
0x6000000, 0x6004000, and 0x6008000

I am trying to display all of the tiles on the one background layer.

#14720 - WillyWonka - Mon Jan 12, 2004 12:10 am

Quote:
It seems like your code is only getting more complicated.

It's not really. It's just got a lot of crap commented out now. I think it just seems like it because I'm just posting portions of the program into this thread and it's changing over time.

Quote:
For starters, why don't you use a bitmap mode if you're displaying a bitmap?


Well, it's because I was looking at the intro screens on Sonic and they never go out of mode 0 & 1. They have what appear to be full screen images, but I just realized now that they actually aren't. So what I'm trying to do might not actually be possible even though I thought sonic did it.

#14722 - yaustar - Mon Jan 12, 2004 12:28 am

WillyWonka wrote:
I'm in 256 colour mode. Not 16. Is that a problem?
Code:
bg2.colorMode = BG_COLOR_256;


It just means you have to use twice as much memory.

I am not sure but doesnt the Char base Blocks 'overflow' into the next if it gets 'full'?

edit: http://forum.gbadev.org/viewtopic.php?t=1896&highlight=char+base I thought I asked this some time ago.....
_________________
[Blog] [Portfolio]

#14724 - dagamer34 - Mon Jan 12, 2004 1:05 am

You're trying to mimic Sonic? One thing is that Sonic Advance was developed by a company not 1 person, who have access to official docs for the GBA (not that we can't get our hands on some).

How complex is your picture? Are you trying to mimic the "SEGA" screen because you have to realize that most of it is white space. There wasn't any need for more tiles than what you can cram in 1 char base block.
_________________
Little kids and Playstation 2's don't mix. :(

#14725 - tepples - Mon Jan 12, 2004 1:05 am

sajiimori wrote:
For starters, why don't you use a bitmap mode if you're displaying a bitmap?

Sure, a scrolling playfield in front of a bitmap background could be constructed with sprites, but then you're down to 16 KB of VRAM to store all the tiles for your playfield, and you'll probably have to use HDMA to OAM. Even then, what about displaying rot/scale stuff in front of the bitmap?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#14726 - WillyWonka - Mon Jan 12, 2004 1:12 am

Quote:
You're trying to mimic Sonic?

The video modes and techniques they use, yes.

Quote:
How complex is your picture?

It's a 240x160x256 photograph. Every tile is different and it fills the full screen.

#14730 - LOst? - Mon Jan 12, 2004 1:48 am

[quote="WillyWonka"]
Quote:
You're trying to mimic Sonic?

The video modes and techniques they use, yes.

Me too :P

#14732 - sajiimori - Mon Jan 12, 2004 2:06 am

Anybody else getting the impression that this thread is going nowhere?
Code:

#include "gba.h"

#define TILE_SHIFT     2
#define TILE_BLOCK(n)  (((n)*0x4000)+0x6000000)
#define MAP_BLOCK(n)   (((n)*0x800)+0x6000000)

#define DMACPY16(dst,src,len) \
  REG_DM3SAD = (int)(src), \
  REG_DM3DAD = (int)(dst), \
  REG_DM3CNT = (len) | DMA_ENABLE

#define HWMAP_CHAR_W    32
#define SCREEN_CHAR_W   (240/8)
#define SCREEN_CHAR_H   (160/8)
#define SCREEN_CHARS    (SCREEN_CHAR_W*SCREEN_CHAR_H)
#define BYTES_PER_CHAR  32
#define TILE_DATA_SIZE  (SCREEN_CHARS*BYTES_PER_CHAR)

extern u16 bg_palette[256];
extern u8 tile_data[TILE_DATA_SIZE];

// last 2 map columns are offscreen
extern u16 map_data[HWMAP_CHAR_W*SCREEN_CHAR_H];

main()
{
    DMACPY16(BG_PALETTE,
             bg_palette,
             256);
    DMACPY16(TILE_BLOCK(2),
             tile_data,
             TILE_DATA_SIZE/2);
    DMACPY16(MAP_BLOCK(0),
             map_data,
             SCREEN_CHARS);
    REG_BG0CNT = 2 << TILE_SHIFT;
    REG_DISPCNT = BG0_ENABLE;

    while(1);
}

#14735 - WillyWonka - Mon Jan 12, 2004 2:49 am

Sajimori, what are BG_PALETTE and DMA_ENABLE's values?

#14736 - yaustar - Mon Jan 12, 2004 3:31 am

looking at the mapdata that I asked for, your data refers to tile numbers 256 and beyond. The text background register only indexes 0-255. This means that I was incorrect before (sorry) the 256 UNIQUE tile limit refers to both types of backgrounds.

As how to fix it ......erm...
_________________
[Blog] [Portfolio]

#14737 - dagamer34 - Mon Jan 12, 2004 3:41 am

Actually, tile backgrounds have an extra 8 bits which allows you to have 1024 unique tiles. Rot backgrounds are only 8-bit. Text is 16-bit. Note that these limitations are for 16-color tiles. Divide by 2 for 256.
_________________
Little kids and Playstation 2's don't mix. :(

#14738 - yaustar - Mon Jan 12, 2004 3:51 am

*re-reading the pern tut* oops, I was right the rest time... >.< then I am at a complete lost. THe map data looks sound and the code is sound (i think)......
_________________
[Blog] [Portfolio]

#14745 - yaustar - Mon Jan 12, 2004 6:15 am

yaustar wrote:
looking at the mapdata that I asked for, your data refers to tile numbers 256 and beyond. The text background register only indexes 0-255. This means that I was incorrect before (sorry) the 256 UNIQUE tile limit refers to both types of backgrounds.

As how to fix it ......erm...


I was partially right (frame of mind any how) it was nt the text register at fault. It was the map editer export
Code:

const u8 t1[ 32 * 32 ] = {
.............
0xE0,0xE1,0xE2,.......
0x100,0x101,0x102,...........
}

I cant believe I didnt see it sooner......
_________________
[Blog] [Portfolio]

#14778 - WillyWonka - Mon Jan 12, 2004 7:25 pm

Yeah! I got it working.

Switching to MapEd and then modifying the file format (That's a cool feature) to match GBAMapEditor Beta 4's output did the trick.

(Well I have some image corruption on the last line of the image, but that's probably my fault)

WOO HOO!

#14781 - yaustar - Mon Jan 12, 2004 7:53 pm

or you can change map4 beta export from 'const u8' to const u16....
_________________
[Blog] [Portfolio]