Buffering level/background data question

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Buffering level/background data question

Post by gravelstudios »

Hello. I'm new here. I'm sorry if this is a question that has been answered before. If so, please feel free to point me to the correct thread.

I've already programmed a game that has a non-scrolling background, similar to a pac-man maze, which is the same for every level. I'd like to start work on a game that scrolls. I have a basic scrolling engine going that stores level data using RLE compression, decompresses that data on the fly, and sends it to the PPU so that as the screen scrolls left and right, it displays the correct new background tiles. I've pretty much figured out 'the seam' and swapping nametables.

In my first game, the level data is stored as data bytes in the rom. wall collision is handled by a routine that converts the sprites' coordinates into the relevant address in the table, and checks to see what type of tile it is, whether it's 'solid' or not. This method only works because the background data is not compressed. As far as I can tell, there is no really efficient way to perform this kind of check on compressed level data.

The NES doesn't really have enough RAM to decompress two entire screens' worth of tiles into a buffer for doing this kind of collision checking. I got it down to two pages with the use of 16*16 metatiles. My basic question is whether I'm using the right approach. Is there a better way to decompress level data, perform wall collision detection with sprites, and then load data into the nametables at the seam? Do I have to use two entire pages of RAM for this, or is there a way to do it with less? Thanks for any advice.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Buffering level/background data question

Post by tepples »

gravelstudios wrote:The NES doesn't really have enough RAM to decompress two entire screens' worth of tiles into a buffer for doing this kind of collision checking. I got it down to two pages with the use of 16*16 metatiles. My basic question is whether I'm using the right approach.
Your approach is workable. Super Mario Bros. decompresses its levels to two 16x13-metatile pages. It uses them as circular buffers for collision data, writing a column at a time as the player progresses through each level. There are other ways, such as multi-level metatiles that allow random access to any part of a level (as seen in Mega Man, Blaster Master, and 16-bit Sonic the Hedgehog), but these don't allow quite as much destruction of a level (such as Mario breaking bricks).
Do I have to use two entire pages of RAM for this
What other uses did you have planned for the RAM?

Here's how an NES platformer might arrange RAM:
  • $0000-$00FF: Commonly accessed global and actor variables
  • $0100-$01BF: VRAM transfer buffer
  • $01C0-$01FF: Call stack
  • $0200-$02FF: Sprite display list
  • $0300-$037F: Music engine state
  • $0380-$03FF: Less commonly accessed global variables
  • $0400-$05FF: Metatiles for two screens of the map
  • $0600-$07FF: Actor variables
Previous discussion about collision map memory use
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Buffering level/background data question

Post by tokumaru »

In most games, the smallest blocks used to compose the level map are not 8x8 pixels, but often 16x16 and sometimes even 32x32 pixels (e.g. lots of Capcom games). The 8x8 tiles are then just the smallest graphical entity used to draw levels, but the physical blocks that build the levels and objects interact with are larger. At those sizes, it becomes more practical to store decompressed sections of the levels in RAM.

Also, whether or not you can test for collisions directly against compressed maps in the ROM will depend of the actual compression format. Something compressed with RLE or LZ obviously can't be randomly accessed, but nested metatiles for example can. In the Mega Man games, for example, levels are composed of screen-sized blocks (256x256 pixels), each made of 32x32-pixel blocks. That kind of scheme would be easy to read right off the ROM, while still using only 64 bytes per unique screen, which is fairly compact.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Buffering level/background data question

Post by rainwarrior »

gravelstudios wrote:The NES doesn't really have enough RAM to decompress two entire screens' worth of tiles into a buffer for doing this kind of collision checking. I got it down to two pages with the use of 16*16 metatiles. My basic question is whether I'm using the right approach. Is there a better way to decompress level data, perform wall collision detection with sprites, and then load data into the nametables at the seam? Do I have to use two entire pages of RAM for this, or is there a way to do it with less? Thanks for any advice.
If the only information you need to store per-tile is "solid" and "not-solid", then you can pack 8 tiles per byte (each one in a separate bit). You'd only need 64 bytes to store 2 x 16 x 16 tiles this way.
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Buffering level/background data question

Post by gravelstudios »

Thank you all for your advice. I am storing level data as 16x16 pixel blocks, using the last two bits of each 'block number' for the palette that's supposed to go with that block. My scrolling engine works fine, but I just wanted to know if I was using the correct techniques to do all this. I guess there is no 'right' way as long as it works.

By the way, does anybody know how Metroid does this? I know that Metroid stores rooms and objects of various sizes, but how does it decompress level data and perform wall collision?
User avatar
OmegaMax
Posts: 80
Joined: Wed Sep 21, 2016 8:55 am
Location: Calgary.Alberta,Canada

Re: Buffering level/background data question

Post by OmegaMax »

AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Buffering level/background data question

Post by AWJ »

gravelstudios wrote:Thank you all for your advice. I am storing level data as 16x16 pixel blocks, using the last two bits of each 'block number' for the palette that's supposed to go with that block. My scrolling engine works fine, but I just wanted to know if I was using the correct techniques to do all this. I guess there is no 'right' way as long as it works.

By the way, does anybody know how Metroid does this? I know that Metroid stores rooms and objects of various sizes, but how does it decompress level data and perform wall collision?
Like several games that were ported from FDS to cartridge, Metroid has an extra 8KB of RAM on the cartridge.
User avatar
gravelstudios
Posts: 159
Joined: Mon Mar 13, 2017 5:21 pm
Contact:

Re: Buffering level/background data question

Post by gravelstudios »

AWJ wrote:Like several games that were ported from FDS to cartridge, Metroid has an extra 8KB of RAM on the cartridge.
Based on the source code, it looks as if Metroid uses 2 kilobytes of cartridge RAM to store 2 complete nametables' worth of 8x8 tiles. Thanks for helping me answer my own question.
Post Reply