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.

Graphics > Modes, tiles

#15141 - Dreamer - Sat Jan 17, 2004 10:21 pm

Wasn't sure if this would be better for Beginner forum or Graphics, but here goes. I tried searching for this but didn't find an answer.

I'm working now on Tetris for practice, and want to eventually start working on an RPG. For Tetris, I was using Mode 1 and worked with sprites just fine, until I couldn't find any sources on showing images with it. So I switched to Mode 4, and while I found out how to show both sprites and images (although I'm having trouble showing one image, fading out, and showing another; the second one shows up looking very dark and shadowed), but now I'm trying to use tile backgrounds to draw dynamic blocks, and to draw interface.

Using source from gbajunkie's chapter 6 tutorial, I can get the tile background thing to work, but not in Mode 4 (his works in Modes 0, 1, and 2 only). Pern Project's Day 4 tutorial for this used Mode 1 also.

Ok so long story short, if I want to work with sprites, tile maps, and full images, what would be a good mode to work with, and would you be able to point out any good source on those?

#15143 - DekuTree64 - Sat Jan 17, 2004 11:07 pm

Use mode 0 or 1, depending on if you need rotation/scaling on your BG. If you just run your image through a tile converter program, and then you can use the tile map it outputs and just go along copying those entries into your BG screen block to display the image. Then you still have the other BG layers to do tile graphics with. Mode4 is only really needed for 3D and such, where you need a double buffered linear bitmap. For a static background image, a tile layer is perfectly fine
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#15147 - Dreamer - Sun Jan 18, 2004 1:50 am

Damn. Just when I had most of the gameplay mechanics working. Changing modes gives me a headache. None of my sprite code seems to work between modes, but at least the refactoring I do has given me some nice functionality. *sigh* Back to the drawing board.

#15158 - tepples - Sun Jan 18, 2004 5:54 am

Background display modes shouldn't affect sprite display except for two things:
  1. Sprites won't show up if a higher-priority background covers them completely with opaque pixels. Modes 3 and 5 have no known way to make parts of the background transparent except perhaps with windowing.
  2. Modes 3, 4, and 5 require all sprite cels to sit in positions 512-1023.
What contrary results have you found?
Try getting the simplest thing working, and then refactor it, making sure it still works after each step.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#15163 - Dreamer - Sun Jan 18, 2004 6:04 am

I can't recall exactly what was not working, I think it might have been some different defines like OAMData. I still don't quite understand what all of the memory and registers are doing, so I assumed it was that I was using the wrong mode.

As for the refactoring, I've spent an hour and a half just now commenting and uncommenting one line at a time trying to figure out why a method is getting an 'undefined reference' compile error. Perhaps someone can shed light (although it is a bit off-topic):

I have my Main.c file in my program directory. I have Background.h and Background.cpp in a subdirectory. Background.cpp has a method called EnableBackground ( * bg ). I #included Background.h in Main.c so that I could call EnableBackground(&bg2). However, when I try to compile, it says undefined reference, even though I included the file. I have no idea why it is doing this, and my best guess is something to do with using .c and .cpp files, or the pass by reference of bg2. Any help?

Also, using a tile map for a background, would someone be able to point me in a direction to know how to, say, during the game dynamically draw a tile on a background using the same loaded tileset? Or must a tile background be drawn directly from the map into memory (without being able to specify x,y coordinates)?

Edit: Actually for that last one I somewhat figured it out, the only problem is, is there a way to do an 8-bit copy when the background tile data array is of type unsigned short? I.e. the following uses the Bricks map that just has a bunch of tiles painted on, and the assignment will change the first 16x8 chunk of the map data to the Bricks data, but I only want to change the first 8x8 chunk. Is this something I can do? Or would I need to figure out how to rewrite the tile code for 8-bit copy?
Code:

temp = (u16*)Bricks;
bg2.mapData[0] = temp[0];

#15166 - sajiimori - Sun Jan 18, 2004 7:48 am

Quote:

I #included Background.h in Main.c so that I could call EnableBackground(&bg2). However, when I try to compile, it says undefined reference, even though I included the file.

You need to compile background.cpp seperately and link it in. That's where the definitions are, so if you don't link it in the linker will complain about things that haven't been defined.
Quote:

Edit: Actually for that last one I somewhat figured it out, the only problem is, is there a way to do an 8-bit copy when the background tile data array is of type unsigned short? I.e. the following uses the Bricks map that just has a bunch of tiles painted on, and the assignment will change the first 16x8 chunk of the map data to the Bricks data, but I only want to change the first 8x8 chunk. Is this something I can do? Or would I need to figure out how to rewrite the tile code for 8-bit copy?

Sounds like you're using a rot/scale background (which uses a byte per tile). Since you can only write 2 bytes to VRAM at a time, replacing a single tile requires reading 2 tiles, replacing one of them, and writing them both back.

#15167 - Dreamer - Sun Jan 18, 2004 8:01 am

Quote:

You need to compile background.cpp seperately and link it in. That's where the definitions are, so if you don't link it in the linker will complain about things that haven't been defined.


My batch file for compiling looks like this (partial). Isn't that compiling it and linking?:
Code:

gcc -c -O3 -mthumb -mthumb-interwork Functionality\Background.cpp
gcc -c -O3 -mthumb -mthumb-interwork Main.c
gcc -mthumb -mthumb-interwork -o Main.elf Main.o Graphics.o Sprites.o Objects.o Pieces.o Background.o



Quote:

Sounds like you're using a rot/scale background (which uses a byte per tile). Since you can only write 2 bytes to VRAM at a time, replacing a single tile requires reading 2 tiles, replacing one of them, and writing them both back.


I'm using the example from Pern Project Day 4 Tutorial. Is there some way I can draw 8x8 dynamically instead of these blocks of 16x8 (i.e. some other source example that uses a different tile method or something). Also, I noticed that, just in testing, dynamically changing the tiles doesn't work at all after the first UpdateOAM() call.

#15175 - poslundc - Sun Jan 18, 2004 4:48 pm

sajiimori wrote:
Sounds like you're using a rot/scale background (which uses a byte per tile). Since you can only write 2 bytes to VRAM at a time, replacing a single tile requires reading 2 tiles, replacing one of them, and writing them both back.


I'm pretty sure you can write one byte at a time to VRAM... it's just a waste of cycles, since VRAM is accessed 16 bits at a time.

To do this in C, you would typecast your pointer if it was declared as some other type.

Code:
u16   *p = SOME_ADDRESS;

*((u8 *)p + somevalue) = singlebyte;

   or

u8   *q = (u8 *)p;
*(q + somevalue) = singlebyte;
   or
q[somevalue] = singlebyte;


Dan.

#15181 - Dreamer - Sun Jan 18, 2004 5:25 pm

I tried playing with the casting, but it didn't work. I tried all three ways you suggested and it still transferred two 8x8 blocks instead of one, i.e.:

Code:

   u8   *q = (u8 *)bg2.mapData;
   q[0] = Bricks[0];


Where bg2.mapData is the u16 array, and Bricks is a u8 array that stores the 8x8 tiles I want to transfer.

Edit: Ok never mind, I somewhat found out how to get it to work. I need to store the map data in an 8bit array as well, and copy over two sections at a time using that as a reference, like bg2.mapData[0] = Bricks[0] + bg2.map8[1]<<8). Thanks for the help though.