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.

Coding > Odd Startup Issue - Forced Blank Enabled?

#20756 - ravenq - Mon May 17, 2004 3:25 am

This may sound like an odd problem, but here goes anyway. I've created a header file for a background image, and included it. My mode is set to 0x0404 (Mode 4 + BG2 Enabled). I then loop through the palette and picture and load them in.

However, the screen is all white, and when I check DISPCNT, the Forced Blank bit (bit 7) is enabled.

But... if I comment out the header file (and the transfer of the palette/bg data), then it starts up in the correct mode.

What would be causing this?
_________________
The Game is Nothing.
The Playing of it Everything

#20759 - dagamer34 - Mon May 17, 2004 3:53 am

Do you load the data before you set the mode? That might be the problem.
_________________
Little kids and Playstation 2's don't mix. :(

#20761 - ravenq - Mon May 17, 2004 4:02 am

No. Here's a very simplified version of my code:

This works:
Code:
int main()
{
  *REG_DISPCNT = 0x0404;
  while(1);
}


This doesn't:
Code:
#include "bgpic.h"

int main()
{
  *REG_DISPCNT = 0x0404;
  while(1);
}


As you can see, the only difference is the include statement. After the first block, REG_DISPCNT = 0x0404, after the second block it's 0x0080.
_________________
The Game is Nothing.
The Playing of it Everything

#20763 - tepples - Mon May 17, 2004 4:22 am

First of all, 0x0080 is the default value for DISPCNT, set by BIOS. Forced blanking lets programs build their initial screen data in VRAM without things flickering on screen.

ravenq wrote:
This works:
Code:
int main()
{
  *REG_DISPCNT = 0x0404;
  while(1);
}


This doesn't:
Code:
#include "bgpic.h"

What is the content of bgpic.h ?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#20764 - ravenq - Mon May 17, 2004 4:29 am

bgpic.h just has two arrays, one with graphic data and the other with pixel data. I've used gfx2gba to create it with these options:

gbx2gba bgpic.jpg bgpic.h -w 16 -s 2 -k -8 -o

Once it's generated that file, I haven't modified it at all.
_________________
The Game is Nothing.
The Playing of it Everything

#20777 - sajiimori - Mon May 17, 2004 7:03 pm

Did you say it was a "simplified version" of your code? Did you actually try compiling and running those simplified versions? I would not expect them to compile because you are not defining REG_DISPCNT.

Compile and run a complete but minimal version, then post that in its entirety. Also, post the relevant portions of the header (with array contents removed), and post the commands you are using to compile.

Lastly, post the portion of your gba header that you use in the program (such as the definition of REG_DISPCNT).

#20811 - ravenq - Tue May 18, 2004 5:41 am

Sorry, REG_DISPCNT _is_ defined in the simplied one, I just hadn't bothered listing it, since it was just assumed ^^ Here is my complete code:

Code:

#include "graphics/credits001.h"
#include "types.h"
#include "registers.h"

using namespace std;

int main(int argc, char** argv)
{
   u16 x, y;

   // Put the GBA into bitmap mode
   *REG_DISPCNT = 0x0403;

   // Load the palette for the credits screen
   //for ( x = 0; x < 256; x++ )
   //{
   //   BGPaletteMem[x] = credits001Palette[x];
   //}

   for ( y = 0; y < 160; y++ )
   {
      for ( x = 0; x < 240; x++ )
      {
         VideoBuffer[y * 240 + x] = credits001[y * 240 + x];
      }
   }

   while ( true );

   return 0;
}


And my definitions for the registers:
Code:
static u16vp   VideoBuffer      = (u16vp) 0x6000000;
static u16vp   BGPaletteMem   = (u16vp) 0x5000000;
static u32vp   REG_DISPCNT      = (u32vp) 0x4000000;


I've seemed to have gotten this working by placing the picture header before the other two, but now the picture is corrupted when I load it into the video buffer. If I leave it _after_ the other two header files, I get the Forced Blank problem.
_________________
The Game is Nothing.
The Playing of it Everything

#20854 - sajiimori - Tue May 18, 2004 6:48 pm

The "assumed" things are where you can expect your problems to be. It's pretty common for people to post small bits of code and ask where their problem is, when the reason they couldn't find it themselves was because they assumed the rest was perfect.

The only additional problem I see here is that your math is wrong for displaying your image. You seem to be trying to write 1 pixel at a time, but VideoBuffer is a u16*, and besides, you have to write 16 bits at a time to VRAM.

If you still have trouble, post the rest of the things I asked for -- post the relevant portions of the header (with array contents removed), and post the commands you are using to compile.

#20856 - ravenq - Tue May 18, 2004 7:15 pm

Heh, I know assumptions can be problems at times. However, I _know_ I've had the rest working before, it works fine in sprite mode, just with this bitmap mode it has issues.

Anyway, here is the rest of the relavent code:

Contents of 'types.h'
Code:
typedef   unsigned char            u8;
typedef const unsigned char         u8c;
typedef   unsigned char*            u8p;
typedef unsigned volatile char*      u8vp;
typedef signed char               s8;
typedef const signed char         s8c;

typedef unsigned short            u16;
typedef const unsigned short      u16c;
typedef unsigned short*            u16p;
typedef unsigned volatile short*   u16vp;
typedef signed short            s16;
typedef const signed short         s16c;

typedef unsigned long            u32;
typedef const unsigned long         u32c;
typedef unsigned long*            u32p;
typedef unsigned volatile long*      u32vp;
typedef signed long               s32;
typedef const signed long         s32c;

typedef unsigned char            byte;
typedef unsigned short            hword;
typedef unsigned long            word;
typedef unsigned long long         dword;


Contents of 'register.h'
Code:
static u16vp   OAMmem         = (u16vp) 0x7000000;
static u16vp   VideoBuffer      = (u16vp) 0x6000000;
static u16vp   BackBuffer      = (u16vp) 0x600A000;
static u16vp   OAMData         = (u16vp) 0x6010000;
static u16vp   BGPaletteMem   = (u16vp) 0x5000000;
static u16vp   OBJPaletteMem   = (u16vp) 0x5000200;

static u32vp   REG_INTERUPT   = (u32vp) 0x3007FFC;

static u32vp   REG_DISPCNT      = (u32vp) 0x4000000;
static u16vp   REG_DISPCNT_L   = (u16vp) 0x4000000;
static u16vp   REG_DISPCNT_H   = (u16vp) 0x4000002;
static u16vp   REG_DISPSTAT   = (u16vp) 0x4000004;

static u16vp   REG_VCOUNT      = (u16vp) 0x4000006;

static u16vp   REG_BG0CNT      = (u16vp) 0x4000008;
static u16vp   REG_BG1CNT      = (u16vp) 0x400000A;
static u16vp   REG_BG2CNT      = (u16vp) 0x400000C;
static u16vp   REG_BG3CNT      = (u16vp) 0x400000E;

static u16vp   REG_BG0HOFS      = (u16vp) 0x4000010;
static u16vp   REG_BG0VOFS      = (u16vp) 0x4000012;
static u16vp   REG_BG1HOFS      = (u16vp) 0x4000014;
static u16vp   REG_BG1VOFS      = (u16vp) 0x4000016;
static u16vp   REG_BG2HOFS      = (u16vp) 0x4000018;
static u16vp   REG_BG2VOFS      = (u16vp) 0x400001A;
static u16vp   REG_BG3HOFS      = (u16vp) 0x400001C;
static u16vp   REG_BG3VOFS      = (u16vp) 0x400001E;

static u16vp   REG_BG2PA      = (u16vp) 0x4000020;
static u16vp   REG_BG2PB      = (u16vp) 0x4000022;
static u16vp   REG_BG2PC      = (u16vp) 0x4000024;
static u16vp   REG_BG2PD      = (u16vp) 0x4000026;

static u32vp   REG_BG2X      = (u32vp) 0x4000028;
static u16vp   REG_BG2X_L      = (u16vp) 0x4000028;
static u16vp   REG_BG2X_H      = (u16vp) 0x400002A;

static u32vp   REG_BG2Y      = (u32vp) 0x400002C;
static u16vp   REG_BG2Y_L      = (u16vp) 0x400002C;
static u16vp   REG_BG2Y_H      = (u16vp) 0x400002E;

static u16vp   REG_BG3PA      = (u16vp) 0x4000030;
static u16vp   REG_BG3PB      = (u16vp) 0x4000032;
static u16vp   REG_BG3PC      = (u16vp) 0x4000034;
static u16vp   REG_BG3PD      = (u16vp) 0x4000036;

static u32vp   REG_BG3X      = (u32vp) 0x4000038;
static u16vp   REG_BG3X_L      = (u16vp) 0x4000038;
static u16vp   REG_BG3X_H      = (u16vp) 0x400003A;

static u32vp   REG_BG3Y      = (u32vp) 0x400003C;
static u16vp   REG_BG3Y_L      = (u16vp) 0x400003C;
static u16vp   REG_BG3Y_H      = (u16vp) 0x400003E;

static u16vp   REG_WIN0H      = (u16vp) 0x4000040;
static u16vp   REG_WIN1H      = (u16vp) 0x4000042;
static u16vp   REG_WIN0V      = (u16vp) 0x4000044;
static u16vp   REG_WIN1V      = (u16vp) 0x4000046;
static u16vp   REG_WININ      = (u16vp) 0x4000048;
static u16vp   REG_WINOUT      = (u16vp) 0x400004A;

static u32vp   REG_MOSAIC      = (u32vp) 0x400004C;
static u32vp   REG_MOSAIC_L   = (u32vp) 0x400004C;
static u32vp   REG_MOSAIC_H   = (u32vp) 0x400004E;

static u16vp   REG_BLDMOD      = (u16vp) 0x4000050;

static u16vp   REG_COLEV      = (u16vp) 0x4000052;
static u16vp   REG_COLEY      = (u16vp) 0x4000054;

static u32vp   REG_SG10      = (u32vp) 0x4000060;
static u16vp   REG_SG10_L      = (u16vp) 0x4000060;
static u16vp   REG_SG10_H      = (u16vp) 0x4000062;

static u16vp   REG_SG11      = (u16vp) 0x4000064;
static u16vp   REG_SG20      = (u16vp) 0x4000068;
static u16vp   REG_SG21      = (u16vp) 0x400006C;

static u32vp   REG_SG30      = (u32vp) 0x4000070;
static u16vp   REG_SG30_L      = (u16vp) 0x4000070;
static u16vp   REG_SG30_H      = (u16vp) 0x4000072;

static u16vp   REG_SG31      = (u16vp) 0x4000074;
static u16vp   REG_SG40      = (u16vp) 0x4000078;
static u16vp   REG_SG41      = (u16vp) 0x400007C;

static u32vp   REG_SGCNT0      = (u32vp) 0x4000080;
static u16vp   REG_SGCNT0_L   = (u16vp) 0x4000080;
static u16vp   REG_SGCNT0_H   = (u16vp) 0x4000082;

static u16vp   REG_SGCNT1      = (u16vp) 0x4000084;
static u16vp   REG_SGBIAS      = (u16vp) 0x4000088;

static u32vp   REG_SGWR0      = (u32vp) 0x4000090;
static u16vp   REG_SGWR0_L      = (u16vp) 0x4000090;
static u16vp   REG_SGWR0_H      = (u16vp) 0x4000092;

static u32vp   REG_SGWR1      = (u32vp) 0x4000094;
static u16vp   REG_SGWR1_L      = (u16vp) 0x4000094;
static u16vp   REG_SGWR1_H      = (u16vp) 0x4000096;

static u32vp   REG_SGWR2      = (u32vp) 0x4000098;
static u16vp   REG_SGWR2_L      = (u16vp) 0x4000098;
static u16vp   REG_SGWR2_H      = (u16vp) 0x400009A;

static u32vp   REG_SGWR3      = (u32vp) 0x400009C;
static u16vp   REG_SGWR3_L      = (u16vp) 0x400009C;
static u16vp   REG_SGWR3_H      = (u16vp) 0x400009E;

static u32vp   REG_SGFIF0A      = (u32vp) 0x40000A0;
static u16vp   REG_SGFIFOA_L   = (u16vp) 0x40000A0;
static u16vp   REG_SGFIFOA_H   = (u16vp) 0x40000A2;

static u32vp   REG_SGFIFOB      = (u32vp) 0x40000A4;
static u16vp   REG_SGFIFOB_L   = (u16vp) 0x40000A4;
static u16vp   REG_SGFIFOB_H   = (u16vp) 0x40000A6;

static u32vp   REG_DM0SAD      = (u32vp) 0x40000B0;
static u16vp   REG_DM0SAD_L   = (u16vp) 0x40000B0;
static u16vp   REG_DM0SAD_H   = (u16vp) 0x40000B2;

static u32vp   REG_DM0DAD      = (u32vp) 0x40000B4;
static u16vp   REG_DM0DAD_L   = (u16vp) 0x40000B4;
static u16vp   REG_DM0DAD_H   = (u16vp) 0x40000B6;

static u32vp   REG_DM0CNT      = (u32vp) 0x40000B8;
static u16vp   REG_DM0CNT_L   = (u16vp) 0x40000B8;
static u16vp   REG_DM0CNT_H   = (u16vp) 0x40000BA;

static u32vp   REG_DM1SAD      = (u32vp) 0x40000BC;
static u16vp   REG_DM1SAD_L   = (u16vp) 0x40000BC;
static u16vp   REG_DM1SAD_H   = (u16vp) 0x40000BE;

static u32vp   REG_DM1DAD      = (u32vp) 0x40000C0;
static u16vp   REG_DM1DAD_L   = (u16vp) 0x40000C0;
static u16vp   REG_DM1DAD_H   = (u16vp) 0x40000C2;

static u32vp   REG_DM1CNT      = (u32vp) 0x40000C4;
static u16vp   REG_DM1CNT_L   = (u16vp) 0x40000C4;
static u16vp   REG_DM1CNT_H   = (u16vp) 0x40000C6;

static u32vp   REG_DM2SAD      = (u32vp) 0x40000C8;
static u16vp   REG_DM2SAD_L   = (u16vp) 0x40000C8;
static u16vp   REG_DM2SAD_H   = (u16vp) 0x40000CA;

static u32vp   REG_DM2DAD      = (u32vp) 0x40000CC;
static u16vp   REG_DM2DAD_L   = (u16vp) 0x40000CC;
static u16vp   REG_DM2DAD_H   = (u16vp) 0x40000CE;

static u32vp   REG_DM2CNT      = (u32vp) 0x40000D0;
static u16vp   REG_DM2CNT_L   = (u16vp) 0x40000D0;
static u16vp   REG_DM2CNT_H   = (u16vp) 0x40000D2;

static u32vp   REG_DM3SAD      = (u32vp) 0x40000D4;
static u16vp   REG_DM3SAD_L   = (u16vp) 0x40000D4;
static u16vp   REG_DM3SAD_H   = (u16vp) 0x40000D6;

static u32vp   REG_DM3DAD      = (u32vp) 0x40000D8;
static u16vp   REG_DM3DAD_L   = (u16vp) 0x40000D8;
static u16vp   REG_DM3DAD_H   = (u16vp) 0x40000DA;

static u32vp   REG_DM3CNT      = (u32vp) 0x40000DC;
static u16vp   REG_DM3CNT_L   = (u16vp) 0x40000DC;
static u16vp   REG_DM3CNT_H   = (u16vp) 0x40000DE;

static u16vp   REG_TM0D      = (u16vp) 0x4000100;
static u16vp   REG_TM0CNT      = (u16vp) 0x4000102;

static u16vp   REG_TM1D      = (u16vp) 0x4000104;
static u16vp   REG_TM1CNT      = (u16vp) 0x4000106;

static u16vp   REG_TM2D      = (u16vp) 0x4000108;
static u16vp   REG_TM2CNT      = (u16vp) 0x400010A;

static u16vp   REG_TM3D      = (u16vp) 0x400010C;
static u16vp   REG_TM3CNT      = (u16vp) 0x400010E;

static u16vp   REG_SCD0      = (u16vp) 0x4000120;
static u16vp   REG_SCD1      = (u16vp) 0x4000122;
static u16vp   REG_SCD2      = (u16vp) 0x4000124;
static u16vp   REG_SCD3      = (u16vp) 0x4000126;

static u32vp   REG_SCCNT      = (u32vp) 0x4000128;
static u16vp   REG_SCCNT_L      = (u16vp) 0x4000128;
static u16vp   REG_SCCNT_H      = (u16vp) 0x400012A;

static u16vp   REG_P1         = (u16vp) 0x4000130;
static u16vp   REG_P1CNT      = (u16vp) 0x4000132;
static u16vp   REG_R         = (u16vp) 0x4000134;
static u16vp   REG_HS_CTRL      = (u16vp) 0x4000140;

static u32vp   REG_JOYRE      = (u32vp) 0x4000150;
static u16vp   REG_JOYRE_L      = (u16vp) 0x4000150;
static u16vp   REG_JOYRE_H      = (u16vp) 0x4000152;

static u32vp   REG_JOYTR      = (u32vp) 0x4000154;
static u16vp   REG_JOYTR_L      = (u16vp) 0x4000154;
static u16vp   REG_JOYTR_H      = (u16vp) 0x4000156;

static u32vp   REG_JSTAT      = (u32vp) 0x4000158;
static u16vp   REG_JSTAT_L      = (u16vp) 0x4000158;
static u16vp   REG_JSTAT_H      = (u16vp) 0x400015A;

static u16vp   REG_IE         = (u16vp) 0x4000200;
static u16vp   REG_IF         = (u16vp) 0x4000202;

static u16vp   REG_WSCNT      = (u16vp) 0x4000204;
static u16vp   REG_IME         = (u16vp) 0x4000208;
static u16vp   REG_PAUSE      = (u16vp) 0x4000300;


The contents of credits001.h (less array contents):
Code:
unsigned u16 credits001[] = { ... };


And finally, my original picture, and the output on the GBA:
Original:
[Images not permitted - Click here to view it]

GBA:
[Images not permitted - Click here to view it]

Sorry everyline doesn't line up, it's just cut and pasted into the window. I can post my makefile as well if it's needed.

And finally, I know VideoBuffer is a u16*, but in Mode 3, doesn't a single pixel take 16 bits? 5 red, 5 green, 5 blue and one unused? Perhaps I've got this more wrong than I thought. Oh well. In any case, thank you for your input.
_________________
The Game is Nothing.
The Playing of it Everything

#20858 - sajiimori - Tue May 18, 2004 8:04 pm

Your image array isn't const, and it's too big for IWRAM.

Your register vars are taking up a lot of RAM, multiplied by the number of places you include the header. Make them const and they'll be like #defines (if you compile as C++).
Quote:

And finally, I know VideoBuffer is a u16*, but in Mode 3, doesn't a single pixel take 16 bits?

Yup. And in mode 4, which is what you said you were using, pixels take 8 bits. Upon closer inspection, your second version actually does set mode 3 (albeit using magic numbers rather than ORing named values).

#20883 - ravenq - Wed May 19, 2004 1:05 am

Ah, yeah, sorry about that *embarrassed look* I changed it to Mode 3 to ensure it wasn't just the way I was handling the palette data.

In any case, this should fix it, so thank you for your help Sajiimori!
_________________
The Game is Nothing.
The Playing of it Everything