There are many, many classical effects on raster hardware which are accomplished by changing registers within the horizontal blanking period... copper bars, mode 7, certain paralax scrolling. When you're on a resource limited system it becomes an art to get the most out of the platform. Look at the difference between Mario 64 and Conker's Bad Fur Day... or Genji: Days of the Blade (PS3) vs Persona 5 (PS3) Even with modern consoles, there is a marked improvement in the apparent visual quality over the lifetime of the device, as developers learn how to squeeze more and more out of the platform.
https://en.wikipedia.org/wiki/Undefined_behavior
This case appears to be "undocumented scenario" or "unsupported use-case", though.
If you want an example of something that’s really an unsupported use case, consider mid-frame palette changes—in order to do this, you actually have to disable and re-enable rasterization during the horizontal blanking interval. It works, but it is difficult to get right and the PPU is clearly not designed with this in mind.
Short of having an actual spec in hand, it would appear that mid-frame scroll register updates were entirely normal and an intended way to use the device, based on the evidence (no other reason for sprite zero check, lots of first-party titles using this feature, other mid-frame updates are much more difficult).
It could be "defined by e-mail".
That's a part of it, to be sure, but another dynamic is that developers have to squeeze more out of the system. Dropping old techniques on new hardware will probably give you a game that looks "better" than what's already out. Once everyone has done that, to look "better" you need something new other than hardware.
- implementation-defined: Not defined by the standard, but implementations must choose a consistent behavior and document it (e.g. what's shifted in when right-shifting signed integer types)
- unspecified: Not defined by the standard; implementations must choose some way of addressing the situation, but need not document it (e.g. the order in which function arguments are evaluated)
- undefined: Entirely outside the scope of the standard; implementations may assume that such situations never occur, and need not have any sensible or consistent behavior (e.g. dereferencing NULL)
In that taxonomy, I think this is much closer to "unspecified" than "undefined". The latter is usually used in scarier contexts like random memory corruption or crashes, not consistent behaviors that rely on deliberate implementation choices as we see here.
Lots of games used funky scrolling mechanics, typically to create status bars, but of all the different games I tested with, TLOZ was by-far the weirdest, requiring an entire special case to get working!
I don't have any screenshots of my own, but some japanese website recently covered wideNES, posting screenshots of it working with the original Legent of Zelda.[2]
[1] http://prilik.com/blog/2018/08/24/wideNES.html
[2] https://emulog.net/fc-nes-emulator-anese-how-to-use-widenes/
You could probably run an async loop which slices up painted frames and compares hashes of the slices to find identical slices to anchor and stitch similar frames together, still maintaining separate layers in case a better match is found later on. Something like that should solve for games like SMB.
Reading articles like this, or about the Atari and how the code would double as a sprite in pac-man, or how 3D was rendered in Wolfenstein, makes me think one had to be much more clever back then.
The 6502 has a few "undocumented" instructions due the fact that if you have certain on/off input pin set, you're actually crossing gates used for multiple instructions. These may crash the chip or do non-useful things, but a few do something useful in vary specific circumstances. The trick to developing on these old systems is to experiment with the chips to understand what the system does in various circumstances.
What I liked about that time was that it was possible to truly understand everything about a system because nothing is hidden from you by software drivers. The were good times.
Want to understand a tiny chunk of that complexity yourself? Check out how the addition operation overflow flag is implemented in silicon on the 6502: http://www.righto.com/2013/01/a-small-part-of-6502-chip-expl...
See
Which was also true back then. Not all programmers back then had to derive arcanely clever tricks to get their job done.
There's also a part of it that is underappreciated, which is that sometimes the cool effect wasn't necessarily an original design goal, but instead was sometimes something that was stumbled upon one way or another, and then it was having that little trick in one's pocket which informed how the design would be.
I love reading about how programmers pulled off these tricks on such limited hardware, hopefully there are some notes about it somewhere on the internet.
Try programming microcontrollers and you can enjoy that feeling today! Get comfy with the relatively powerful ARM Cortex-M variants, which typically sports 10s of kB of RAM. Then if you feel frisky, try your hand at some 8-bit uC's with less than 64 bytes of RAM (spend your bits wisely).
Maybe it's finding creative solutions, but today there is a lot to know.
https://www.vice.com/amp/en_us/article/9a3b8y/why-zelda-was-...
And that's just the NES devices! The Famicoms were different again, there were at least two licensed clones, and dozens of unlicensed clones (if you, eg, wanted your game to sell in Russia, you'd care about being compatible with the Dendy as well as the genuine NES).
https://www.youtube.com/channel/UCwRqWnW5ZkVaP_lZF7caZ-g/vid...
See http://bootgod.dyndns.org:7777/ for a database of the hardware inside each cartridge.
Paperboy comes to mind. It's smooth and looks good without any noticable glitching, and without using custom chips, too. Not sure how they did it.
Edit: as sibling comment noted, Paperboy does have custom logic on the cartridge, a 74HC161 4-bit counter. I think this is just used to switch between CHR banks.
Nope. Paperboy uses a CNROM, which is basically an MMC3. Maybe they're doing some clever edge-replacement stuff on the mirrored table, like SMB3 does with the same hardware? But you can see glitching when SMB3 does it.
(edit: my sibling post answers it. That's slick.)
Wow, this is chock-full of content. I wish there was one for the Sega Master System too
Off-topic, but thought I'd link to this very fun comparison of various games across the two platforms: https://huguesjohnson.com/features/nes-vs-sms/
SMB1 actually also does not use the sprite zero split technique because it never scrolls vertically. Its status bar is just a bunch of fixed background tiles.
Regarding SMB1, I'm quite sure it uses the sprite 0 thing to keep the status bar stationary while the level scrolls smoothly beneath it by setting the scroll register only after when the status bar is done drawing. See more thorough description here: https://retrocomputing.stackexchange.com/questions/1898/how-...
Also, Y-scrolling wasn't completely figured out until late in the NES's life. The register writes needed to do so are very strange, and Zelda certainly doesn't do it correctly!
Mode X or Q reminds me of the amazing Mode 7 SNES graphics used to great smooth effect in F-Zero and many other titles.
"The system was designed to accommodate the ongoing development of a variety of enhancement chips integrated in game cartridges to be competitive into the next generation."
Also isn't vertical split quite common? I would assume this is something the hardware designera thought of, not a game company figuring it out. They even put stuff like sprite 0 hit bit for this kind of tricks
Just doing it now, converting all the animations to WebP makes it 1.6MB. and it works in all current browsers.