Dynamic SNES sprite table construction?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Dynamic SNES sprite table construction?
by on (#34852)
Tell me what you think of this idea for building a dynamic SNES sprite table. (Or share you ideas).

The hardest part of building the table would seem to be setting up the 32 byte table at the end of the list (whatever it's technically called).

My idea for making this easy would be constructing 2 256 byte tables, for 128 sprites.

One table would contain values where the size bit is 0, and the other one would contain a size bit of 1. Each sprite would store the address of the table to use. The table pointer would remain the same throughout the 'life' of the sprite, and only need to be set when the sprite was initially added.

Each table would contain:

%000000x0 (x is the size bit)
%000000x1
%0000x000
%0000x100
%00x00000
%00x10000
%x0000000
%x1000000
.. repeated for the entire 256 bytes. (This could use 8 bytes, but the time spent masking the pointer probably wouldn't be worth saving 248 bytes per table).

At the beginning of the sort routine, the entire 640 bytes of sprite memory would be cleared.

An offset pointer, to the correct table entry, would be set up at the beginning of the routine, and incremented by two each time.

The upper byte of the sprite x position, would be added to the table offset pointer. The value, obtained from the table, would be or'ed with the current location in the sprite table. There would be no need for masking, as the byte would be cleared at the beginning, and be built up sequentially.

I would probably process 4 sprites at a time, this would allow me to:
1) Store the temporary value in a zero page memory location, and write it as a single byte to the sprite table.

2) Increment the sprite table address for each 4 sprites.

The 'shadow' sprite list would have to be padded out to 4 sprites increments by the sorting routine.

Does this sound reasonable, or is there a faster/easier way?

Could it be done in the vertical retrace, assuming the routine was fairly well written (in asm)?

by on (#34932)
I think it all depends on how much sprites you want to display/what kind of genre you're doing.

From my experience(and that's not very much), you usually won't have more than 15-32 sprites on screen that need sorting for the average jump n run or rpg, anyway.
And of the total time needed to process a sprite in such an environment, you`ll probably spend the most calculating the sprite action/movement/animation/whatever.

For such a low number of sprites, the time needed to copy from your object list to your oam table buffer probably wouldn't matter that much.
Unless you're doing a bullet hell shooter of course, but you'd probably leave out sorting, sprite priority and the x-position msb completely in that case.
Also, calculating the offset and bit position in the x-pos msb/priority oam table does not take _that_ much time if you're using a lookup table for the shifts.

Your idea sounds nice, but I'd imagine that once you've implemented it, you'd spend most of the time clearing your 640 byte table each frame, not creating the oam table itself.

I just hope I didn't miss your point completely...

by on (#34937)
d4s wrote:
I think it all depends on how much sprites you want to display/what kind of genre you're doing.

Your idea sounds nice, but I'd imagine that once you've implemented it, you'd spend most of the time clearing your 640 byte table each frame, not creating the oam table itself.

I just hope I didn't miss your point completely...


But, doesn't each genre need to sort the sprites in some way?

The 640 byte table will be operated on in ram, and should be fairly easy to clear.

I think you understand what I'm trying to accomplish.
Re: Dynamic SNES sprite table construction?
by on (#34973)
Quote:
The hardest part of building the table would seem to be setting up the 32 byte table at the end of the list (whatever it's technically called).


I know this is basically gaming sacrilege, but if you have a bottleneck and don't otherwise want to limit your game ... if you're willing to clip the sides of the screen by ~16 pixels each, then you really don't need to worry about the 32-byte attribute table at all. It only stores the highest-bit of the X position, and the size of the sprites.

I think it's relatively safe to assume your sprites aren't going to change sizes every frame. And when they do, you'll have more overhead changing them than a bit in an attribute table.

As for X.d8, well, if your screen width is 256 pixels, is it really ever necessary to place a sprite at X=256 (completely offscreen) or above? If you try and use it as a "sprite disable" bit, you get to worry about the fun bug where if X is exactly 256, all of its tiles are added to your on-screen sprite limit count, even though none of it is visible. It's better to set Y to 224 or 240 to disable a sprite.

With the clipping, you'll no longer need to set "negative" sprite positions (eg 511 = -1) to smoothly scroll a sprite off the left edge of the screen.

Quote:
Could it be done in the vertical retrace, assuming the routine was fairly well written (in asm)?


Retrace gives you ~50,000 cycles of time. That gives you ~2,000 or so instructions to work with. Usually, NMI routines are designed to blit data to VRAM, OAM and CGRAM from a saved list, poll for input, maybe do some sound events, and not much else. Each DMA byte transferred consumes 8 cycles from your available time.

You should also keep in mind that you can control "vertical retrace" (or more honestly, the ability to write to VRAM, OAM and CGRAM on a given scanline) by turning on forced blank. Games like SFA2 use IRQs to disable the screen for the first 16 lines or so, and for the last 16 lines or so, which doubles the length of your vertical retrace period in return for a slight reduction in screen real estate.

But really, you should process the list outside of your NMI routine, and let the NMI just blit the entire 544-byte table all at once if a "dirty" flag is set.
Re: Dynamic SNES sprite table construction?
by on (#34992)
byuu wrote:
But really, you should process the list outside of your NMI routine, and let the NMI just blit the entire 544-byte table all at once if a "dirty" flag is set.

Yup, that's what virtually all NES games do.