Page 1 of 1

sprite attribute table

Posted: Tue Jul 01, 2014 1:32 am
by powerofrecall
I have done some small MD exercises in the past but I have always handled no more than a few sprites at a time so managing the sprite list has been simple. How is the sprite list handled in larger productions?

Is it acceptable to manage a sprite list in RAM and just DMA it over to the VDP RAM? This seems like it would be much easier than trying to dynamically manage the sprite list through the VDP's ports.

Posted: Tue Jul 01, 2014 1:55 am
by Mask of Destiny
The SAT is only 640 bytes (in H40 mode) so unless you're starved for DMA bandwidth during VBLANK, DMAing it from work RAM to VRAM every frame is probably the sanest option.

Posted: Tue Jul 01, 2014 2:09 am
by powerofrecall
This is what I was thinking, it's just nice to have consensus and check if there is some better way that I am completely glossing over.

Posted: Tue Jul 01, 2014 1:14 pm
by Stef
Mask of Destiny wrote:The SAT is only 640 bytes (in H40 mode) so unless you're starved for DMA bandwidth during VBLANK, DMAing it from work RAM to VRAM every frame is probably the sanest option.
Actually the SAT can be 128 entries length (and so 1024 bytes) even if only 80 linked entries can be parsed (don't forget you can parse the list in whatever order, thanks to the link field).

Posted: Tue Jul 01, 2014 6:33 pm
by Mask of Destiny
It's kind of surprising that is allowed in a way since it means the VDP needs to have a full 512 bytes (or more likely 2688 bits) of on-die RAM for caching the link and y position fields which seems rather expensive for a marginally useful feature. It's especially surprising given that they didn't include an extra 2-words of VSRAM (at least not until the Genesis 3 anyway) so that the extra internal columns of the background could have their own scroll value.

Posted: Tue Jul 01, 2014 10:20 pm
by Nemesis
Stef wrote:
Mask of Destiny wrote:The SAT is only 640 bytes (in H40 mode) so unless you're starved for DMA bandwidth during VBLANK, DMAing it from work RAM to VRAM every frame is probably the sanest option.
Actually the SAT can be 128 entries length (and so 1024 bytes) even if only 80 linked entries can be parsed (don't forget you can parse the list in whatever order, thanks to the link field).
Actually, I don't think you can do this. When I wrote my sprite test ROM ( viewtopic.php?p=8364#8364 ) I tested referencing entries past the maximum sprite number (64 under H32, 80 under H40), and it doesn't work on the real hardware. Every emulator had this wrong. Regen was the only one I tested that had the correct behaviour at the time.

Posted: Tue Jul 01, 2014 10:48 pm
by Mask of Destiny
Heh, I actually implemented that in BlastEm (probably after testing with your sprite test ROM) and forgot about it.

Posted: Wed Jul 02, 2014 9:03 am
by Eke
Nemesis wrote:
Stef wrote:
Mask of Destiny wrote:The SAT is only 640 bytes (in H40 mode) so unless you're starved for DMA bandwidth during VBLANK, DMAing it from work RAM to VRAM every frame is probably the sanest option.
Actually the SAT can be 128 entries length (and so 1024 bytes) even if only 80 linked entries can be parsed (don't forget you can parse the list in whatever order, thanks to the link field).
Actually, I don't think you can do this. When I wrote my sprite test ROM ( viewtopic.php?p=8364#8364 ) I tested referencing entries past the maximum sprite number (64 under H32, 80 under H40), and it doesn't work on the real hardware. Every emulator had this wrong. Regen was the only one I tested that had the correct behaviour at the time.
This is not how this is implemented in Genesis Plus either (you can access VRAM & internal SAT at any link address below 0x80) but surprisingly, it always passed test #9 in your test ROM so I wonder what this test does exactly ?

I find it weird that the VDP would actually check the link value against the current sprite limit (64 or 80), internal cache might indeed be limited in size and cause potential issues when fetching above that limit but I do not see why the VDP would limit the acces to VRAM

Posted: Wed Jul 02, 2014 12:43 pm
by Stef
Nemesis wrote: Actually, I don't think you can do this. When I wrote my sprite test ROM ( viewtopic.php?p=8364#8364 ) I tested referencing entries past the maximum sprite number (64 under H32, 80 under H40), and it doesn't work on the real hardware. Every emulator had this wrong. Regen was the only one I tested that had the correct behaviour at the time.
Oh really, i though the contrary because i do know some games are filling the sprite list as if it could contains 128 entries but i have to admit i never made tests to confirm that.

Posted: Wed Jul 02, 2014 3:04 pm
by Charles MacDonald
I find it weird that the VDP would actually check the link value against the current sprite limit (64 or 80), internal cache might indeed be limited in size and cause potential issues when fetching above that limit but I do not see why the VDP would limit the acces to VRAM
I had assumed that for sprite numbers larger than 80, the X position and attribute words were read from VRAM like normal (at an offset larger than 640), but the Y position and size/link fields read were garbage since the on-chip RAM has 640 of 1024 locations implemented, so you get whatever random values are on the internal data bus.

Do we actually know how it works? Like has anyone put a logic analyzer on the VRAM address bus and looked at fetches for sprites >=80 in 320 pixel mode, or found a way to use those higher value sprites in a consistent (non glitchy) way?

Posted: Wed Jul 02, 2014 6:43 pm
by Mask of Destiny
Charles MacDonald wrote:
I find it weird that the VDP would actually check the link value against the current sprite limit (64 or 80), internal cache might indeed be limited in size and cause potential issues when fetching above that limit but I do not see why the VDP would limit the acces to VRAM
I had assumed that for sprite numbers larger than 80, the X position and attribute words were read from VRAM like normal (at an offset larger than 640), but the Y position and size/link fields read were garbage since the on-chip RAM has 640 of 1024 locations implemented, so you get whatever random values are on the internal data bus.

Do we actually know how it works? Like has anyone put a logic analyzer on the VRAM address bus and looked at fetches for sprites >=80 in 320 pixel mode, or found a way to use those higher value sprites in a consistent (non glitchy) way?
The big problem with trying to ascertain sprite rendering internals from VRAM is that the entirety of the first phase of rendering doesn't touch VRAM at all since it only needs the information stored in the SAT cache. You can really only observer what happens in that phase by seeing what SAT entries (x pos and tile number portion) get fetched in phase 2. I haven't actually looked at this scenario under a logic analyzer (though perhaps Nemesis has), but since the sprite in question in his test isn't rendered it's probably not making it to phase 2.

One possible explanation for the behavior that makes a bit more sense than an explicit sprite limit check is that the SAT cache returns all zeroes for entries >= $80. This would result in the final sprite having a y position of 0 and link field of 0 which would not be rendered and would terminate the sprite list.

Of course, that doesn't explain the behavior in H32 mode. My guess there would be that only the low 6 bits of the link field are used. Should be testable with an appropriately crafted sprite list.

Posted: Thu Jul 03, 2014 3:42 am
by Nemesis
Eke wrote:This is not how this is implemented in Genesis Plus either (you can access VRAM & internal SAT at any link address below 0x80) but surprisingly, it always passed test #9 in your test ROM so I wonder what this test does exactly ?
Source is provided, so it should be easy to determine what's happening. I just noticed the links weren't working from my webspace, so I've fixed them. From memory, it's something fairly simple, like showing all but the last allowable sprite number (IE, 63 in H32, 79 in H40), then for the last sprite, the link data skips over one entry and takes it to the one after. This means the left tick should appear if you display sprite 63, while a cross will be placed on the right if you display sprite 64, under H32 mode that is.

I never had a solid theory of why sprites are limited in this way. This is a test I was surprised to discover failed on the hardware. Originally the point of that test was to verify it DID work, then I found out it actually didn't work on the hardware either. The theory about scrambled or zeroed data coming out of the internal SAT cache is a very good point. It's possible that the values in other areas of the SAT, IE, in the preceding sprite on the list, affect the data for entries read off the end of the table.

I have used a logic analyzer to trace the VRAM access cycles for SAT reads, but not under the particular case of attempted reads past the end of the table. As Mask of Destiny mentioned, sprite rendering has two distinct phases, and the first one operates entirely from the internal cache of a portion of the SAT. The first step would be to determine if attempted sprite access past the end of the table is being rejected at the first or second step, and then to see if this behaviour is influenced by any other data in the table, like it is for reads past the end of VSRAM.

Posted: Thu Jul 03, 2014 3:48 am
by Nemesis
Thinking all this through again, I think the answer might be simpler than I thought. The internal cache of part of the SAT is only effective within the region where the SAT is actually present. I suspect this caching process might also take account of the current H32/H40 mode, and perhaps, it only caches data within the first 64 entries of the table when H32 is active, and the first 80 entries of the table when H40 is active. It might be that reads past the end of the SAT wrap back around to the start of the table past entry 80, so if you try to read from sprite 81 for example, you'd be reading the cached data for sprite 1, and the uncached data from sprite 81. I suspect entries 65-80 in the cache can only be modified when H40 is active, otherwise they retain their previous values. Some tests could easily be constructed to investigate this.

Posted: Thu Jul 03, 2014 10:57 am
by Eke
Nemesis wrote: Source is provided, so it should be easy to determine what's happening. I just noticed the links weren't working from my webspace, so I've fixed them.
Thanks, i think I figured what's going on.

in h40.bin, sprite entry $4F link value is set to $40 (65th sprite ) instead of $50 (81th sprite) so sprite entry $50 is never parsed, hence why this test is OK in every emulators and real hardware

if someone want to quickly test the real behavior on hardware, replace $40 at ROM offset $1E69F by $50

EDIT: I tested the modified ROM and the test is still OK on real hardware in H40 mode but now fails on all emulators (cannot test Exodus or Blastem), which means sprites entry above the 40th sprite are either not cached or simply ignored during parsing.
I suspect entries 65-80 in the cache can only be modified when H40 is active, otherwise they retain their previous values. Some tests could easily be constructed to investigate this.
Test #9 in H32 mode was indeed OK in Genesis Plus / Regen because of this: internal SAT cache writes above offset $200 are ignored in H32 mode ($400 in H40 mode)

EDIT: I modified the ROM again to make it set sprite entry $4e in both H32 & H40 mode with the "bad" sprite then set the last sprite entry link to $4e instead of $40 in H32 mode (entry $4e not linked in H40 mode).

Test #9 now fails in Regen & Genesis Plus when going from H40 to H32 mode but is always OK on real hardware, which seems to indicate that sprite entry $4e was ignored during parsing, despite being cached when in H40 mode.

here is a link for modified ROM: http://www.speedyshare.com/xxaD8/Sprite ... dified.bin

and expected output on real hardware:
Image Image
It might be that reads past the end of the SAT wrap back around to the start of the table past entry 80, so if you try to read from sprite 81 for example, you'd be reading the cached data for sprite 1, and the uncached data from sprite 81.
I verified it was not the case by patching the last ROM to change the sprite list in H40 mode from $44->$4f->$50 to $44->$50->$4f : on real hardware, the last two sprites are not being displayed (left cell is "ko" and right cell is "ok"), indicating VDP stopped parsing the sprite list once it reached sprite entry $50

here is a link with patched ROM that partially "fails" test#9 in H40 mode:
http://speedy.sh/GGwkM/Sprite-Masking-Test-ROM-fail.bin

Image

Last thing that needed to be verified is if entries $40-$4f can still be modified in cache during H32 mode and affect parsing in H40 mode.
This time I patched the modified Test ROM so that VRAM is not updated when switching to H40 mode and the result is that sprite entry $4e ("KO" sprite) is not displayed when switching to H40, indicating that internal cache entry was not updated during H32 mode

here is a link with patched ROM that does not update VRAM in H40 mode:
http://www.speedyshare.com/uusXF/Sprite ... th-H32.bin

Image