Flash Free Screens From SD

From Uzebox Wiki
Revision as of 03:48, 31 October 2014 by D3thAdd3r (talk | contribs) (Created page with "==Introduction== This is another short and sweet tutorial. This in particular will be very useful in many games, especially if you are already using the SD card for something e...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Introduction

This is another short and sweet tutorial. This in particular will be very useful in many games, especially if you are already using the SD card for something else(and you already paid the flash space footprint for the code). The basic concept here is to use a large ram buffer to grab graphical data from the SD card. Then we want to use that ram to display to screen. Conveniently, Mode 3 ram_tiles[] is a large buffer of data that we can readily display on the screen. We can also load some data into vram, which will the actual tile indices to draw. It's just like we might normally do with a map stored in flash with DrawMap2(). This technique can easily be applied to any of the tile only modes that lack ram tiles, to at least save the space of the map in flash. Without ram tiles, there is no way to actually store the tile data in ram in a way we can display it on the screen. Even just maps take up a lot of space, so this can still help us considerably. After you understand the rather simple technique it could also be applied to the bitmap modes, an RLE mode I hope to release, etc. This tutorial will assume Mode 3.


Formatting The Data

Before we can draw something on the screen, we need the data to be on the SD card. We will need to create a file where we will store our graphics data in binary form, or perhaps you already have it for other resources. To make it easier, and because the storage of the SD card is nearly infinite for most purposes related to Uzebox, we will just use totally uncompressed data. There are many ways this could be done, either manually with a hex editor and a little copy/paste by hand or a program. The method I have used is simply to use TileStudio with a custom conversion script(you can use gconvert of course) to generate the tile and map data as per usual. Using a text editor like notepad++ delete all characters that are not actual hexadecimal representations of the data. Now that you have the pure bytes of your tile graphics and map layout, open up your binary image and paste the tile graphics at some offset and write down that offset. Now someplace after that data paste the map data and note that offset. If everything went ok and there weren't any issues with formatting you should have all the pixels for your tiles, and the map for the screen you wish to draw. This is truly a kludge that I don't enjoy as it is a very tedious process. Please feel free to recommend a better tool and or process to use! This does work fine and probably quicker than writing a custom program though, that's why I do it that way/lazy.


Creating An Index Table

Imagine we have repeated that process 15 times and have a huge amount of data in a hex file. If you scroll through and look at it, there is really no clear order to it all-that's why I said write down the offsets! What we need to do, is store the offsets to the graphics data and the map data somewhere at a known location within the binary file. That way our program can go to this known offset, apply an additional offset based on which screen to draw(that offset will of course be the size of an index entry multiplied by which screen) and then know exactly where the data we want is. It will vary based on your games needs. This method is primarily meant for parts of a game where speed is not an issue, and we can devote all our ram tiles to draw the screen. My format for the current game I'm working on is as easy as this: 2 bytes - offset to first byte of ram tile data, 2 bytes - offset to first byte of tile data...that's it. In Lolo, I am attempting some pretty cool looking "Full Motion Video" using long sequences of these screens. Obviously that quickly surpasses the 16bit boundary so I ended up going with 3 byte offsets. Just an example of a few modification you may wish to make if you are doing something tricky. Most people can probably just use this very simple method and actually get something done instead of stewing over overly complex features :| This is what it looks like in a hex editor, notice that I am only really using the first 4 bytes but each of the entries takes a while line equaling 16 bytes. I personally do this because hex editors work nicely without changing setting for 16 wide columns, a little waste is pretty meaningless here, and it allows me to write some comments in case I have to track down a problem with the graphics(which will generally be because of a problem with the formatting while copy/pasting to the hex editor window).

Hexeditorneo1.png


Putting It On Screen

Now we have all the pixel data for our graphics tiles, we have the information for which tiles to draw where, and our program can easily find exactly where all that is in the SD card. The next part is just as simple, and it's where our hard work pays off! Understanding everything we have read so far, the following code should hopefully be self explanatory:

void RamifyFromSD(uint8_t id){

HideSprites();//IMPORTANT! sprite blitting during SD read will ruin our buffered data FRESULT res;

uint32_t off = (uint32_t)(id*16); uint32_t off2; WORD br;

res |= pf_lseek(off);//go to our index table res |= pf_read(ram_tiles,16,&br));//load up the entry data off = (uint32_t)((ram_tiles[0]<<8)+(ram_tiles[1]));//graphics offset off2 = (uint32_t)((ram_tiles[2]<<8)+(ram_tiles[3]));//map offset

res |= pf_lseek(off);//go to the offset we found in the table res |= pf_read((BYTE *)ram_tiles,(RAM_TILES_COUNT*64),&br);//load up the pixel data to ram tiles res |= pf_lseek(off2);//go to the offset we found in the table res |= pf_read((BYTE *)vram,(VRAM_TILES_H*SCREEN_TILES_V),&br);//load the map into vram

if(res) SDCrash();//whatever error handling you want to do, if any. }