It is currently Sun Oct 22, 2017 7:49 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Sun Jan 15, 2006 8:15 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10066
Location: Rio de Janeiro - Brazil
Those attribute tables suck.

I'm designing a platform engine that scrolls the screen to the sides as well as up and down. I'm using vertical mirroring, wich should (or so I thought!) present no problems in updating the attributes when scrolling sideways, as I'd have a huge off-screen buffer. However, the PPU has no "increment 8" mode as it has an "increment 32" one. Does that mean I really have to write the address to $2006 8 times if I want to update an attribute column? Oh, well...

A different problem shows up when updating rows of attributes. Since I'm using vertical mirroring, if I mess with the attributes at the bottom of the page I may be messing with blocks that are at the top, depending on the scrolling. So, I have to keep a copy of the attributes in RAM, update only the bits I need and them write the row to the PPU.

This all seems very inneficient... Isn't there a trick or something to handle attributes more efficiently?

I'll just think about it a little longer... this thing is really getting in the way of my engine...

EDIT: Hum... thinking better about the second problem, I guess most games don't have it because they have a status bar at the top or at the bottom, giving the programmer a buffer. I don't plan to have a status bar (wich would be difficult anyway, since the game can scroll anywhere it would be impossible to keep an area reserved for a status bar - unless using MMC5 and it's advanced mirroring control), so should I just shut the rendering off 16 pixels earlier to avoid any color glitches?


Top
 Profile  
 
PostPosted: Mon Jan 16, 2006 2:25 am 
Offline

Joined: Thu Sep 15, 2005 9:23 am
Posts: 1194
Location: Behind you with a knife!
tokumaru wrote:
...unless using MMC5 and it's advanced mirroring control...


That was my immediate thought. Before you do anything else, you should put more thought into using 4 NT at once as this would make for a fantastic game plus you would see no graphical glitches in any of the borders.

_________________
http://www.jamesturner.de/


Top
 Profile  
 
PostPosted: Mon Jan 16, 2006 9:38 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19116
Location: NE Indiana, USA (NTSC)
tokumaru wrote:
I don't plan to have a status bar (wich would be difficult anyway, since the game can scroll anywhere it would be impossible to keep an area reserved for a status bar - unless using MMC5 and it's advanced mirroring control)

Super Mario 3 just made the world 54 tiles high. Kirby's Adventure kept two parallel copies of the map spaced roughly a screen apart so that when the vertical scroll was to enter the status area, it would jump back a screen. One of the Gauntlet games used a mid-screen split to skip the status bar.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 9:50 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7234
Location: Chexbres, VD, Switzerland
Well, it is the exact third consequitive time that a thread in NESDev section start from "how can I do that..." end end up with "use an MMC5". Yeah, I admit MMC5 is awsome. BUT still, cards using it are very rare, and I think its use should be reserved for very large RPG and strategy games, allowing great graphics and save feature (Just Breed enter in all those categires, hehe). I don't have anything against platformers, but MMC5 is just not worth it. Tokumaru, the problems you mentionned can be surmounted easily with any mapper. Yes, the attributes tables such, and yes, the MMC5 can fix that in ExGrafix mode ONLY so with no extra nametable feature (one-screen mirroring needed).
Quote:
I'm designing a platform engine that scrolls the screen to the sides as well as up and down. I'm using vertical mirroring, wich should (or so I thought!) present no problems in updating the attributes when scrolling sideways, as I'd have a huge off-screen buffer. However, the PPU has no "increment 8" mode as it has an "increment 32" one. Does that mean I really have to write the address to $2006 8 times if I want to update an attribute column? Oh, well...
Yes. And I don't know why it hurts you so much. In a NTSC VBlank, you have enough time to upload a whole column while writing 68 times to $2006 then to $2007, including 2x30 nametable writes and 8 attribute table writes, additionnal to sprite DMA. VBlank is short, but not THAT short.
Quote:
A different problem shows up when updating rows of attributes. Since I'm using vertical mirroring, if I mess with the attributes at the bottom of the page I may be messing with blocks that are at the top, depending on the scrolling. So, I have to keep a copy of the attributes in RAM, update only the bits I need and them write the row to the PPU.

Yes, it is one of the worst flaws of the NES, additionally to the 8 sprites per scanline limitation.
If you want to save RAM, you are able to read an attribute tile, modify the bits you want, and write it back. You DO have time to do that in VBlank if your code is efficient enough. However, in that case, you'll have to write the nametable efficiantly whith two vertical strings and not tile per tile as mentionned above, that I think you would anyway do. Doing such complicates the code, but fast it up a lot.
If you want to save timem, a trick is to hold the exact copy in $3c0-$3cf and $7c0-$7cf to mirror respectivly $23c0-$23cf and $27c0-$27cf. So you don't have to recalculate adresses. I discovered that in tracing a Dragon Warrior game, but never did that in practice.
It IS possible to calculate attributes normally, that means to read your map 30 tiles earlier and split all colors bit to mix them together. It is pretty hard, and innefecive in some case where it removes some flexibility. However, think about it.
About color glitches, they're 100% avoidable by using vertical mirroring and an NTSC television that cuts the top and bottom 8 pixels.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 10:37 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10066
Location: Rio de Janeiro - Brazil
Yeah, you got it right, I do want to make an 100% glitch-free game.

Thanks for the insights Bregalad. I've been giving a LOT of thought to the rendering routine of my engine in the past few hours. I calculated everything in a way that VBlank time is enough to do all the drawing I need.

Scrolling is limited to 8 pixels (1 tile wide/tall) per frame in both directions. My game uses 16x16 pixel blocks to build the world, but I'll render only half of a column/row of blocks at a time, so that in case I need to draw both (row and column = player moving diagonally) I have enough time. For simplicity's sake, when I render rows of blocks I render two full name tables worth of blocks (vertical mirroring = wider video area), so that the level's screens stay aligned with the name tables.

As for the attributes, I'll keep a copy of them in RAM to modify at will (I got some free RAM to spare... 128 bytes is not a problem at all). I also accounted for them in the rendering routine and there is enough time to write a row and a column of attributes if needed.

There is also time to update the palettes and do a sprite DMA.

In frames that don't need attribute rendering, I use the time to update a few random BG tiles and attributes (for simple BG animation, disappearing stuff, etc).

I think I found a way to update the screen that's very well suited to my game. The copy routines are HUGE though, a bunch of LDA's and STA's chained together reading from the buffers and writing to the PPU.

Now regarding the mapper... I don't think using MMC5 all the time is the answer either. I feel like using it for this project though, mainly because it can address 8k worth of tiles for sprites and 4k more to the background. Using ExAttribute for a fast-paced game is counter-productive, I think. VBlank time is already short enough when we use 64 bytes of attributes... having to update the attributes at the same ratio as the name table could really slow things down.

I'll try to choose some other mapper, I need something with good CHR switching (1k banks), and 16k PRG switching is fine. Scanline/cycle counter is a plus for me, although I don't really know if I'll be using it. I want to, but will depend on the kind of levels I design for the game.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 10:59 am 
Online

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19116
Location: NE Indiana, USA (NTSC)
tokumaru wrote:
I'll render only half of a column/row of blocks at a time, so that in case I need to draw both (row and column = player moving diagonally) I have enough time.

Or you could render a row in one frame and then a column in the next frame if the hero isn't fast like a blue hedgehog.

Quote:
I think I found a way to update the screen that's very well suited to my game. The copy routines are HUGE though, a bunch of LDA's and STA's chained together reading from the buffers and writing to the PPU.

Unrolling is a good thing if you have the ROM space.

Quote:
Now regarding the mapper... I don't think using MMC5 all the time is the answer either [...]Using ExAttribute for a fast-paced game is counter-productive, I think.

How fast-paced?

Quote:
VBlank time is already short enough when we use 64 bytes of attributes... having to update the attributes at the same ratio as the name table could really slow things down.

But you wouldn't have to update the attributes using read-modify-write.

Quote:
I'll try to choose some other mapper, I need something with good CHR switching (1k banks)

Can you get away with 2 KB switching for background or sprites and not using 8x16 sprites from both pattern tables simultaneously? If so, I recommend MMC3.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 11:25 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10066
Location: Rio de Janeiro - Brazil
tepples wrote:
Or you could render a row in one frame and then a column in the next frame if the hero isn't fast like a blue hedgehog.

Thought of that... but I plan to use this engine (with small modifications) in more than one game, and at least one of them will need to be fast. I've set the max player speed to 8 pixel per frame in this case, wich means I have to be prepared to draw one column AND one row of tiles if I need to.

My original idea was to draw the full blocks, but if by any chance the player moved in both directions by an ammount that would require screen updates, I'd either get visual glitches (for not having drawn stuff that should be showing already) or choppy camera movement (if I didn't let the camera see areas that have not yet been rendered).

Quote:
Unrolling is a good thing if you have the ROM space.

Yeah, these copy routines will definately take less than 2k of space. I can live with that. It would be impossible to make a fast game otherwise.

Quote:
How fast-paced?

Well, I don't have any figures but... in the usuall way you'd have to write 8 bytes for a full column or row of on screen attributes, and using ExAttribute you'll have to write 30 or 32 bytes. It may eventually get in your way depending on how much speed you need. With the player moving at 8 pixels per frame in both directions it wouldn't be possible to use ExAttribute (it may be possible, but it'd probably be all you'd be doing - no sprite DMA, no palette updating, etc), I think.

Quote:
But you wouldn't have to update the attributes using read-modify-write.

True, but, I at least, do my reading-modifying-writing outside of VBlank, not wasting any precious cycle of it.

Quote:
Can you get away with 2 KB switching for background or sprites and not using 8x16 sprites from both pattern tables simultaneously? If so, I recommend MMC3.

It seems like it's the logical choice, doesn't it? I can live with 2k switching for one of the pattern tables, but I'll have a hard time adjusting to not using the BG side of it for 8x16 sprites.


Top
 Profile  
 
PostPosted: Mon Jan 16, 2006 1:31 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10066
Location: Rio de Janeiro - Brazil
tepples wrote:
Super Mario 3 just made the world 54 tiles high. Kirby's Adventure kept two parallel copies of the map spaced roughly a screen apart so that when the vertical scroll was to enter the status area, it would jump back a screen. One of the Gauntlet games used a mid-screen split to skip the status bar.


I don't plan to have a status bar, but I do like the topic. We've dicussed these methods somewhere in here before...

Skiping the status bar is the only method with no great impact on the speed of the game, but it does add extra complexity and possible small glitches.

Limiting the height of the level to little less than 2 screens is the worst choice in my opinion 'cause I love big levels! I wouldn't live well with such a limitation. It is the simplest way if this height is enough for your game.

Drawing things twice is a smart way of handling the problem, but also cuts your drawing time in half. This is the most creative of the methods, and that is why I like it the most.

It is really interesting to see how people have managed to overcome this kind of difficulty through the years. That's one of the coolest thing about the older gaming systems.


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: No registered users and 7 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