So... the sprite overflow flag doesn't necessarily get set when there are more than 8 sprites on one line, because as has been documented on the Wiki, once 8 sprites are found, the PPU starts interpreting tile index, attribute, and X coord data in sequence as Y coords for every 3/4 sprite records in the OAM after that (only 1/4 of the records then after actually have their proper Y coords used in the overflow test).
That said, it's also my understanding that the sprite overflow flag could even be set if 8 sprites, but no more than 8, were actually found to be in range on a scanline, just based on any random and unique configuration of the PPU's entire 256-byte OAM.
A serious question then comes to my mind, when I think of the sprite overflow flag's operation:
*** Is "Sprite Overflow" an appropriate name for a PPU flag that bases it's function on a whole lot of complex sprite randomness? Was this complex behavior intentionally implemented, or (heaven forbid), an engineering mistake on behalf of Nintendo's PPU designers? ***
A further thought for consideration: How can an NES programmer even take advantage of this flag (for timing), when even modifying a single byte in an unrelated part of the OAM _may_ cause this flag's behavior to glitch? I mean, we 2C02 developers are skilled and talented low-level CPU mechanics of such temporal-sensitive environments like the NES's, but we are not magicians who can occupy and utilize the OAM in such an awkward way (how?), that will not glitch out this stupid little flag's operation of bizarre behavior.
Opinion: It almost seems to me that the designers of the original 2C02 schematic made some sort of mistake when they implemented this flag's function in logic, because I can not wrap my head around the purpose of this "feature", as has been documented.
This glitch is similar in headache (but not as useless) to as how the APU's DMC DMA unit steals 3 uselsess CPU read cycles from innocently executing joystick code (however, if SNES pads were used instead of NES pads, then detecting a DMC DMA controller glitch would be as easy as examining the 14th, 15th, or 16th read bit from $4016/7 as a 0 or a 1, but that's neither here nor there).
Comments?
TL;DR
Just cycle sprites all the time if you're creating a game where sprites may (or may not) be in the same scanline at the same time.
Bee 52 used sprite overflow to split the screen.
Edit: no, it didn't. But it did require Sprite Overflow to get past a solid purple screen.
3gengames wrote:
TL;DR
Just cycle sprites all the time if you're creating a game where sprites may (or may not) be in the same scanline at the same time.
I was thinking more along the lines of using the flag for a stable, horizontal playfield split, but that's not going to be possible when I've gotta rearrange OAM data every frame.
For a stable horizontal playfield split, use Sprite 0 hit (possibly combined with DMC IRQ). You can shuffle the rest of the sprites fine.
Dwedit wrote:
For a stable horizontal playfield split, use Sprite 0 hit (possibly combined with DMC IRQ). You can shuffle the rest of the sprites fine.
Well, I know I can use Sprite 0 hit to do that, but the basis of this query is to establish some community consensus for the fact that the Sprite Overflow flag is either hard as hell to depend on, or just not being worth bothering with to use in the first place for programming (unless someone can show me a practical solution, where practical means not having to restrict my use of the OAM to make the flag work dependably).
Also, based on my tests with my own NES/FC R.E. KIT, I know of *NO* known way to synchronize the DMC timing with the CPU (not $4015.R/W, $4010.W, nor $4017.W), because even though the first DMC DMA fetch will occur 3 or 4 clocks after the write to $4015, the subsequent DMA cycles will occur whenever the hell they want to, within the DMC's timing base (it is more likely to be able to synchronize other NES hardware around the DMC timing via it's optional end-of-sample IRQ generation, but we can't do that with the non-soft resetable 2C02 PPU).
I don't think the Sprite Overflow flag is ever intended to be relied on and I don't think any commercial games used it for anything. Atleast, I don't remember ever implementing that flag in atleast one of my NES emulators and it never seemed to cause any problems. But it's been awhile.
MottZilla wrote:
I don't think the Sprite Overflow flag is ever intended to be relied on and I don't think any commercial games used it for anything. Atleast, I don't remember ever implementing that flag in atleast one of my NES emulators and it never seemed to cause any problems. But it's been awhile.
Well I guess that this is one PPU flag that is much adieu over nothing, then. It just really bugs me when a hardware designer implements a function that is absolutely useless to a programmer in nature. I must be sick to care for such a thing.
I don't know but maybe it's usage was maybe not meant for syncing to the PPU, but actually to know if there were sprites dropped.
That way sprite cycling could have been coded to happen only when it's necessary.
Don't forget the that Famicom was originally designed to run Donkey Kong and similar games.
Yeah, I always assumed it had a diagnostic function, not really something you would use as part of the runtime logic.
The problem is sprite cycling all the time can be done at pretty much no cpu cost so it makes no sense to even bother checking the flag at all.
Now sprite overflow drawing wise is relevant to emulate since games like Legend of Zelda use it to do masking on the vertical doorways apparently. I'm guessing at this time they had not started using the sprite masking technique used in Super Mario Bros 3 and other games to make a sprite appear behind part of the background but not all of the background.
The sprite overflow flag is just completely unusable, because it's not just prone to false negatives, but also false
positives. That alone is enough of a reason to not rely on it for anything, not even screen splits.
Even without the bug, your sprite routine would need to specifically avoid having more than 8 sprites on a given scanline, because that would trigger your screen split at a time you don't want it to be triggered.
And even then, you'd be wasting 8 perfectly good sprites. There are people starving in third world countries, you know.
Yes, it's an unfortunate hardware bug that renders the bit completely useless, but the NES/FC seemed to get along just fine anyway.
I'd highly recommend using sprite 0 for a screen split, anyway.
Drag wrote:
I'd highly recommend using sprite 0 for a screen split, anyway.
Sadly there are
conflicting statements on sprite 0 hit's purpose as well.
Full thread.
(As I've been waiting patiently for something like 13-14 years for an MMC3 devcart, re: IRQ counter, and am still waiting... ;) )
Dwedit wrote:
For a stable horizontal playfield split, use Sprite 0 hit (possibly combined with DMC IRQ).
Sprite 0 hits suck when you use scrolling. For completely arbitrary splits, it's impossible to always have solid pixels overlap the sprite unless you specifically erase/draw a solid tile at the proper NT location every frame.
Anyway, I have found a use for the sprite overflow flag in my game. In order to hide vertical scrolling glitches, I keep background rendering disabled for the first 16 scanlines. Since the background is blank, it would be weird to have sprites there, so I have to mask them too. However, I don't want the different dot crawl pattern that results from having both the BG and sprites disabled at the start of the frame, so I mask the sprites with 9 high priority sprites (1 through 9, 0 is free in case I want to use it for a split) using blank patterns.
Since those sprites are transparent and have priority over all others, no sprites will be visible up there. The sprite overflow flag, which will be set at the same time every frame, is used for detecting the end of VBlank, so that I can wait for the end of the blanked area and enable background rendering at the correct time.
Yeah, it's a bit hacky, but is a practical use of the flag.
EDIT: hehe koitsu already mentioned my rant about the usefulness of sprite 0 hits. =)
EDIT 2:
Big Nose Freaks Out (top right of the blanked area at the bottom) and
The Guardian Legend (top left of the status bar) are examples of games that have solid tiles following sprite 0, but that's at the bottom of the screen, most likely after the game logic is complete. Doing that near the middle of the screen wouldn't be so easy, and would probably require a DMC IRQ. Moving solid tile + sprite 0 hits + DMC IRQs = too much complexity for something that SHOULD be (and CAN be, with mappers) simple.
tokumaru wrote:
... and The Guardian Legend (top left of the status bar) ...
I always wondered what the hell that thing was. I always thought it was some sort of speed or scroll indicator. Should check that thing out in FCEUX sometime. It looks like the sprite tile index it uses for that thing is $FE.
tokumaru wrote:
Sprite 0 hits suck when you use scrolling. For completely arbitrary splits, it's impossible to always have solid pixels overlap the sprite unless you specifically erase/draw a solid tile at the proper NT location every frame.
Makes you wonder why Nintendo went with the whole sprite/background collision and didn't just trigger the flag when the first non transparent pixel of sprite 0 was drawn instead. There really is no reason to have it only happen when the background and sprite are non transparent unless the hardware implementation of this somehow wouldn't work the same.
I'm working on a zapper game that uses sprite 0 to determine the object pointed at since at minimum 8 scanlines inbetween them. It's not working, but my solution I decided to go with was to make the background always use solid colors for background. On places where you have to scroll you can always keep a line of solid pixels with good graphic design, although I agree it should have been as soon as a sprite 0 non-zero pixel was hit any background tile.
tokumaru wrote:
Sprite 0 hits suck when you use scrolling. For completely arbitrary splits, it's impossible to always have solid pixels overlap the sprite unless you specifically erase/draw a solid tile at the proper NT location every frame.
TMNT 1.
tokumaru wrote:
Since those sprites are transparent and have priority over all others, no sprites will be visible up there. The sprite overflow flag, which will be set at the same time every frame, is used for detecting the end of VBlank, so that I can wait for the end of the blanked area and enable background rendering at the correct time.
Ah, I see how your solution works now... if your initial sprite usage in the frame can guarantee that there will be no lines with 8 or more sprites on it, up until you deliberately intend to set the flag with 9 sprites all on 1 line, then this can be a practical solution to depend on the overflow flag's timing for, quite possibly for even establishing a top-screen status bar + horizontal split (provided less than 8 sprites/scanline (or no sprites at all) are used in the status bar). I suppose that overflow flag timing then just depends on which sprites you occupy in OAM to trip the flag (it just makes sense to always use 9 sequential sprite records to trip the overflow).
Of course, this makes using the overflow flag for timing out of the question for any scanlines following any playfield sprite activity that may introduce 8 or more sprites on one line, but just for the fact that you've given me a really neat idea that allows me to save the Sprite 0 hit for something later, really shows me how wrong I was to think the sprite overflow was useless. It may be a waste of 9 sprites, but ideally, those sprites could be used to display tiles like a power meter, or score digits (even those these sprites will hang down into the active part of the playfield- a small aesthetic price to pay, to get some use out of the rarely-used sprite overflow flag).
Very nice, tokumaru
MottZilla wrote:
Makes you wonder why Nintendo went with the whole sprite/background collision and didn't just trigger the flag when the first non transparent pixel of sprite 0 was drawn instead. There really is no reason to have it only happen when the background and sprite are non transparent unless the hardware implementation of this somehow wouldn't work the same.
Opinion: Nintendo was just taking what had already been developed by other companies, and just built on those designs to make their PPU.
Case example: The Colecovision video processor TMS9928A (a Texas Instruments device with official available documentation) is sort of like a stripped-down version of the 2C02 (with a 4 sprite per scanline limit, if you can believe it!), but it did have something in it's status register called the "Coincidence flag", which would simply be set if 2 sprites overlapped the same location on the screen.
Interestingly enough, the TMS9928A also had a 5th Sprite Flag, which would get set when the processor would find more than 4 sprites on one scanline (and apparently, the processor would actually load the sprite record index value of the 5th sprite that sets the sprite overflow flag into another status register- kinda interesting).
It is odd though, why Nintendo's PPU designers demanded a coincidence between sprite 0, and the playfield, because while it is inconvenient for an NES developer to make sure that there is a non-transparent PF pixel underneath sprite 0 (as has been brought up when working with bottom screen status bars), it is equally a pain-in-the-ass to deal with in accurate PPU emulation... Gotta love the NES, man!
It was also the fashion in arcade games of the time to have a top status bar.
Still other than being lazy/copying, I haven't heard any good reason why it shouldn't just be a Sprite Zero Pixel has been drawn flag. I know some emulators change behavior to that for Battletoads to avoid the possibility of a deadlock since the sprite 0 is usually just 1 pixel and under certain conditions without correct timing or ppu behavior you won't get a sprite hit and the game is stuck forever.
There is no back way to manually clear the sprite overflow flag, correct?
In addition to discussing the paradigm behind the PPU's Sprite 0 hit depending on the playfield pixels being solid, some attention has to be paid to the 2A03 audio hardware, most notably the sweep units.
If you look at the size of the silicon real-estate that the 2A03 consumes for it's audio unit compared to the 6502 section (thanks, Q), and THEN consider the fact that the sweep unit is only updated at a sluggish 240 times/sec (why not just use 6502 code calculations to update the wavelength register for a channel anyway, instead of using hardware to do this for a slow shift & add calc?), a serious question comes to mind:
** Why waste hardware resources on a chip to perform functions that can be efficiently implemented in software, with some thoughtful planning? (By the MMC5's time, Nintendo knew the sweep hardware was a waste of silicon, albeit some 8 years after the fact.) **
That answer has to be because hardware engineers, as innovative as they are, can not foresee how future software predicaments will challenge their idea of how current hardware implementations should be managed, which is at best, always based on at least 1 previous generation of implemented and exercised knowledge.
I've personally designed hardware projects that have ended up back at the drawing board, because of software requirements that I did not think of at the time of hardware design, and I doubt that this is an engineering mistake that is unique to a hobbyist or tinkerer.
MottZilla wrote:
Makes you wonder why Nintendo went with the whole sprite/background collision and didn't just trigger the flag when the first non transparent pixel of sprite 0 was drawn instead.
Yeah, it would have been much more useful that way.
MottZilla wrote:
There really is no reason to have it only happen when the background and sprite are non transparent unless the hardware implementation of this somehow wouldn't work the same.
Maybe the logic for the hit is hidden in the priority circuit and really depends on solid pixels in both layers... Maybe some day we'll find out (possibly with the decapping of the chip), but it won't change the way things are.
digilogistist wrote:
if your initial sprite usage in the frame can guarantee that there will be no lines with 8 or more sprites on it, up until you deliberately intend to set the flag with 9 sprites all on 1 line, then this can be a practical solution to depend on the overflow flag's timing for
Yup, that's right. The disadvantage (besides wasting 9 sprites - but I've seen even more being wasted) is that you might need to burn a few scanlines with timed code, but you can always minimize that by doing constant-timed tasks (reading the controllers, initializing variables, clearing arrays, etc) instead of just waiting. But like you said, if you use this for status bars, you even have sprite 0 free for effects further down the screen.
bunnyboy wrote:
There is no back way to manually clear the sprite overflow flag, correct?
As far as I know, only the end of VBlank can do it, just like it is with the sprite 0 hit flag.
You are right that Nintendo wasted silicon on things that can be done in software.
For the sweep unit I disagree, in fact it's useful if your sound engine updates at only 50/60Hz, having the sound sweep with a resolution of 196Hz or 240hz really helps for sound effects, and sometimes even for music.
It can also make sound engine's code smaller as you don't have to implement sweep in software.
What is completely useless is the length counters and decay envelopes. Both can be done in software easily, and the resolution of 50/60Hz is not really a problem.
The worse thing is that 6 years later when Nintendo released the GameBoy with a similar audio hardware in it, they made it impossible to do volume envelope entierely in software without reseting the phase of the square wave, therefore games have to use the hardware envelope. This was really another poor design choice.
On the other hand, there is many really good design choices Nintendo made. The controllers were very ergonomic for their time. The tiles, attributes and palette system is very clever and done in a way that is more efficient as for example the C64.
And even if the serial interface to communicate between the CPU and PPU via $2007 is confusing when you start programming the NES for the first time, it's in fact better than shared memory like on the C64, where they had to divide the cloth of both teh CPU and the video device to have them interleave access to RAM.