Sorry for the bump, but I'm not making a new topic.
I've examined the code and I *think* I have a good idea as to how to do this. Just so I won't leave people in the dark, and also so that people who know more than I do would be able to tell me if this scheme has a major problem in it, I'll post the full theory here, coded for convinience:
NEW SONIC 2 LEVEL FORMAT
From my understanding, all pertinent data for levels as arranged in RAM is as so:
$0000-$8000 - 128x128 tile definitions $100 of them
$8000-$9000 - Main level layout where for each row of $100 bytes, the first $80 refers to the FG and the last $80 refers to the BG
$9000-$A800 - 16x16 tile definitions, $300 of them (although it seems the format would allow for up to $400, the data from $A800 to $B000 is apparantly used. Furthermore, the only block set in the game with more than $300 16x16 tiles is ARZ by a slight margin, and even then the tiles that do spill over $A800 are null and unused. Perhaps Sonic Team wanted $400 tiles for RAM, but found out they couldn't do so and thus had to cut down some extra tiles from ARZ? Who knows, but I digress.
Anyway, as can be seen, the big RAM hog in this scheme is the 128x128 tile definitions. So the biggest priority was trying to cut that down somehow in the move to 64x64 tiles. However, there were two more major problems: 1, the extra space that would be required to address 64x64 tiles as opposed to 128x128 ones for the same sized level, and the fact that I wanted my levels to be much bigger than the maximum $4000x$800 pixel cap in Sonic 2. Thus, I came up with the following solution:
$0000-$2000 - Primary 64x64 tile definitions ($100 of them)
$2000-$4000 - Secondary 64x64 tile definitions ($100 of them, see *A* for details)
$4000-$5000 - Level layout data square section 1 ($40x$40)
$5000-$6000 - Level layout data square section 2 ($40x$40) <--- See *B* for details of both
$6000-$6200 - Level layout section 1 Primary/Secondary tile switches
$6200-$6400 - Level layout section 2 Primary/Secondary tile switches <--- See *C* for details of both
$6400-$7400 - Exclusive 64x64 BG tile definitions ($80 of them)
$7400-$7800 - 64x64->128x128 BG tile redefinitions <--- See *D* for both
$7800-$9800 - 16x16 tile definitions, extended to $400 tiles
$9800-$A800 - Extra RAM
Now for explanations:
*A* - This scheme is used to not only lower the amount of RAM usage by the 64x64 tiles, but also the RAM usage of the level layout itself (more on that later). The primary 64x64 tile definitions are ones that are ALWAYS loaded, no matter what. They will be, obviously, used for the most common level elements. The secondary 64x64 tile definitions, however, are swapped in and out of each other in real-time. How? I haven't decided yet. it'll most likely be tags within the level itself similar to the path switcher that will move the data into RAM when crossed, probably via DMA in the VBlank routine (not all at once, but sections at a time). Regardless of how it'll be done, the big limitation will be that levels will have to be designed with this scheme in mind.
*B* - Now for the interesting part. Instead of loading the entire level into RAM, instead the level will be loaded in sections, using a sort of page fliiping scheme to keep things moving in real-time. Each page of a level is $40x$40 tiles big, which amounts to $1000x$1000 pixels of level per page. Every attempt will be made to keep ALL the level pages compressed. So how will this work?
1 2 1 2 1 2 1 2 etc
____________________________________________________________________
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
| | | ! ! | | | | | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A B C D E F G H
Each section of this chart represents a section of the level (yes, I know they aren't square, this is for demonstration purposes only). Each level page is connected to each other horizontally to form an entire level. The big advantage of this is that I can make each level as big or as small as I please (up to $10000x$1000 pixels of course so I don't break the engine) in ROM. The numbers on top indicate which section of RAM each portion of the game refers to when determining tile data. It's a simple 1-2 pattern, and actually allows me to do tile position calculations a bit more easily (in theory). The letters on the bottom are just arbitrary section numbering for easy reference.
As for swapping, take a look at the lines designated by l and r. Assume sections B and C are currently loaded. In Section C, Sonic passes through the line marked by 'r'. Once that occurs,the engine will see if section D is already loaded. Since it is not, the engine will now fill the space currently occupied by section B (in other words, the section 2 RAM data) with Section D's data. How? It'll begin a sort of dynamic decompression. Instead of decompressing all $1000 bytes of data at once, it will instead decompress a small amount of data each frame, pausing the decompression each time until it's done. This means that there has to be a suitable amount of space between where Section C ends and where the point Sonic crosses to begin the decompression is. These values haven't been exactly determined yet. Now section D is loaded, but you need to go back. Once Sonic crosses the line marked by 'l' in section C, the game will reload section B into section D's space. Repeat ad infinium.
*C* - These do have to be noted though.These are the primary/secondary tile bit switches. The normal level layout sections described above use a single byte to reference a tile. But as you've noticed, there are indeed $200 64x64 tiles loaded in RAM at a time. So we need these sections of memory. Basically, both of these refer to their companion level layouts in RAM. Each bit represents whether to use the primary or seconday tiles in RAM. Each byte will take care of 8 bytes in the normal layout, conserving space. They will most likely stay decompressed in ROM since they're so small and so that they can be swapped in and out in tandem with the main level layout sections without skipping a beat.
*D* - Ah, the BGs. The layouts used for BGs will not be nearly as varied as the normal layouts. So the BG for each level is going to use makeshift 128x128 tiles. Also, each BG will be stored and accessed in ROM uncompressed (though they will most likely be segmented into pages like the normal layouts, for convinience sake). how will it work? The first area in RAM designated here is simply an array of BG exclusive 64x64 tiles. As far as referencing goes, these tiles will 'replace' the first $80 tiles in the primary 64x64 tile definitions. The last $80 are as-is. The redefinitions RAM area is how the BG is going to be able to use 128x128 tiles. Each byte in a 4-byte section will reference a 64x64 tile. If less than $80, it'll refer to the 'exclusive tiles' as mentioned earlier. If $80 or higher, it'll refer to the last $80 tiles in the primary definitions. The BG layout, therefore, refers to each of these 4-byte sections ($100 of them, so one byte per section in the BG), which are then used to determine the 64x64 tiles used to draw the BG. It's hard to explain, so if you don't understand something, ask for clarification. Also, it is probably possible to store the 4-byte sections in ROM uncompressed, but I'll see about that.
Also, as you'll note, the 16x16 tile definitions have been augmented to $400 instead of $300 to give more breathing room. Also, there is at least $1000 bytes of unused RAM that I have to decide how to use. Possibilities include an array of addresses to custom dynamic level layout changes stored in ROM. as well as a decompress buffer in-game, so I can for example switch art mid-level. Any other suggestions would be appreciated.
Longer than I wanted, but it works. I probably made several mistakes, so fire at will. I'll begin implementing it once I get an editor running to actually make all the data this scheme uses.
This post has been edited by jman2050: 09 January 2006 - 02:00 PM