It is currently Wed Oct 18, 2017 3:15 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Mon Mar 13, 2017 5:39 pm 
Offline
User avatar

Joined: Mon Mar 13, 2017 5:21 pm
Posts: 5
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.


Top
 Profile  
 
PostPosted: Mon Mar 13, 2017 5:55 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19096
Location: NE Indiana, USA (NTSC)
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).

Quote:
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


Top
 Profile  
 
PostPosted: Mon Mar 13, 2017 6:37 pm 
Online
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10053
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Mar 13, 2017 8:06 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5718
Location: Canada
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.


Top
 Profile  
 
PostPosted: Tue Mar 14, 2017 2:44 am 
Offline
User avatar

Joined: Mon Mar 13, 2017 5:21 pm
Posts: 5
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?


Top
 Profile  
 
PostPosted: Tue Mar 14, 2017 12:57 pm 
Offline
User avatar

Joined: Wed Sep 21, 2016 8:55 am
Posts: 54
Location: Calgary.Alberta,Canada
http://www.metroid-database.com/m1/sourcecode.php


Top
 Profile  
 
PostPosted: Tue Mar 14, 2017 4:02 pm 
Offline

Joined: Mon Nov 10, 2008 3:09 pm
Posts: 429
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.


Top
 Profile  
 
PostPosted: Tue Mar 14, 2017 4:27 pm 
Offline
User avatar

Joined: Mon Mar 13, 2017 5:21 pm
Posts: 5
OmegaMax wrote:
http://www.metroid-database.com/m1/sourcecode.php


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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: tokumaru and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group