#105720 - Diirewolf - Wed Oct 11, 2006 2:25 pm
Im trying to use 2d tiled sprites (ie. not specifying OBJ_1D_MAP when calling SetMode) with Mode4. First, i know i have to index the tiles starting from 512, so this shoudln't be a problem. Second, i know that i have to copy my sprite gfx to BITMAP_OBJ_BASE_ADR(0x6014000) instead of SPRITE_GFX(0x6010000). Now when i do this, my objects don't display properly. Now im pretty sure im indexing my tiles right (attribute 2). The thing im not sure about is how to copy the data to the BITMAP_OBJ_BASE_ADR. I read somewhere that when using 2d tiled sprites, you have to copy your graphics differently to the sprite graphics but i never found out how exactly. Can someone explain how to do this properly or suggest what else i might be doing wrong?
Thanks
edit:
heres my current code:
dmaCopy(sprites_Palette, SPRITE_PALETTE, sizeof(sprites_Palette));
int x, y;
for(y = 0; y < 24; y++)
{
for (x = 0; x < 32; x++)
{
((u16*)BITMAP_OBJ_BASE_ADR)[y * 128 + x] = sprites_Bitmap[y * 32 + x];
}
}
#105741 - poslundc - Wed Oct 11, 2006 5:29 pm
The simplest answer is not to use 2D sprite mapping. Use 1D instead. I can think of at most two or three reasons to ever use 2D mapping, and they probably aren't your reasons.
I've deleted your other post. Please don't crosspost.
Dan.
#105743 - Diirewolf - Wed Oct 11, 2006 5:38 pm
ye sry bout the crosspost. I though of using 1d sprite mapping, but i would prefer to use 2d and even if i use 1d, i want to know how to do 2d sprite tile mapping just for the knowledge, and i know how to do it, but the question is how do i copy my image data to 0x6014000.
#105861 - Cearn - Thu Oct 12, 2006 6:22 pm
In 1d mapping, all the tiles of the object are continuous; in 2d mapping each tile-row has a tile offset of 32 (i.e., 256 bytes). For example, a 32x16 pixel object has 2 rows of 4 tiles. Supposing you used 0 in attribute 2, the tiles used are 0, 1, 2, 3, 4, 5, 6, 7. In 2d mode, it'd use tiles 0, 1, 2, 3 and 32, 33, 34, 35.
Code: |
32x16p (4x2t) object
Tiles in 1D:
---------------
| 0 | 1 | 2 | 3 |
---+---+---+---
| 4 | 5 | 6 | 7 |
---------------
Tiles in 2D:
-------------------
| 0 | 1 | 2 | 3 |
----+----+----+----
| 32 | 33 | 34 | 35 |
-------------------
|
In the 1D case you can use a single memcpy of 256 bytes, in 2D mapping you'd have to break it up into 2 parts of 128 bytes, which may be annoying. Unless your object bitmap is of the appripriate width so that it can be copied to VRAM as a whole; in that case 2D mapping may be quite useful.
#105870 - Diirewolf - Thu Oct 12, 2006 7:38 pm
what exactly do you mean by splitting it up into 2 parts of 128 bytes? can you provide some code for doing this... lets say... for a 24 x 32 image ie. 3 x 4 tiles. 2D mapping seems the most logical way to map sprites imo. Also i have used vba to see the tiles of some Nintendo games and they use 2d tiling and i figure it makes perfect sense to use 2d mapping so why does everyone discourage me on using 2d mapping? Also there is no tutorial/article which describes in detail 2d mapping, they all just say that there is something called 2d mapping but 1d is better so use that.
#105871 - tepples - Thu Oct 12, 2006 8:20 pm
2D mapping essentially considers the sprite cel VRAM as a big bitmap, much like the sprite sheets you see on resources for sprite comic artists. This bitmap is 256 pixels wide for 16-color cels and 128 pixels wide for 256-color cels, and it is 256 pixels tall in background modes 0-2 and 128 pixels tall in background modes 3-5. When loading a sprite cel into a 2D VRAM, you'll need to call memcpy() once per eight pixels of the cel's height. For example a 32 pixel tall sprite cel takes four memcpy() calls, one for each row of tiles that make up the cel.
One reason why a lot of people recommend 1D is that the more dimensions you have, the more likely you are to run into external fragmentation.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#105877 - Cearn - Thu Oct 12, 2006 9:28 pm
Diirewolf wrote: |
what exactly do you mean by splitting it up into 2 parts of 128 bytes? Can you provide some code for doing this... lets say... for a 24 x 32 image ie. 3 x 4 tiles |
Essentially, it's the same as how you divided the bitmap in your earlier code into rows of 64 (=32*sizeof(u16)) bytes with the two loops. The destination buffer has a different width than the source, so you have to copy in each scanline separately. If both were 64 bytes wide, you'd only have to use a single loop. Or, rather, no loop, because it's usually more efficient to copy blocks of memory (the x-loop) with dedicated copy routines like memcpy.
But aside from that, now that I look at it more closely, I think you're missing a couple of crucial points about the organisation of bitmaps and tiles. First, bitdepth and datatypes. Different bitdepths have different pitches (bytes per scanline), and you need to take that into account when copying. In this case, you seem to be trying to copy from a 32x24 @ 16bpp source bitmap to a 256xheight @ 8bpp destination. Or a 128xheight @ 16bpp destination. Or any of the other possible width+bitdepth combinations, but none that have a relation to anything you might see on the GBA. NDS objects maybe, but not GBA.
The second problem is tiles. I don't think the word means what you think it does. The GBA tile graphics have their graphics in 8x8 pixel mini-bitmaps called tiles. All the pixels of these tiles are stored in sequence: the top scanline of each tile is immediately followed by its next row and not by the top scanline of the next tile. The VBA tile viewer is a little misleading in this respect: it depicts tile VRAM as a 256x256 bitmap, but this does not accurately indicate the way in which the data is stored in memory. If you still want to go by the address = y*pitch + x formula for bitmaps, it should have been a a stack of 1024 8x8 tiles, in other words a 8x8192 bitmap (8 pixels wide, 8192 pixels high). However, this is slightly impractical.
GBA tiles come in two forms: 4bpp and 8bpp, for 32 and 64 bytes, respectively. Because these bytes are consecutive in memory, the tile can be considered a unit as well, just like bytes, shorts and ints. Obj VRAM can then be viewed as containing 1024 4bpp tiles or 512 8bpp tiles.
1D mapping considers obj VRAM as an 1024 (or 512) long array of tiles. When you choose a tile index in attr2, that becomes the starting tile, and the next N number of tiles will be used to make up the object on screen. As I said earlier, a 32x16 sprite with tile 0 would use tiles 0-7. 2D mode is different. It sees obj VRAM as a matrix; 32x32 or 16x32 tiles in size. This is more bitmap-like, only with tiles as units instead of pixels. The on-screen object is a matrix of TW x TH tiles, which are taken from a TW x TH section of VRAM as well. Because the matrix is 32 tiles wide, each row of tiles in the object is offset by 32 tiles, instead of following the previous row immediately like in 1D mapping. Because you how have a gap between destinations, you need to copy each rows separately. In the case of a 32x16 @ 4bpp object, that's two rows of 4 tiles, is two rows of 4*32=128 consecutive bytes.
#105927 - Diirewolf - Fri Oct 13, 2006 7:35 am
thx for the detailed description cearn!