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.

C/C++ > Arrays of pointers to image data == black screens?

#34448 - Kyoufu Kawa - Wed Jan 19, 2005 7:49 pm

Greetings. I'm writing a game (what a surprise) that has several still images. In the first run, these images were loaded to VRAM as needed by three DMA calls. In the second run, I had three arrays listing each picture's tiles, map and palette. This however didn't work and gave me blackness. I suppose this is because I don't know jack about pointers and stuff like that yet so I guess it's just a missing & or something. Third run, which I don't intend to use, has several if clauses, which is as wasteful as the first run. Here's the code. I originally intended to use just one array but this will suffice. I hope one of you guys/gals can show me how to make it go.

Code:
#include "pics.h"
...
const u8 *picTiles[] =
{
   scene_title_Tiles,
   scene_intro_Tiles,
   ...
   scene_gameover_Tiles
};
const u16 *picPals[] =
{
   scene_title_Palette,
   scene_intro_Palette,
   ...
   scene_gameover_Palette
};
const u16 *picMaps[] =
{
   scene_title_Map,
   scene_intro_Map,
   ...
   scene_gaemover_Map
};

void ShowPic(u16 picture)
{
// Third run code
//   if(picture==1)
//   {
//      DmaArrayCopy(3, scene_intro_Tiles, BG_VRAM+0x4000, 32);
//      DmaArrayCopy(3, scene_intro_Palette, BG_PLTT, 32);
//      DmaArrayCopy(3, scene_intro_Map, BG_VRAM+0x0800, 32);
//   }

// Second run code
   DmaArrayCopy(3, picTiles[picture], BG_VRAM+0x4000, 32);
  DmaArrayCopy(3, picPals[picture], BG_PLTT, 32);
  DmaArrayCopy(3, picMaps[picture], BG_VRAM+0x0800, 32);
}


Thank you for your time.

#34457 - Mucca - Wed Jan 19, 2005 9:49 pm

I assume the pointers within your arrays of pointers (eg scene_title_Tiles) are themselves declared as arrays in pics.h, otherwise array copy wont work (it wouldnt know the size to copy if they were just external symbols in an object file created from raw binary data).
Also make sure the background layer you're using has its tile base block set to 2 (because of 0x4000) and screen map offset set to 1 (0x800). Use Visual Boy Advance to check if anything at all is getting copied to VRAM or Palette RAM, and also the background control register. The way you're passing the pointers to the Dma macro seems fine to me.

#34496 - Kyoufu Kawa - Thu Jan 20, 2005 3:22 pm

Well, each image has it's own .c and .o file. pics.h consists mostly of extern const statements. Array sizes are defined for all in this header.

The background register has been set up correctly, never mind that.

#34499 - Cearn - Thu Jan 20, 2005 3:47 pm

Exactly how would DmaArrayCopy know how much data it needs to copy? I see source and destination, but nothing to do with length. The only way that I could think of is that if you are using the sizeof operator inside it; but that'd only give you the size of the pointer (i.e., 4), not the size of the array. See here for a bit more on how sizeof works. If it's not done with sizeof, then how?

#34504 - Mucca - Thu Jan 20, 2005 5:20 pm

In fact you'll know if its a sizeof problem if you look at the memory in VBA and only four bytes are being copied. Probably easiest with palette memory at 0x05000000, as I doubt the first two colours in your palette are black, whereas with tiles the first tile probably should be all zeroes.

But if they are declared as arrays with static size in the header file, regardless whats in the c file, then sizeof should return the size of the array. However, if the array is at any stage reinterpreted as a pointer rather than an array, as in your method two, then sizeof will return the size of the pointer not the array. ie

int getSize(char * ptr){
return sizeof(ptr);
}

main()
{
char mystr[] = "I am not me";
...
cout <<sizeof mystr
<<getSize(mystr);

}

will output
12
4

So, I think third method should work, but not second method. Actually the third method mightn't work either if the arrays are external.
Regardless, you should probably start converting everthing to raw binary and using objcopy to convert to object files. Then you get a start, end, and size symbol. The FAQ at devrs details this.

#34512 - Kyoufu Kawa - Thu Jan 20, 2005 7:58 pm

Actually, the third method works fine. It's just very much of a waste.

#35580 - Kyoufu Kawa - Mon Feb 07, 2005 3:40 pm

I'm sorry to bump this but I would like to know how to make the second method work. I considered just copying the data in a for loop but would like to know the opinion(s) of anyone who knows better.

#35583 - Cearn - Mon Feb 07, 2005 4:32 pm

Kyoufu Kawa wrote:
I'm sorry to bump this but I would like to know how to make the second method work. I considered just copying the data in a for loop but would like to know the opinion(s) of anyone who knows better.

You can't. At least, not directly. Just like Mucca says: "if the array is at any stage reinterpreted as a pointer rather than an array, as in your method two, then sizeof will return the size of the pointer not the array". However, what you could do is build a table with the array sizes as well. Am I correct that DmaArrayCopy is defined like this?
Code:
#define DmaArrayCopy(  DmaNo, Srcp, Destp, Bit)             \
        DmaCopy(       DmaNo, Srcp, Destp, sizeof(Srcp), Bit)

If so, all you need to do after you've build your size table is use DmaCopy instead of DmaArrayCopy, with the right size instead of the sizeof(Srcp). Assuming properly initialized tables picTileSizes, picPalSizes and picMapSizes, it could be something like this:
Code:
    DmaCopy(3, picTiles[picture], BG_VRAM+0x4000, picTileSizes[picture], 32);
    DmaCopy(3, picPals[picture], BG_PLTT, picPalSizes[picture], 32);
    DmaCopy(3, picMaps[picture], BG_VRAM+0x0800, picMapSizes[picture], 32);

#35593 - Kyoufu Kawa - Mon Feb 07, 2005 8:11 pm

No need to bother with size tables. The tilesets are all the same size, as are the palettes (which are 240 entries per pic btw)

I'll keep your suggestion(s) in mind, thank you very much.




I'M DUTCH! HAHAHA!!1

#35626 - Kyoufu Kawa - Tue Feb 08, 2005 3:26 pm

And it is teh done. Thank you all for your help on this matter.

Code:
u16* thisPal;
u16* thisPic;

thisPal = picPals[picture]; //warning: assignment discards qualifiers from pointer target type
thisPic = picTiles[picture]; //warning: assignment from incompatible pointer type

DmaCopy(3, thisPal, BG_PLTT, 480, 32);
DmaCopy(3, thisPic, BG_VRAM+0x4000, 30720, 32);

//Where 480 == 240 * 2 == 15 strips of 16-bit colors and 30720 == the constant size of my pics.


Unexpected: this shit's fast enough to do full motion video. I already have a kind of "relative frame indexing" array ready and working.

...how did Cearn know the definition of DmaArrayCopy, which indeed was DmaCopy(DmaNo,Srcp,Destp,sizeof(Srcp),Bit), including the exact whitespacing? Is it that much of a standard? Or does Cearn have... wouldn't surprise me.

#35628 - Cearn - Tue Feb 08, 2005 3:39 pm

I saw it in darkfader's stuff a very long time ago. Thought it looked familiar so I checked and there it was.

Glad to see it all works now :). Btw, if you're wondering why you get those warnings, that's because your arrays are `const u16*', while the pointer is just `u16*'. C doesn't like it when you throw away things like constness and such. Not that it matters in this case of course. An explicit cast should get rid of the warnings.
Code:
thisPal = (u16*)picPals[picture];

#35629 - Kyoufu Kawa - Tue Feb 08, 2005 3:54 pm

Cearn wrote:
Glad to see it all works now :). Btw, if you're wondering why you get those warnings, that's because your arrays are `const u16*', while the pointer is just `u16*'. C doesn't like it when you throw away things like constness and such. Not that it matters in this case of course. An explicit cast should get rid of the warnings.
Okay, thanks. I'll change that ASAP.

Y'know, my group intro screen spawns "implicit truncation" warnings, but now I can replace it with a short movie so why bother?