Tile Mapping Libnds or PAlib

Discussion in 'NDS - Emulation and Homebrew' started by Dr.Razor, Apr 24, 2012.

Apr 24, 2012

Tile Mapping Libnds or PAlib by Dr.Razor at 7:02 PM (1,451 Views / 0 Likes) 15 replies

  1. Dr.Razor
    OP

    Member Dr.Razor GBAtemp Regular

    Joined:
    Oct 25, 2008
    Messages:
    109
    Country:
    Switzerland
    Hi,
    I'm looking for a tuto about tile mapping. I have a 2 dimensionnal array with the number of my tiles. (0,1,..)
    but I don't find any information about how to set them as background with Palib or Libnds.
    Actually, I'm using the 3Dsprit function in palib to display my array on the screen. ( As I need 192 "objects" on the screen)
    Another problem is that I want to use 16x16 tiles, but I guess I'll just have to create a routine to display
    4 8x8 tiles.

    If someone could give me an example, it would be perfect :D
     
  2. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    The examples are actually in the PAlib directory.

    The PAlib converter takes an image and cuts it into pieces starting with the upper left-hand corner (Tile 0), they're 8 by 8 pixels large by default as you already know but you may change that as far as I know. The resulting files after the conversion are a MAP for the original image, a BIN containing the tileset and a PAL holding the palette.

    The loading of such a background is performed by using the PA_LoadBackground function, you can however alter the Tiles displayed by using PA_SetMapTileAll or PA_SetMapTile in which you specify the X and Y values of the tile (Pixel X position / TileWidth and Pixel Y position / TileHeight) and the specific Tile number for which you want to swap.

    All you have to do is loop through that Array of yours when tiles are supposed to change and swap tiles on the fly.

    I do recommend switching to NightFox lib - you WILL run into problems with PALib eventually as the library has been discontinued. If you feel you're up to the task, you can also try pure libnds - the documentation for background loading is in the devkitPro examples folder. ;)
     
  3. Dirbaio

    Member Dirbaio GBAtemp Regular

    Joined:
    Sep 26, 2010
    Messages:
    158
    Location:
    Spain
    Country:
    Spain
    PALib is dead, DON'T use it.

    ...

    No, seriously, don't :) LibNDS is way better though it's a bit more less functional, you'll have to code some extra stuff.

    Basically, to get a background working in LibNDS, use the bgInit functions, and then use bgGetMapPtr and bgGetCharPtr to get where the BG data is stored and copy your data there :)
     
  4. smealum

    Member smealum growing up sucks.

    Joined:
    May 1, 2006
    Messages:
    626
    Location:
    SF
    Country:
    United States
    Totally not a big deal but you mention you use a 2D array to store your map; you probably shouldn't. Better practice would be to store it in a 1D array (you can do that by accessing array[x][y] as array[x+y*width]).
    Of course that's not always true, 2D arrays do have their uses, but for a tilemap, which you're eventually going to want to copy to the VRAM it is, as you'll then be able to copy it all in one go.
     
  5. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    I don't think he wants to do that - I believe he wants to have a fixed amount of Tiles and simply display different ones at given times - they're all in VRAM at once, it's just the map that changes.
     
  6. smealum

    Member smealum growing up sucks.

    Joined:
    May 1, 2006
    Messages:
    626
    Location:
    SF
    Country:
    United States
    I'm sorry, I'm not sure I understand what you mean, or rather how any of what you say conflicts with my suggestion.
    (I also forgot to mention that 2D arrays take up more space than their 1D counterparts; it is usually very much negligible but might as well be thorough...)
     
  7. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    It was my understanding that the tilesets for backgrounds in PAlib (and NFLib for that matter), unless one chooses to create a custom tileswap routine, are in VRAM in their entirety (Except for the buggy PA_Unlimited backgrounds which should be avoided at all costs) by default while the map simply directs which tiles are snapped to which positions on the background grid - you mention transfers to VRAM which in this case would not take place.
     
  8. smealum

    Member smealum growing up sucks.

    Joined:
    May 1, 2006
    Messages:
    626
    Location:
    SF
    Country:
    United States
    Well, where do you think the map has to be stored for the 2D hardware to access it ? :P
     
  9. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    That... makes sense lol.

    Pardonne-moi, vous avez raison. :ha:
     
  10. Dirbaio

    Member Dirbaio GBAtemp Regular

    Joined:
    Sep 26, 2010
    Messages:
    158
    Location:
    Spain
    Country:
    Spain
    Wait, what?

    2D arrays aren't bigger than their 1D counterparts, and they *can* be copied to VRAM in one go.

    ushort tilemap[32][32];
    tilemap[someX][someY] = someTile;
    memcpy(somePtrInVRAM, tilemap, sizeof(tilemap)); //Or DMA equivalent.

    It is also possible to get a 2D array pointer pointing to VRAM so you read/write from it as a 2D array. As long as all reads/writes are 16bit it should work.

    (C++ vectors are an entirely different story)
     
  11. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    I would also choose a 2D array, but for different reasons entirely.

    It simply comes as more natural to think in two dimensions when working in two-dimensional space - when I know I'm going to assign things by rows and columns, why would I employ unnecessary maths to search for them? Afterall...

    ATile[Row][Column] would have to be catalogued as ATile[Column + (Row*TotalNumberOfColumns)] in a single-dimension array - it's pointless to do so in my opinion, even if it "saves" miniscule amounts of the scarce VRAM.
     
  12. smealum

    Member smealum growing up sucks.

    Joined:
    May 1, 2006
    Messages:
    626
    Location:
    SF
    Country:
    United States
    Ok, so I guess I'm actually a bit wrong here. See, what I had in mind was this kind of dynamically allocated 2D array :


    int** array=malloc(sizeof(int*)*sizex);
    for(i=0;i
     
  13. Dr.Razor
    OP

    Member Dr.Razor GBAtemp Regular

    Joined:
    Oct 25, 2008
    Messages:
    109
    Country:
    Switzerland
    Thank you I was able to do exactly what I wanted :D
    Another question though, How many tiles can I have per background ?
     
  14. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    Depends on the size of the tile and the colour depth.

    Each default tile consists of 8x8 = 64 pixels and each of those pixels may be one of 256 colours (thus each being the size of 8 bits), so 64 x 256 = 16384 bits per default tile.

    You can fit as many tiles as you can fit in VRAM or *even more* if you employ a tile swap routines, but you get the drill now so you can calculate it.

    To simplify it, you can use one VRAM bank per background if you're using libnds, as for the PALib or NFLib limits, you have to check the documentation.
     
  15. Dirbaio

    Member Dirbaio GBAtemp Regular

    Joined:
    Sep 26, 2010
    Messages:
    158
    Location:
    Spain
    Country:
    Spain
    Smealum: yes, the array width needs to be known at compile-time, you're absolutely right. For fixed width arrays I usually use 2D arrays because I can, and for variable-width arrays it's better to use 1D arrays and do the x+y*width thing :)

    For getting pointers to the map data you can do something like

    typedef ushort[32][32] tilemap;
    (...)
    tilemap* ptr = (tilemap*) bgGetMapPtr(bg3);
    ptr[3][2] = 10;

    or something like that. But yea, it doesn't allow fixed width :(

    ----

    Dr. Razor: about how many tiles you can fit in a BG.

    There are two limits for it. First is the type of BG. There are 8bit BGs and 16bit BGs, the difference is that the tile number is 8 or 16 bit, obviously.
    8 bit BGs -> 256 possible different tiles.
    16 bit BGs -> 1024 possible different tiles. The 16 bits are used for x/y flipping (2bit), palette number (4bit) and tile number (10bit)
    So one BG can't have more than 256 or 1024 possible tiles. Even if you have more VRAM.

    The second limit is the VRAM space. One tile is 8x8 pixels, 1 byte per pixel, so 64 bytes.
    1 big VRAM block is 128kb = 131072 bytes = 2048 tiles.

    (actually a bit less if you have to store the BG map too)

    Depending on how many tiles you'll want to have you can use more or less VRAM for tiles, so you can have VRAM for other uses too.
    Also BGs can share tiles, or can have their own tilesets, or even share only parts of it. You can layout the VRAM the way you want by playing with the tile and map offsets of each BG.

    (wow, longest post ever)
     
  16. Foxi4

    Reporter Foxi4 On the hunt...

    pip
    Joined:
    Sep 13, 2009
    Messages:
    22,705
    Location:
    Gaming Grotto
    Country:
    Poland
    -Snip! I stand corrected.-
     

Share This Page