#36505 - ymalik - Wed Feb 23, 2005 2:05 am
Hello,
I have generated a 9984x9728 8 BPP image. Please go here to see what I'm talking about: http://www.cs.stevens.edu/~ymalik/Tgr34031lkA.png Because I want to be able to scroll through the image, I broke up the image into 256x256 BMP images and ran gfx2gba with tile mode on them. I only saved the ones that had streets in them, so I ended up with 522 images versus 1482 images. I want the scrolling to be un interrupted, but each image has its own set of tiles and map (they all have the same palette). How can I accomplish this?
Thanks,
Yasir
#36506 - DekuTree64 - Wed Feb 23, 2005 2:37 am
You'll need to write a scrolling system that not only copies in strips of tiles at the edges of the screen, but also loads only the visible tiles into VRAM.
Since the screen is 240x160, or 30x20 tiles, and you can scroll half a tile horizontally and vertically, that means you can get 31x21 tiles on the screen at once. Then add one more row/column that's always offscreen, to copy in the new tiles without corrupting the edges, and you get 32x22, or 704 tiles in VRAM at once. Plenty small enough.
Then when you scroll the map, unload any tiles that went offscreen out of VRAM, and load in the new ones coming on. Easier said than done though.
I don't know how you generated that image, but if it's possible, I'd suggest inventing a vector-based format to store it, instead of a giant bitmap. Then either render the whole thing every frame in mode4 (might be too slow), or write a scrolling system that dynamically draws the new chars to load at the edges instead of loading them from ROM.
That would be a pretty big challenge to write, but would save a bunch of cart space, and you could zoom in and out (I'd hate to scroll around an image that size on a GBA :) ).
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#36513 - tepples - Wed Feb 23, 2005 3:49 am
Make the map image 4-bit instead of 8-bit, and you'll be able to fit 1024 unique tiles into VRAM at once. That will simplify the code a bit, as you won't have to worry about updating the map at all; just updating the tiles will suffice.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#36517 - dagamer34 - Wed Feb 23, 2005 5:11 am
Dynamically load the map by dividing it up into segments. The GBA doesn't have a HUGE screen so even if you could fit the entire map into VRAM, I doubt it will be displayed all at once.
_________________
Little kids and Playstation 2's don't mix. :(
#36519 - sajiimori - Wed Feb 23, 2005 6:05 am
Hasn't anybody written a fairly generic dynamic scrolling system that they'll share the code for? This topic comes up so often that it seems like a waste of time to keep rewriting that same old functionality.
I guess having a programming job has made me think "practical" rather than "challenging". ;)
(But seriously, refusal to share and adopt code must be the biggest limiting factor in homebrew GBA development.)
Last edited by sajiimori on Wed Feb 23, 2005 7:21 pm; edited 1 time in total
#36522 - ymalik - Wed Feb 23, 2005 3:35 pm
Much thanks for all your comments.
What DekuTree64 is proposing is what I was thinking about doing, but it just seemed overly completed and almost impossible. But I'll try that. I actually generated that map from an ESRI Shapefile using PHP's image extension. A shapefile is a vector image, and is only about 1 unit wide. The map I have posted is Passaic county, NJ. It is a small county, but has over 17000 lines. A bigger county, say somewhere in Texas, may have 3 times the number of lines in Passaic County. I have displayed a shapefile on the GBA, but just scanning through all the lines is a bottleneck: it takes 2-3 seconds to draw Passaic county, and since I am using fixed point path, there is no way I can get the resolution shown in the PNG image.
The diagonal text you see on the image is antialiased, and thus additional colors are stored in the palette. 256x256 was smallest I could make the image without gfx2gba warning me that the number of tiles exceed memory, since there are so many unique tiles. I doubt storing the text in a seperate image would produce a 16 color palette or have enough unique tiles to fit in memory.
By the way, I [looked at] LOZ: The Minish Cap to see how they do scrolling, and I notice that in the map viewer, a background is 256x256, but it is changing each time Link moves. The map, although, takes up only about 240x160 in the map viewer. [Buy it, rip it] and see for yourself. It's pretty amazing to see the scrolling in the map viewer.
And, yes, I would love to have a tiling engine.
mod says Yarr...
#36545 - AnthC - Thu Feb 24, 2005 1:32 am
There's many methods, some of them efficient and others inefficient.
Here?s an inefficient one :-
Just looking at your map you could recursively split it up into a quad tree.
You would save a high ratio on the blank areas using this method.
I did some tests; first I resized the canvas on your png to 16384x16384, reduced the colour depth to 16 colours, then I ran the map through a simple quadtree programme which crunched your city map into approx 8 megabytes using 16x16 blocks as the termination threshold.
Things I didn't try were looking for duplicate 16x16 pixel blocks and further block compression.
The resulting number of quadtree nodes was 29549 with 59832 16x16 blocks..
This means the bulk of the data was 16x16 blocks with a much smaller tree. Processing these blocks using run length coding + duplicate blocks, I would hazard a guess would reduce the size requirement by 50% to a more manageable 4 megs.
You could then decompress the relevant section on the fly quite quickly as most of the area is white space.
#36562 - AnthC - Thu Feb 24, 2005 5:17 pm
Could you upload the original shapefile/vector file or whatever ?
I'm doing something similar to this for a friend on mobile phones.
I'm thinking I could use a similar technique to a quadtree to sort the lines and minimise the amount of lines needed to be scanned per given area.
(Without original format the size restrictions on the comrpessed file will be an issue)
I've also looked at your other post on fixed point, I think it would be a simple matter of storing the lines in fixed point and writing a fixed point version of Bresenham to reduce rounding errors. If you round the points and use integer Breshenham you are going to get this 'waggle.'
My problems are
(1) Efficient data structure to store the lines (which I believe could be solved easily using trees - maybe BSP or quad etc.)
(2) Storing the line co-ordinates (trivial using floating point or fixed point)
(3) Plotting your lines (also trivial and very fast)
Thanks
Anth
#36567 - ymalik - Thu Feb 24, 2005 7:38 pm
Much thanks for your enthusiasm. I will read more into your posts now, but here are the uploaded files:
http://www.cs.stevens.edu/~ymalik/Tgr34031lkA.dbf.gz
http://www.cs.stevens.edu/~ymalik/Tgr34031lkA.shp.gz
You can download a Shapefile for every county in the U.S. from http://www.mapshots.com/downloads/tiger.asp
#36568 - ymalik - Thu Feb 24, 2005 7:51 pm
So a quadtree is a B-tree with 4 nodes. Can please tell me how this will help me in scrolling? I have split the image up into 256x256 images and images that have data (lines, street names) in them, as per my first post.
This is a part of my software engineering course, and this course has convinced me to think practically, and I'm looking for a solution that I can implement in the next few days.
#36577 - AnthC - Thu Feb 24, 2005 9:56 pm
ymalik wrote: |
So a quadtree is a B-tree with 4 nodes. Can please tell me how this will help me in scrolling? I have split the image up into 256x256 images and images that have data (lines, street names) in them, as per my first post.
This is a part of my software engineering course, and this course has convinced me to think practically, and I'm looking for a solution that I can implement in the next few days. |
2 problems ? efficiency and speed of display.
With efficiency the problem is that you have to scan large data sets to display your lines. A tree system should cut down that dataset into something more manageable than a brute force algorithm, so you would only consider a small percentage of your dataset ? the parts that could potentially be visible onscreen which is a small %age of your whole dataset.
With your bitmap (png) method a tree system would take advantage of the large spaces in your png and include these as large blank areas with no data storage. If you had mapped the png as a tile map then these large areas would be included as arrays which would be an inefficient method of storing them. (I believe you did this when you excluded screens with nothing on them)
If you have access to the line sets then a tree method would reject lines that are not on your screen very quickly and you would be left with a small section of your dataset to perform more efficient tests on.
Personally I would stick with tree/line sets as that seems much more efficient memory wise.
As with your scrolling, the tree would leave you with blocks that are potentially on screen and would not store areas that so obviously contain blank data.
Example
You have a screen composed of an array of tile index?s, where X is a blank 8x8 and A contains solid. The tree would cut this area up into blank areas which would _not_ be stored as arrays, only the areas with data on them would.
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXA
Storing this as a tile map would take 8x8 cells as a tree would take much less.
(This is just a crude example)
If you imagine your dataset (lines) split into 2 regions A B with a divider.
If your screen was in A then you would only consider the lines in A. If your screen was in B you would only consider the lines in B. The degree in which you split up your lines donates how many lines you would consier in your tests.
#36580 - AnthC - Fri Feb 25, 2005 12:52 am
I tried both these examples (winzip winrar in winxp) I got an error in each case. I also downloaded some map data from that site and got the same errors.
#36597 - ymalik - Fri Feb 25, 2005 5:49 pm
What errors are you getting? You can view the DBF file in Excel or
OpenOffice. The shapefile can be viewed in fgis. You can access the
contents of the shapefile using Shapelib. I have unzipped the files (they
don't have the .gz extension anymore).
#36612 - AnthC - Fri Feb 25, 2005 10:29 pm
I get invalid archive directory for one file and error reading dircetory after processing 0 entries for another for the other.
#36625 - ymalik - Sat Feb 26, 2005 5:46 am
I really don't know. Those files work fine in Unix and Windows for me.
#36633 - ymalik - Sat Feb 26, 2005 3:53 pm
Anthc's suggestion sounds too complicated for the moment. Our first demo is this Thursday, so I want to put together a dirty solution. What I plan on doing is displaying 256x256 background and loading a new background each time one scrolls too far. I created two arrays which had all of the tile and map data for the 522 smaller files (the output of gfx2gba was pieced together into one big array) and complementary offset arrays. The map data array was about 5 MB, which is managable. But the tile data file was a 27 MB array. I compiled the file using gcc -c in MinGW, but gcc stops and an error says cc1.exe: out of memory allocation 65536 bytes. cc1 leaves a VM footprint of more than 440 MB. How can I get around this? Would adding memory solve this (I would prefer a free solution at the momemt)? I have 256 MB of RAM.
Using the compression option in gfx2gba produces smaller tile files, and thus a smaller big array file that is compilable by gcc, but then I can't use DMA to simply load from the ROM into VRAM.
#36634 - tepples - Sat Feb 26, 2005 4:00 pm
Do not compile multimegabyte arrays with GCC. Find an alternative binary file inclusion method that bypasses GCC and goes straight to Binutils, such as bin2s (available as part of the GBFS package) or .incbin or objcopy (although objcopy doesn't allow to specify alignment).
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#36635 - ymalik - Sat Feb 26, 2005 4:21 pm
The file I am trying to compile is a giant C array--an ASCII file. But your bin2s program ``converts binary files to assembly language.''
#36638 - tepples - Sat Feb 26, 2005 6:56 pm
What program generated this C file?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#36640 - ymalik - Sat Feb 26, 2005 8:12 pm
Ok, here's what I'm doing:
I have 522 256x256 8 BPP BMP images. I run "gfx2gba -m -fsrc" (the one by Markus) on all of them to produce a C source file with all the tiles and a C source file with the map for each image. There is a single palette file. I then scan through each source file and pull out the tile data, piece everything together, format the string to include necessary declaration information, and then output the stuff into a file. This results in a 27 MB C file with one array that contains all tile data for all the images. I have a complementary file with another array that contains the offset and length of each tile data produced from an image, but that's a trivial size (about 20 KB). The samething is done for map data, but the conglomeration of all the map data into a file results in a 4 MB file, which is compilable by GCC. I used PHP to make the big files.
Much thanks, tepples, for sticking in there.
#36643 - tepples - Sat Feb 26, 2005 8:43 pm
ymalik wrote: |
I have 522 256x256 8 BPP BMP images. I run "gfx2gba -m -fsrc" (the one by Markus) on all of them to produce a C source file with all the tiles and a C source file with the map for each image. |
(For those playing at home, here's the gfx2gba 0.13 manual)
Try -fasm instead of -fsrc to produce an assembly file roughly as big as the C file but which can be compiled much more efficiently. Or if you're not doing source-level debugging with gdb, try -fraw and use GBFS to append your data files to the ROM.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#36649 - ymalik - Sat Feb 26, 2005 11:33 pm
I can't deal with ASM or binary files. I am clumping multiple raw.c and map.c files into one big raw file and one big map file. Here is an example:
Here is a file with offset and length pairs
Code: |
#include "offset_length.h"
const OffsetLength map_offset_lengths[] = {
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
{0, 0},
// square (0, 11)
{0, 1024},
// square (0, 12)
{1024, 1024},
{0, 0},
// square (0, 14)
{2048, 1024},
...
|
And here's the file with the map data. Each section after a comment represents what is stored in a separate map.c file.
Code: |
const unsigned short maps[] = {
// square (0, 11)
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
...
// square (0, 12)
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
...
// square (0, 14)
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
Likewise for the tile data.
However, your gbfs utility looks promising. I can just simply compile each separate raw.c and map.c file, and append it to the GBFS archive. I can call up the file using the name of the file, that's fine, but would I be able to access an array stored in the file, whose name is going to be different in each file, and do a DMA fast copy from it to VRAM?
Thanks,
Yasir
#36652 - tepples - Sun Feb 27, 2005 12:52 am
The way it works with GBFS is that you define a file format and then export raw binaries in that format. For instance, you could state that the first n bytes are the map and the rest of the file is tile data. You may need to design a header to express this.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#36654 - AnthC - Sun Feb 27, 2005 1:13 am
ymalik wrote: |
Anthc's suggestion sounds too complicated for the moment. Our first demo is this Thursday, so I want to put together a dirty solution. What I plan on doing is displaying 256x256 background and loading a new background each time one scrolls too far. I created two arrays which had all of the tile and map data for the 522 smaller files (the output of gfx2gba was pieced together into one big array) and complementary offset arrays. The map data array was about 5 MB, which is managable. But the tile data file was a 27 MB array. I compiled the file using gcc -c in MinGW, but gcc stops and an error says cc1.exe: out of memory allocation 65536 bytes. cc1 leaves a VM footprint of more than 440 MB. How can I get around this? Would adding memory solve this (I would prefer a free solution at the momemt)? I have 256 MB of RAM.
Using the compression option in gfx2gba produces smaller tile files, and thus a smaller big array file that is compilable by gcc, but then I can't use DMA to simply load from the ROM into VRAM. |
If you have chosen to use this method, then scrolling really is quite trivial.
You basically need to reserve a screen sized chunk of tiles and as the screen scrolls, write to the relevant data to the tile strip coming onto the screen. It seems strange that you obtained a 27MB tile file, the data that my programme spit out was 15316992 bytes at 8 bits per pixel, so reducing this to 4 bits per pixel would reduce the storage by 50% (7MB?) and that was without duplicate tile checks.
#36655 - ymalik - Sun Feb 27, 2005 2:08 am
AnthC wrote: |
If you have chosen to use this method, then scrolling really is quite trivial.
You basically need to reserve a screen sized chunk of tiles and as the screen scrolls, write to the relevant data to the tile strip coming onto the screen. It seems strange that you obtained a 27MB tile file, the data that my programme spit out was 15316992 bytes at 8 bits per pixel, so reducing this to 4 bits per pixel would reduce the storage by 50% (7MB?) and that was without duplicate tile checks. |
Are you splitting up the image into 256x256 squares as well? And what program do you use to create the tile and map data? For me, each square has it's own separate tile data.
What you are proposing is what I thought about doing as well, but the problem that occured was that since each square had its own tile and map data, I would have to do some kind of replacement algorithm to make sure that I don't corrupt the existing tile and map data.
#36656 - AnthC - Sun Feb 27, 2005 2:14 am
ymalik wrote: |
AnthC wrote: | If you have chosen to use this method, then scrolling really is quite trivial.
You basically need to reserve a screen sized chunk of tiles and as the screen scrolls, write to the relevant data to the tile strip coming onto the screen. It seems strange that you obtained a 27MB tile file, the data that my programme spit out was 15316992 bytes at 8 bits per pixel, so reducing this to 4 bits per pixel would reduce the storage by 50% (7MB?) and that was without duplicate tile checks. |
Are you splitting up the image into 256x256 squares as well? And what program do you use to create the tile and map data? For me, each square has it's own separate tile data.
What you are proposing is what I thought about doing as well, but the problem that occured was that since each square had its own tile and map data, I would have to do some kind of replacement algorithm to make sure that I don't corrupt the existing tile and map data. |
I didn't split the image into 256x256 squares. I just processed the bitmap as an area into squares which were 2^n x 2^n pixels. When a square was blank I didn't include this in the output as it would be pointless storing a blank array, this is where the efficiency of the tree cuts in. I wrote a small c app (about 50 lines of code) which formed the quad tree and spit the raw tiles out.
I noticed you replied recently, I am in on IRC Effnet #gbadev if you want to talk.
#36658 - ymalik - Sun Feb 27, 2005 3:16 am
How long will you be online? I would prefer not to talk right now because we have dialup, and don't want to block incoming calls. I would prefer to talk around 11:30 P.M. (it is 9:15 P.M. where I live right now).
#36800 - ymalik - Tue Mar 01, 2005 11:43 pm
Our architect has figured out how we should do the scrolling. Of course, it is the slave programmers who have to implement it.
If you play your store-bought Minish Cap ROM on an emulator, you'll notice that there are many layers. I'm betting they made multiple layers just to save memory, because they can only have 16K of tiles for a layer. For example, in the Minish forest, the layer with the road and buildings, you'll see some black areas. Those black areas are leaves, but they are in another layer. They are putting them together to make one image.
Now, my maps are 256x256. They have to be that way because we are also going to have searching of street names, and a meta-file with the street names will be stored by a 256x256 map. At most, there will be 4 different maps displayed on a screen. Well, each portion of a map can be a seperate layer. The GBA conveniently has 4 layers. The biggest problem with using one layer is that you have to figure out a way to proper store the differnt tiles into VRAM, since each map has it's own set of tiles and map. Each background will have it's own set of tiles for each 256x256 square.
#38056 - ymalik - Mon Mar 21, 2005 5:16 am
Hello,
I can't decide whether my technique is going to work. Here's what I'm going to do. I'm using 256x256 4 BPP maps. Each map has it's own palette. t's hard to explain.
- Tiles of map i will be stored in char base block 0.
- The map that creates an image of 256x176 pixels will stored in the last screen block of char base block 0. The rest of the map that is not shown (the bottom 256x80 pixels of map 1) will consist of tiles of color index 0 of map i's palette. Note that color index 0 is not always black, and will most of the time be a color like beige, which is what majority of the maps are made of as well. See my first post for an image of the big map I'm talking about.
- The map will be displayed in bg0.
- Scrolling to the right for the first 16 pixels will simply increment bg0 horizontal offset register.
- After going 16 pixels, bg0 h-offset will be set to 0 and a new map that is 240x176 pixels with 16 pixels offset from map i will be stored at (0, 0) of bg0. The rest of the tiles will be of color index 0.
- At the same time, the tiles of map i + 1 will be stored in char base block 1, and the map that creates the first 16x176 pixels of map i + 1 will be stored at pixel (240, 0) of bg1. The rest of the map (which is the first 240x176 pixels of bg1) will consist of tiles of the color index 0 of map i + 1's palette. bg1 will be given a higher priority than bg0.
- Scrolling will again be done by incrementing both bg0 and bg1's h-offset registers until 16 pixels pass, and then 16 pixels of map i will be chopped off, and 16 pixels of map i + 1 will be added.
Now here comes my question. The 16x176 pixels of bg1 consist of mainly beige tiles, which could be color index 0 of the palette of map i + 1. Just underneath it is bg0, which, in the 16x176 pixels stored at (240, 0), will consist of tiles of color index 0 of map i's palette. Will the 16x176 pixels of map i + 1 be shown over the corresponding transparent section of map i, and the will the transparent section of map i + 1 (the first 240x176 section) allow the 240x176 pixels of map i (which are not transparent but may consist mainly of the transparent color tiles) to show through?
Boy, that's a mouthful.
Thanks,
Yasir
#38074 - poslundc - Mon Mar 21, 2005 5:05 pm
ymalik wrote: |
If you play your store-bought Minish Cap ROM on an emulator, you'll notice that there are many layers. I'm betting they made multiple layers just to save memory, because they can only have 16K of tiles for a layer. For example, in the Minish forest, the layer with the road and buildings, you'll see some black areas. Those black areas are leaves, but they are in another layer. They are putting them together to make one image. |
There are several reasons to do this, but memory is rarely one of them.
More practical reasons include having multiple priority layers (eg. one background behind the player, and one background obscuring the player), creating complex environment combinations (eg. a bg of chairs on different types of floor tiling), and parallax-scrolling of BGs at different speeds in order to give a more interesting movement effect.
Quote: |
- After going 16 pixels, bg0 h-offset will be set to 0 and a new map that is 240x176 pixels with 16 pixels offset from map i will be stored at (0, 0) of bg0. The rest of the tiles will be of color index 0. |
Why not leave bg0 where it is, and simply load in a new vertical strip of tile indices? The beauty of the GBA hardware is that it will continue to wrap around as you continue to change the offset.
Quote: |
Now here comes my question. The 16x176 pixels of bg1 consist of mainly beige tiles, which could be color index 0 of the palette of map i + 1. Just underneath it is bg0, which, in the 16x176 pixels stored at (240, 0), will consist of tiles of color index 0 of map i's palette. Will the 16x176 pixels of map i + 1 be shown over the corresponding transparent section of map i, and the will the transparent section of map i + 1 (the first 240x176 section) allow the 240x176 pixels of map i (which are not transparent but may consist mainly of the transparent color tiles) to show through? |
In a 256-colour bg, colour 0 is always transparent, no matter how your layers are organized, and will show through to underlying layers (or the backdrop if none are present). In a 16-colour bg, colour 0 of each of the 16 palettes is transparent, no matter how your layers are organized, and will show through to underlying layers (or the backdrop if none are present).
The colour of the backdrop is the colour stored at bg-palette index 0. So in the case where you are using a 256-colour map and your transparent colour is beige, then beige will show through on the backdrop if there is nothing to obscure it. But if you are using a 16-colour bg, the two colours will only correspond if the tile in question is using palette 0.
Dan.
#38077 - ymalik - Mon Mar 21, 2005 6:53 pm
poslundc wrote: |
Why not leave bg0 where it is, and simply load in a new vertical strip of
tile indices? The beauty of the GBA hardware is that it will continue to
wrap around as you continue to change the offset.
|
That's easier said than done. Here's the problem I'm have with using one
background. Each 256x256 map has it's own set of optimized tiles and map.
If I move too far within a map, say i, I've to load the next map's, say i +
1, vertical map strip and the corresponding tiles. But then where would I
store them? I just can't take out map i's vertical tiles at the opposite end because
those tiles may be repeated somewhere else in map i. I'll have rearrange
the incoming map i + 1's map based on where the vertical tiles are stored.
Things get hairy when I have four maps on the screen at the same time. If
you can tell me a way a way to do this, I would rather do this method.
poslundc wrote: |
The colour of the backdrop is the colour stored at bg-palette index 0. So
in the case where you are using a 256-colour map and your transparent
colour is beige, then beige will show through on the backdrop if there is
nothing to obscure it. But if you are using a 16-colour bg, the two colours
will only correspond if the tile in question is using palette 0.
|
I feel like a mime. Suppose I have the following in bg0. The inner
rectangle represents the GBA screen.
Code: |
+=====================+
| | |
| v f (A) | |
| r | |
| s c v | |
| c | |
|_________________| |
| |
| |
| (B) |
| |
| |
+=====================+
|
The lowercase letters represent lines, bitmap text, etc, of different
colors. Region (A) and (B) could of be of the same palette color 0,
the transparent color. Region (B) is the transparent color.
And here's bg1:
Code: |
+=====================+
| | q |
| |(C)|
| | |
| | r |
| |x |
| |___|
| |
| |
| (D) |
| |
| |
+=====================+
|
Where again, region (C) and (D) could be of the same palette color 0. The
palette is different than the bg0's palette.
Region (D) is the transparent color.
Would I get the following when both backgrounds are combined:
Code: |
+=======================+
| | |q |
| | v f (A) | |
| | r |(C)|
| |s c v |r |
| c| x| |
| |________________| |
| |
| |
| |
| |
| |
+=======================+
|
assuming that the both the h-offset registers in bg0 and bg1 have been shifted by the same amount. bg1 has higher priority than bg0. The color of region (A) is shown and so is the color of region (C).
#38078 - poslundc - Mon Mar 21, 2005 7:37 pm
ymalik wrote: |
That's easier said than done. Here's the problem I'm have with using one background. Each 256x256 map has it's own set of optimized tiles and map. If I move too far within a map, say i, I've to load the next map's, say i + 1, vertical map strip and the corresponding tiles. But then where would I store them? I just can't take out map i's vertical tiles at the opposite end because those tiles may be repeated somewhere else in map i. I'll have rearrange the incoming map i + 1's map based on where the vertical tiles are stored. Things get hairy when I have four maps on the screen at the same time. If you can tell me a way a way to do this, I would rather do this method. |
In 16-colour mode you have access to 1024 tiles in a single background. If you expect to really need to use more than that amount on a single level/playfield/whatever (ie. before you can transition to another map, such as by fading down then up again), then yes, you must dynamically load tiles in.
The vast majority of games, however, do not come close to approaching this limit. In this case the simple stripping method is far preferable to streaming tile-data in during VBlank. Ask yourself if you really need to access more than that many chars per level before proceeding... 1024 is an easy enough limitation for most map-based games to live with.
If you want to stream tiles in, then yes, you've got your work cut out for you. There's actually another thread going on at the moment that's discussing how to set up a LRU cache for this kind of thing. Personally, I don't go for such systems if I can avoid them, as the limitations of the system become ambiguous, which is never a good thing for the people designing levels, etc.
As best as I can tell, your other question is just asking whether or not scrolling and transparency work. They do. :|
Dan.
#38080 - ymalik - Mon Mar 21, 2005 8:59 pm
poslundc wrote: |
The vast majority of games, however, do not come close to approaching this limit. In this case the simple stripping method is far preferable to streaming tile-data in during VBlank. Ask yourself if you really need to access more than that many chars per level before proceeding... 1024 is an easy enough limitation for most map-based games to live with.
If you want to stream tiles in, then yes, you've got your work cut out for you. There's actually another thread going on at the moment that's discussing how to set up a LRU cache for this kind of thing. Personally, I don't go for such systems if I can avoid them, as the limitations of the system become ambiguous, which is never a good thing for the people designing levels, etc.
|
I'm not making anything like a game. I just want scroll around in this image uninterrupted: http://www.cs.stevens.edu/~ymalik/Tgr34031lkA.png That's why I've broken up the image into 256x256 images. The optimized tiles of each image are stored in a char base block and the map is stored at the screen block at the end of the corresponding char base block. However, only the map indices that are needed are stored in the screen block; the rest of the indices are tiles of the transparent color. This way, I can have all backgrounds enabled at once to have smooth scrolling in between successive maps. The visible tiles of one map are going to be over the transparent tiles of another map.
poslundc wrote: |
As best as I can tell, your other question is just asking whether or not scrolling and transparency work. They do. :|
|
Forget about scrolling for the moment. Would the third ASCII image I have result when both bg0 and bg1 are enabled?
Thanks,
Yasir
#38095 - Steve++ - Mon Mar 21, 2005 10:25 pm
Hi Yasir.
I'm just itching to properly reply to this thread. I'm just waiting for GraphicsGale to finish downloading. I'm trying to find out how many unique 8x8 tiles this map contains. I tried gfx2gba, but it crashed. The file was probably too big and it probably has a really lazy (brute force) method of tile optimisation which would fall over with such large files.
I'll edit this post (or reply if someone else replies after this) when I have gathered the right information (soon). I'm the guy that write the LRU caching code in the other thread that Dan (poslundc) mentioned. I think you may find it useful. More on this soon.
- Steve
#38096 - ymalik - Mon Mar 21, 2005 10:31 pm
Wow, thanks for your enthusiam! You can't use gfx2gba on my image--it's about 10,000x10,000 pixels. I broke up the image into 256x256 images and then ran gfx2gba on each image.
#38103 - poslundc - Mon Mar 21, 2005 11:43 pm
ymalik wrote: |
I'm not making anything like a game. I just want scroll around in this image uninterrupted: http://www.cs.stevens.edu/~ymalik/Tgr34031lkA.png That's why I've broken up the image into 256x256 images. The optimized tiles of each image are stored in a char base block and the map is stored at the screen block at the end of the corresponding char base block. However, only the map indices that are needed are stored in the screen block; the rest of the indices are tiles of the transparent color. This way, I can have all backgrounds enabled at once to have smooth scrolling in between successive maps. The visible tiles of one map are going to be over the transparent tiles of another map. |
If you just want to scroll around a large image and don't care about gameplay factors, you should make a map that has has each tile point to a unique char in VRAM. Then stream in a row or column of tiles into VRAM as necessary, as you scroll around. You should still be able to leave both your map and your tiles intact for everything that doesn't change.
Your 10K x 10K pixel image would work out to something like 48 MB of data, so you will clearly have to either find redundant and H/V-flipped tiles, or use some type of compression. There are a variety of options for going about this, though.
Quote: |
Forget about scrolling for the moment. Would the third ASCII image I have result when both bg0 and bg1 are enabled? |
If I'm understanding the example correctly, then yes.
Dan.
#38107 - ymalik - Tue Mar 22, 2005 12:32 am
poslundc wrote: |
If you just want to scroll around a large image and don't care about gameplay factors, you should make a map that has has each tile point to a unique char in VRAM. Then stream in a row or column of tiles into VRAM as necessary, as you scroll around. You should still be able to leave both your map and your tiles intact for everything that doesn't change.
Your 10K x 10K pixel image would work out to something like 48 MB of data, so you will clearly have to either find redundant and H/V-flipped tiles, or use some type of compression. There are a variety of options for going about this, though.
|
I've thought of doing that, and that's how Mikhail does it in the GBA GPS mapping receiver, but we plan to have multiple maps, say of every county in New Jersey. The image I posted is of Passaic county, and that is a small county. We could only fit 1 or 2 counties using unoptimized tiles.
#38108 - Steve++ - Tue Mar 22, 2005 12:44 am
OK Yasir, I wrote a program using the Allegro library that analyses a bitmap and determines how many unique 8x8 tiles it contains (it doesn't generate any data yet). Please see if you can find something wrong with the logic. The result I got was 34,055 unique tiles. That's just over 2MB of memory. Very manageable I think.
Here's the code. See if you can find anything wrong with it (because that number sounds too good to be true).
Code: |
#include <allegro.h>
#include <list>
#include <cstdio>
class AllegroBitmap
{
BITMAP* bitmap;
public:
AllegroBitmap(BITMAP* bitmap) : bitmap(bitmap)
{
}
AllegroBitmap()
{
}
BITMAP* getBitmap()
{
return bitmap;
}
bool compare(AllegroBitmap* b)
{
BITMAP* bmp = b->getBitmap();
if ((bmp->w != bitmap->w) || (bmp->h != bitmap->h))
{
return false;
}
for (int i=0; i<bmp->h; ++i)
{
unsigned char* line1 = bitmap->line[i];
unsigned char* line2 = bmp->line[i];
for (int j=0; j<bmp->w; ++j)
{
if (line1[j] != line2[j])
{
return false;
}
}
}
return true;
}
int hashCode()
{
int hashcode = 0;
for (int i=0; i<bitmap->h; ++i)
{
unsigned char* line = bitmap->line[i];
for (int j=0; j<bitmap->w; ++j)
{
hashcode += line[j];
}
}
return hashcode;
}
};
using namespace std;
int main(int argc, char* argv[])
{
allegro_init();
set_color_depth(8);
PALETTE palette;
BITMAP* bitmap;
printf("Loading bitmap... ");
fflush(stdout);
bitmap = load_bitmap(argv[1], palette);
if (!bitmap)
{
printf("Failed.\n");
return 1;
}
printf("Done.\n");
// Generate tiles - they share memory with the main bitmap
printf("Generating tiles... ");
fflush(stdout);
list<AllegroBitmap> submaps;
for (int i=0; i<bitmap->w; i+=8)
{
for (int j=0; j<bitmap->h; j+=8)
{
submaps.push_back(AllegroBitmap(create_sub_bitmap(bitmap, i, j, 8, 8)));
}
}
printf("Done.\n");
// Create a list of hashcodes
printf("Hashing tiles... ");
fflush(stdout);
list<AllegroBitmap*> hash[16384];
for (list<AllegroBitmap>::iterator iter = submaps.begin(); iter != submaps.end(); iter++)
{
hash[(*iter).hashCode()].push_back(&(*iter));
}
printf("Done.\n");
// And now the fun part - eliminating duplicates
printf("Eliminating duplicates... ");
fflush(stdout);
for (int i=0; i<16384; ++i) // For each hashcode
{
printf("%d ", i);
fflush(stdout);
list<AllegroBitmap*> uniqueList;
for (list<AllegroBitmap*>::iterator iter = hash[i].begin(); iter != hash[i].end(); iter++) // For each element in the original list
{
// If it's not in the unique list, add it to the unique list
AllegroBitmap* a = *iter;
bool found = false;
for (list<AllegroBitmap*>::iterator jter = uniqueList.begin(); jter != uniqueList.end(); jter++) // For every element in the unique list
{
AllegroBitmap* b = *jter;
if (a->compare(b))
{
found = true;
break;
}
}
if (!found)
{
uniqueList.push_back(*iter);
}
}
hash[i] = uniqueList;
}
printf("Done.\n");
// Calculate number of unique tiles
int tilecount = 0;
for (int i=0; i<16384; ++i)
{
tilecount += hash[i].size();
}
printf("Number of unique tiles = %d.\n", tilecount);
return 0;
}
END_OF_MAIN();
|
Anyway, I'm really busy at the moment, so I haven't got time to write all the other stuff I really want to write - I'm moving house today. I can reply tomorrow. We're basically working on the same problem, so I'm quite keen to help.
Did you check out my caching thread? http://forum.gbadev.org/viewtopic.php?t=5238
Edit: Once I've completed my dynamic tile engine, I'll contribute it here so people don't keep asking the same question. Someone (I forget who) said that someone should contribute their code instead of everyone hiding it so people can just get on with making games instead of everyone reinventing that same stuff over and over.
Edit: Just changed the code to use printf and fflush. Gets around default line buffering behaviour of stdout.
Last edited by Steve++ on Tue Mar 22, 2005 2:26 am; edited 1 time in total
#38114 - Steve++ - Tue Mar 22, 2005 2:12 am
Ah what the hey, you only live once. Here's what can't wait until tomorrow...
This thread has gone way out of control and has become way too complicated. There are actually two problems:
1. You have a big tilemap (1248x1216 tiles) and you need to map it into the hardware tilemap (32x32 tiles).
2. You have more unique tiles (34,055) than can be stored in VRAM (992).
The solution to problem 1:
For each frame, load the appropriate tile indices from the ROM tilemap to the VRAM tilemap. Easy. I've implemented this before. You can find it here. It's old and probably dodgy, but it works.
The solution to problem 2:
Instead of loading the tile indices from ROM verbatim, implement a dynamic tile loading system. The interface to such a system will have a lookup function/method where you pass a ROM tilemap index and it gives you a VRAM tilemap index. It also tells you if you need to load a tile from ROM, and if so, from where to where. I have implemented this here. The only thing that hasn't been done is the actual tile loading code. I've only coded the generic stuff so far.
You don't need anything more complicated than that.
Now that I've coded both solutions, if only I could find the time to combine them...
#38129 - ymalik - Tue Mar 22, 2005 5:47 pm
You're code that figures out the number of unique tiles looks correct. Clever use of a hash table. 2 MB of unique tiles looks correct because I also generated about 2 MB worth of unique tiles. However, the map was broken up into smaller 256x256 images, and the unique tiles were by each sub image.
I have an algorithm in mind that implements scrolling, but it uses all four backgrounds and char base blocks. I'm going to implement that first that is pretty straight forward, and I know how to do it. If I have time, I will implement the dynamic loading method, which is preferable because you use only one background.
#38141 - Steve++ - Tue Mar 22, 2005 11:11 pm
Quote: |
I have an algorithm in mind that implements scrolling, but it uses all four backgrounds and char base blocks. I'm going to implement that first that is pretty straight forward, and I know how to do it. |
That's what I don't understand - why use more than one background? The number of unique tiles that you can reference doesn't increase when you have more backgrounds. In fact, it decreases by 32 for each 32x32 tile background, which is 96 in your case (or more if you have larger hardware backgrounds). The only benefit on multiple backgrounds is being able to display some stuff in front of other stuff. That would only be useful in your case if you seperated the roads from place names.
Well, good luck. As soon as I get some time, I'll modify that Allegro program so it generates the tiles and tilemap. Then I'll merge my code together to get (hopefully) a fully dynamic tilemap scrolling engine. AND, I'll release that code.
#38149 - Mucca - Wed Mar 23, 2005 12:43 am
Just use one background, write your own tileset and map exporter, and use 32 bits for map entries (you could use less but alignment would be a pain), which are run through the dynamic tile engine to get the 10-bit vram tile index, then OR in your six flag bits. The map will be big, but theres a lot of blank space which could be compressed. You could split the single large map into chunks of 256x256 (all chunks reference the same tileset), compress the chunks to cart, and decompress whatever four currently required to EWRAM at runtime.
#38194 - Steve++ - Wed Mar 23, 2005 10:24 pm
Quote: |
use 32 bits for map entries (you could use less but alignment would be a pain) |
Why would alignment be a pain if you have an array of u16s? There are 34,055 tiles, which can be indexed in 16 bits. Just represent the tilemap as an array of u16s and let the compiler worry about alignment issues. Sure, there will be a slight performance hit, but all that matters is that every frame can be rendered on time. I think Yasir would rather save cartridge space.
As far as compression goes, you could RLE encode each row. Have the tilemap generator do this. It will also need to generate a table that stores the address of the start of each row. It shouldn't take too long to decompress a row with RLE. I think this would save a lot of space because there are a lot of large runs in this map.
Here's a question though: if I define an array of u16, s16, u8 or s8, is each element 32-bit aligned by default, or does the compiler only pad structs and not arrays?
#38195 - tepples - Wed Mar 23, 2005 10:40 pm
Steve++ wrote: |
Quote: | use 32 bits for map entries (you could use less but alignment would be a pain) |
Why would alignment be a pain if you have an array of u16s? There are 34,055 tiles, which can be indexed in 16 bits. |
For this county. There are larger counties.
Quote: |
Here's a question though: if I define an array of u16, s16, u8 or s8, is each element 32-bit aligned by default, or does the compiler only pad structs and not arrays? |
Using the __attribute__((aligned (4))) directive (see the GCC manual), you can force any object 32-bit aligned.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#38198 - Steve++ - Wed Mar 23, 2005 11:04 pm
tepples wrote: |
Steve++ wrote: | Quote: | use 32 bits for map entries (you could use less but alignment would be a pain) |
Why would alignment be a pain if you have an array of u16s? There are 34,055 tiles, which can be indexed in 16 bits. |
For this county. There are larger counties. |
Excellent point. My page replacement code assumes only one index type. I'll have to modify it to support two index types. It shouldn't be too difficult at all.
Thanks for pointing that out.
#38209 - ymalik - Thu Mar 24, 2005 12:38 am
tepples wrote: |
Steve++ wrote: | Here's a question though: if I define an array of u16, s16, u8 or s8, is each element 32-bit aligned by default, or does the compiler only pad structs and not arrays? |
Using the __attribute__((aligned (4))) directive (see the GCC manual), you can force any object 32-bit aligned. |
What do you mean by 32-bit alignment?
#38211 - tepples - Thu Mar 24, 2005 12:55 am
The ARM7 processor can read a 32-bit (4-byte) number only from addresses that are a multiple of 4 bytes. For instance, it can read a 32-bit number from 0x08005238, but reading from 0x08005237 or 0x0800523A won't do nearly what a fellow coming from x86 would expect.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#38263 - Mucca - Thu Mar 24, 2005 9:38 pm
Steve++ wrote: |
Why would alignment be a pain if you have an array of u16s? There are 34,055 tiles, which can be indexed in 16 bits. |
Well, you'll need two bits for flipping tiles, and four for palette offset. The palette bits could be salvaged if either its a 256-color tileset (obviously not desirable in this instance), or if the whole tileset only uses 16 colors (which is probably the case here, havent studied the image, it made my browser crash :p). The mirror bits are likely very important though, which leaves 14 bits or 16384 tile indices, ie not enough.
Also, I wouldnt go for row by row compression. Each row is a bit over 2K at 16 bits per entry and 9000 pixels wide. Splitting the map into blocks of 256x256 would also produce chunks of 2K after decompression, but you would need to decompress them on average much less frequently, and would probably achieve greater compression on them, plus you only need four in EWRAM at any one time (with screen size 0) with a footprint of 8K as opposed to a minimum 21 rows with a footprint of ~47K.
Or, in short, vertical scrolling is just as likely as horizontal scrolling.
#38281 - ymalik - Fri Mar 25, 2005 5:57 am
Well, I'm implementing my solution, and I'll have it working by tomorrow, but it's not very good. I'm not using backgrounds as they are meant to be used: I'm using backgrounds to compose an image. If there are four maps on the screen, I'll have four tile sets stored in four char blocks, and the tile map will be dynamically generated according to the background register offsets and will be stored in screen base block (char_base_block<<3) + 7. In order to compose the image, some of the tiles will be transparent. You could think of each dynamically generated map to look like a gnomon, with the transparent tiles being the 'L' and the rectangle being the part of the map being shown. It will work for some counties in NJ, but it probably won't work for Manhattan, which is very crowded, and may have more tiles that can fit into a char base block. And when you have four maps on the screen, things slow down quite a bit.
I'm keen on implementing what you guys have suggested. However, I'm just not sure how LRU, which is used to replace pages in OS paging system, can be used in this instance.
Mucca wrote: |
Just use one background, write your own tileset and map exporter, and use 32 bits for map entries (you could use less but alignment would be a pain), which are run through the dynamic tile engine to get the 10-bit vram tile index, then OR in your six flag bits. The map will be big, but theres a lot of blank space which could be compressed. You could split the single large map into chunks of 256x256 (all chunks reference the same tileset), compress the chunks to cart, and decompress whatever four currently required to EWRAM at runtime. |
This seems reasonable. Just how fast are the BIOS decompression routines? And how good is the compression rate? As you know, I am storing 256x256 chunks of the map, but they are opmtimized tiles, and I'm only storing the chunks that actually have any data. The ROM with only Passaic County was about 3 MB. This way I could fit all of New Jersey.
#38288 - Mucca - Fri Mar 25, 2005 1:15 pm
Oops, realised too late what Steve++ meant when he suggested RLEing the rows: the required indices could be found by scanning the compressed rows instead of decompressing the entire row. Interesting, could require an awful lot of ROM access though. Hard to tell without seeing it in action, as its very dependant on the nature of the images.
The system decompression routines are fine for starting with, compression wont be fantastic, but incorporating it all will cost you no time.
#38295 - ymalik - Fri Mar 25, 2005 3:13 pm
Mucca wrote: |
The system decompression routines are fine for starting with, compression wont be fantastic, but incorporating it all will cost you no time. |
I've heard that the BIOS uncompression routines are not fast. Is that true?
#38310 - Miked0801 - Fri Mar 25, 2005 10:07 pm
We use them for some stuff - but get better compression with our own routines. Size is more important than speed most of the time.
#38313 - ymalik - Fri Mar 25, 2005 10:22 pm
I compressed an unoptimized tile set with gfx2gba, and I was able to produce a file that was smaller than an optimized tile set, so I am not worried about size. I'm assuming by your response that BIOS decompression is very fast.
#38349 - ymalik - Sat Mar 26, 2005 3:36 pm
Mucca wrote: |
Oops, realised too late what Steve++ meant when he suggested RLEing the rows: the required indices could be found by scanning the compressed rows instead of decompressing the entire row. Interesting, could require an awful lot of ROM access though. Hard to tell without seeing it in action, as its very dependant on the nature of the images. |
I didn't pay much attention to this, but what is "RLEing?" I saw the term RLE in the CowBite documentation for RLUnCompWRAM.
Also, according to the CowBite specification, "LZ77 decompressors actually decompress LZSS, not LZ77, which is slightly different." But I'm using gfx2gba to compress the data, which uses LZ77. Will the uncompressed data be different than using a LZ77 decompressor written by myself?
#38357 - tepples - Sat Mar 26, 2005 4:32 pm
RLE is run-length encoding. In theory, this is equivalent to LZSS with a window size of 1.
LZ77 is a family of algorithms; LZSS is a member of this family.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#38370 - ymalik - Sat Mar 26, 2005 7:34 pm
Using what everyone has suggested, here's what I've come up. Please comment.
-Create unoptimized tiles for each 256x256 map. This will generate 1024 tiles, therefore, there is a 1-1 (and onto!) mapping between a tile map and the tile set.
-Compress the tile set. This is necessary because unoptimized tilescreate a file that is about 28 MB. By compressing, we get a tile set file that is smaller than an optimized tile set. I'm betting that Passaic county will be about 1 MB, which is fantastic.
-We don't need to store the tile maps.
-Load the tile map with consecutive tiles (viz 0 to 1023). The tile map will not change throughout the scrolling process.
-The tiles that are stored in VRAM are buffered in all of IWRAM.
-Based on the scrolling position, uncompress a tile set into EWRAM.
-At most 4x32,768 bytes of memory will be used.
-The buffered tileset in IWRAM will be changed based on the position, e.g., after moving 16 pixels to the left, a vertical tile strip 16 pixels in width is loaded from the uncompressed tileset into the buffered tile set and the first 16 pixels of tile set are taken out. Same thing for moving vertically, except now it's 96 pixels.
- This requires changing the entire tileset. To avoid the changing the entire tileset, I'm betting I can change just part of the tile set and to some tricks with the vertical offset registers. I'm not sure on this, though.
- During vblank, the bufferred tile set is blasted into VRAM.
- With this, I can have at most 2 char base blocks left over and 3 backgrounds (I'm dealing with a 4 BPP image).[/list]
#38383 - tepples - Sat Mar 26, 2005 11:22 pm
Quote: |
The buffered tileset in IWRAM will be changed based on the position, e.g., after moving 16 pixels to the left, a vertical tile strip 16 pixels in width is loaded from the uncompressed tileset into the buffered tile set and the first 16 pixels of tile set are taken out. Same thing for moving vertically, except now it's 96 pixels. |
Best to use 16 pixels in both directions, as 1. it's a factor of 256, and 2. it evens out CPU time as opposed to creating huge CPU spikes that could conceivably cause a brief pause.
Quote: |
This requires changing the entire tileset. To avoid the changing the entire tileset, I'm betting I can change just part of the tile set and to some tricks with the vertical offset registers. I'm not sure on this, though. |
If you only replace the horizontal or vertical strip of tiles that you're going to scroll onto, then you don't need to do anything to the entire tileset at once. You could just have one map using VRAM 0x06000000-0x06007FFF for tiles and VRAM 0x0600F800-0x0600FFFF for the map, which is kept constant at identity.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#38408 - ymalik - Sun Mar 27, 2005 4:36 am
tepples wrote: |
If you only replace the horizontal or vertical strip of tiles that you're going to scroll onto, then you don't need to do anything to the entire tileset at once. You could just have one map using VRAM 0x06000000-0x06007FFF for tiles and VRAM 0x0600F800-0x0600FFFF for the map, which is kept constant at identity. |
Yes, that was what I was going to do. I'll let the offset registers increment without bounds. Then the image will wrap around, but I'll put the incoming tile set strip in the location where the wrapping around will occur.