Just another limitations related question

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Just another limitations related question
by on (#159949)
Hello everyone!

I am creating a game in Unity game engine. One of my goals is to make the game look like a genuine NES game. I know most of the limitations, but there are things that confuses me.
-I am considering to replicate sprite flickering. So I can create my sprites divided into 8x16 tiles (because that's my choice). How can I make it flicker? When do I have to disable the sprite renderer on my objects? What's the "most realistic" way to do it? How should I detect the number of sprites in a scanline? OK, what would be the best way to simulate scanlines (not visually but for the flicker's purpose)?

-What is the exact limit for tiles loaded at a time and stored in a ROM in overall? I don't want to create unrealistically too much for my game. Any memory mappers that extended their number?

-Can I assign other palette to a sprite / background? Or I can just change their current palettes' colour?

Current progress (using a modified Castlevania III sprite as a character placeholder (it won't be a Castlevania game though))
Image

A screenshot with HUD:
Image
Suddenly that's all comes into my mind.
Re: Just another limitations related question
by on (#159951)
AdamP wrote:
How can I make it flicker? When do I have to disable the sprite renderer on my objects? What's the "most realistic" way to do it? How should I detect the number of sprites in a scanline? OK, what would be the best way to simulate scanlines (not visually but for the flicker's purpose)?

What happens is that the PPU can only render 8 sprites per scanline. If there are more than 8 present in a scanline, the ones with lower priority will not show. Priority is defined by the order of the sprites in OAM: sprite 0 has the highest priority and sprite 63 the lowest. Games make the sprites flicker by alternating/randomizing the OAM order every frame, so that all sprites have the chance of being high priority every once in a while.

Simulating this accurately will require you to draw sprites one line at a time (8x1 pixels), as opposed to the whole 8x16 pixels at a time, since there could be a situation where the top of a low priority sprite is in a busy area and doesn't get displayed, but the bottom part of it is in a less busy area and it does get partially displayed.

The correct thing to do would be what the NES does: every scanline, loop through all 64 sprites, starting from 0 (the one with highest priority), subtracting each sprite's Y coordinate from the scanline index, and if the result is less than 16, that's the sprite line you have to draw. Once 8 sprites have been found to be in range, don't draw any more sprites.

Quote:
-What is the exact limit for tiles loaded at a time and stored in a ROM in overall? I don't want to create unrealistically too much for my game.

A mapperless game can only see 512 tiles. The background can only use 256 of those, and 8x8-pixel sprites can also only use 256. 8x16-pixel sprites can use all 512 tiles, but the top tile is always even, and the bottom tile is the odd one that follows it.

Quote:
Any memory mappers that extended their number?

The main purpose of mappers is to expand memory. The simplest way to break the 512-tile limit is to use CHR-RAM instead of CHR-ROM. The NEs can still only see 8KB of CHR (512 tiles), but since it's RAM, it can be rewritten by the program on the fly, so the total limit is how much tile data you can fit in the program ROM.

Many mappers can expand the total amount of tiles, but most still only allow 512 at a time. I suggest you read the wiki pages about the existing mappers to get an overall idea of what they can do.

Quote:
-Can I assign other palette to a sprite / background? Or I can just change their current palettes' colour?

I don't understand the question.

Quote:
Current progress

Looks good!
Re: Just another limitations related question
by on (#159952)
AdamP wrote:
How can I make it flicker? [...] How should I detect the number of sprites in a scanline?
Check the sprites' bounding boxes, sort by Y, see which scanlines have more than 8 tiles worth of sprites. Either randomly or sequentially pick a subset of 8 different tiles to draw, and throw away the rest.

Quote:
When do I have to disable the sprite renderer on my objects? What's the "most realistic" way to do it? OK, what would be the best way to simulate scanlines (not visually but for the flicker's purpose)?
The problem, on some level, is that Unity is not designed to make implementing this restriction easy.

For example, if you have a situation where you have two 64x8 pixel sprites, separated vertically by a 4 pixel gap, and you try to add another 8x8 tile in that gap, only the 4 rows in the gap will show up.

Quote:
-What is the exact limit for tiles loaded at a time and stored in a ROM in overall? I don't want to create unrealistically too much for my game. Any memory mappers that extended their number?
Most minimal (plain NROM): 512 8x8 tiles at a time, of which half are used for background and half are used for sprites. You can swap which half is used for which at any point, including mid-screen.

Cheapest (oversize CNROM): up to 256 planes of 512 8x8 tiles, with the above restrictions; you can swap which plane is present at any time:

Most common: (MMC3/FME7): up to 256 planes of 64 8x8 tiles, where you choose any four planes for background tiles and any four planes for sprite tiles.

Most overkill: (MMC5): 16384 8x8 tiles, with a different palette for each 8x8 zone. Using the fine-grained palette selectors doesn't look "NES"-like. Additionally, 8x16 sprites here can come from any eight 32 8x16 tile planes.

Quote:
-Can I assign other palette to a sprite / background? Or I can just change their current palettes' colour?
There are four sprite palettes and four background palettes. Each sprite can have any arbitrary single palette; each 16x16 pixel zone of the background can have any arbitrary single palette.

You can change colors in the palette mid-screen, but it requires turning off the NES's renderer, so can in practice only be used for status bars and the like.
Re: Just another limitations related question
by on (#159959)
From an artistic perspective, it's really not worth the effort implementing sprite flickering. Especially if it's as difficult as you say it is. Things like size and color limitations will add to your NES aesthetic, but flicking is more of an annoyance if anything. It also creates issues for epileptics and it's something many disable in emulators anyways.

In my opinion, you should probably focus your efforts on improving the game itself. Or maybe how you handle tile rendering. The mixed pixel sizes make everything look very cluttered. :(
Re: Just another limitations related question
by on (#159960)
From a programming perspective, it's dead simple.
Re: Just another limitations related question
by on (#159965)
DragonDePlatino wrote:
From an artistic perspective, it's really not worth the effort implementing sprite flickering. Especially if it's as difficult as you say it is. Things like size and color limitations will add to your NES aesthetic, but flicking is more of an annoyance if anything. It also creates issues for epileptics and it's something many disable in emulators anyways.

In my opinion, you should probably focus your efforts on improving the game itself. Or maybe how you handle tile rendering. The mixed pixel sizes make everything look very cluttered. :(


The pixel ratios are fine, it just looks like Unity's nasty way of handling pixel art assets.
(Particularly, it's quite poor at managing tiled graphics.)
Re: Just another limitations related question
by on (#160028)
Thanks for all the answers. Things are clearer now. But... I still have a few questions and things that I don't understand.

lidnariq:
lidnariq wrote:
You can change colors in the palette mid-screen, but it requires turning off the NES's renderer, so can in practice only be used for status bars and the like.
Post


What does it mean exactly? What can I and what can't I do because of that? How fading effects and day to night transitions work (like in Castlevania II)? I mean, obviously with palette colour change, but why it was possible technically?

Also the mapper explanation is super useful, thanks!

Alp wrote:
The pixel ratios are fine, it just looks like Unity's nasty way of handling pixel art assets.
(Particularly, it's quite poor at managing tiled graphics.)


Yeah, I realised that. At some resolutions, there are distortions. Trying to fix it. For sprites, I wrote a special shader. It basically snaps the vertices to rounded values, so my sprites can be only at an exact "pixel", not half pixel off for example. Also my shader is specified for using only FF0000,00FF00,0000FF colours on the sprite. Yeah, it's kinda tricky to edit the sprites since I have to use those three colours at the end, the shader changes it to colours from the predefined palettes that uses somewhat accurate colours of the real NES. Also this makes it impossible to use an "illegal" colour.

But about pixel art handling, still there are issues in Unity for me.

tokumaru wrote:
I don't understand the question.


I try to explain. I have 4 active palettes for sprites. My character sprite uses palette #0 for example. Am I allowed to assign palette 1,2 or 3 to the sprite on the fly? Or I am restricted to use that palette.

tokumaru]Looks good![/quote]

Thanks!

[quote="DragonDePlatino wrote:
In my opinion, you should probably focus your efforts on improving the game itself. Or maybe how you handle tile rendering. The mixed pixel sizes make everything look very cluttered.


Of course, I'll improve the game itself, it's just the very beginning of the project. What's the problem with the pixel size and where? I think it's the same pixel size everywhere.


Thanks everyone the help!
Re: Just another limitations related question
by on (#160029)
AdamP wrote:
lidnariq wrote:
You can change colors in the palette mid-screen, but it requires turning off the NES's renderer, so can in practice only be used for status bars and the like.

What does it mean exactly? What can I and what can't I do because of that? How fading effects and day to night transitions work (like in Castlevania II)? I mean, obviously with palette colour change, but why it was possible technically?

There's no problem with changing the palette between one frame and the next. Lidnariq is referring to use of one palette for the top of the screen and use of another for the bottom. This sort of mid-screen palette switch is a bit trickier and typically requires a few scanlines to be left blank between one palette and the other so that the palette-in-progress doesn't get displayed as a rainbow streak on the screen. These blank lines are usually fine for changes between the playfield and status bar but not for changes within a playfield.

Quote:
I have 4 active palettes for sprites. My character sprite uses palette #0 for example. Am I allowed to assign palette 1,2 or 3 to the sprite on the fly? Or I am restricted to use that palette.

The palette for a sprite can be changed whenever the display list is reuploaded to OAM, which typically means once per frame.
Re: Just another limitations related question
by on (#160031)
Everything can be changed from one frame to the next, you're only limited by how much data you can send to VRAM during the small interval that exists between frames. The biggest bandwidth hogs are background and pattern updates, which must be restricted to small portions. Sprites and palettes are relatively quick to update, since there's a DMA function to help with the sprites and all palettes together take less than 32 bytes. After these 2 are updated, you can maybe change another 128 bytes or so in the remaining vblank time.

Mid-frame changes are more complicated. Rendering parameters, such as the scroll, color emphasis and grayscale mode, can be changed without side effects if you time the changes carefully, but anything that requires new data to be sent to VRAM can only be done if rendering is interrupted for the duration of these updates.
Re: Just another limitations related question
by on (#160045)
AdamP wrote:
Of course, I'll improve the game itself, it's just the very beginning of the project. What's the problem with the pixel size and where? I think it's the same pixel size everywhere.


Like Alp said, the way Unity is rendering your tiles is pretty terrible. It looks like they're being resized from 8x8 to about 15x15 and that extra pixel of space is being filled with garbage. The result is that you've got 2x2 pixels in some places and 1x1 pixels in others. On the right is a fix for what I'm talking about:

Image
(Note, there are still some leftover issues from your resizing. The item slots in the upper-right still look distorted, for example)

Ideally, I would render everything at 1x zoom then stretch the entire screen to 2x when blitting it to the window. It will slow down your game's rendering but will fix alignment issues and make everything look far more professional.
Re: Just another limitations related question
by on (#160117)
DragonDePlatino wrote:
AdamP wrote:
Of course, I'll improve the game itself, it's just the very beginning of the project. What's the problem with the pixel size and where? I think it's the same pixel size everywhere.


Like Alp said, the way Unity is rendering your tiles is pretty terrible. It looks like they're being resized from 8x8 to about 15x15 and that extra pixel of space is being filled with garbage. The result is that you've got 2x2 pixels in some places and 1x1 pixels in others. On the right is a fix for what I'm talking about:

Image
(Note, there are still some leftover issues from your resizing. The item slots in the upper-right still look distorted, for example)

Ideally, I would render everything at 1x zoom then stretch the entire screen to 2x when blitting it to the window. It will slow down your game's rendering but will fix alignment issues and make everything look far more professional.


Oh yeah, I see now. It's really terrible how it looks like. I didn't even realise it when I took the screenshot. Actually it's caused by my shader... and Unity's horrible tile rendering. My shader snaps vertices to integers or actually since my 8 pixels per unit for my sprite settings, I snap them to every 1/8th unit. For the player, it works fine, but there are issues with it like what you pointed out. Disabling snapping fixes the problem. Maybe I'll find an other solution for snapping. Maybe it's better if I snap the actual game object to the right position (which'll cause other kind of troubles)
Re: Just another limitations related question
by on (#160152)
See if you can render your game to a 256x240 surface, then draw a scaled version of that for your final output.
Re: Just another limitations related question
by on (#160254)
mikejmoffitt wrote:
See if you can render your game to a 256x240 surface, then draw a scaled version of that for your final output.


Thanks for the feedback, I am working on it!