that's it then, the final piece.
You can play games, record scenes, and boot games back up with the
recorded map.
It's not perfect, _far from it_, but it works!
There is still a lot of work to do, improving heuristics and such,
but I think wideNES is at a point where it can be merged into
master and shown off a bit :)
exciting!
Perceptual hashing... that's the cool shit.
I mean, my "advanced" perceptual hashing algorithm is really dumb
right-now, literally just taking a sum of all pixels in the frame,
and yet, it's good enough to detect when a _bunch_ of pixel-values
change from frame-to-frame. I bet that with a bit more tweaking,
like normalizing the frame wrt. the palette, I can get some even
better results.
I also have a "true" hashing implementation, where each frame gets
a unique hash. It seems to be realtively collision-free. That said,
there are times where there are collisions, namely in Metroid,
where the game likes to reuse screens. I'll have to figure out how
to deal with that...
So, what's the next step?
Whenever a scene changes, take the hash of the new screen, and see
if it matches up with anything we've seen before.
That way, we can have "re-enterant" scenes, which is a key to being
able to save/load tiles!
didn't think i'd be able to pull it off, but Zelda seems to scroll
fine now! All I needed to do was sniff the PPUADDR register, since
after all, PPUSCROLL and PPUADDR both point to PPU t/v anyways...
I also bunched-up the heauristics a bit better, hopefully making
the code a bit nicer.
before showing off my work, the big thing that needs to get done is
scene detection. Yeah, heuristics are cool, and fun to implement,
but I can do that later. What I _should_ focus on is getting scene-
detection working, and afterwards, saving and loading, since that's
the killer feature (imo)
It's going to be tricky, but i've been reading-up on perceptual
hashes, so that might be useful?
Alternatively, I could sniff what games tend to write to the PPU
during "scene transitions" and see if there is anything I can use
to fingerprint scenes...
If a human can figure out which parts of a screen to chop, why
can't wideNES do it automatically? Well, it can! sort of...
I implemented a couple of heuristics that use the state of the PPU
and the Mapper to "guess" what padding values make sense.
For now, I only have 2 implemented:
1) Check if the bgr-mask column is enbled on PPUMASK
- if so, add 8px of padding to the left of the screen
- many games that mask the left also have artifacting on the
right, so mask off 8px on the right too.
2) Check what scanline the Mapper IRQs happened on
- mask-off the rest of the screen
- many games use the Mapper IRQ for status-bars (smb3, kirby)
Now, these are not perfect heuristics by any means, with exceptions
rampant. eg: Lode Runner doesn't have any graphical artifacting on
the right of the screen. eg2: MegaMan IV uses the IRQ for different
reasons, unrelated to status-bars.
Nevertheless, they do a decent job with many games, smb3 and MC Kids
work flawlessly. Moreover, Metroid and Super Mario Bros work great
too, automatically having the entire screen captured (no padding)
While implemeting this feature, I decided to cleanup how I was
reading the NES's state, and implemented a basic Callback system,
enabling arbitrary methods to hook into important parts of the NES
lifecycle. eg: I added callbacks whenever a mapper fires an IRQ,
and a mapper whenever a PPU frame finished drawing (scanline 240)
This had the happy side-effect of fixing my smearing issues, as it
makes a lot more sense to sample the NES's state _before_ the NMI
handler happens, as that state the one that resulted in the current
frame! Just like that, every game I tested worked flawlessly, no
smearing to be found!
Also, this lays a much more solid groundwork for implementing a
proper debugger! It should be easy to take the nastyness that is
ppu_debug.cc and extract it into it's own GUI module! That way,
there will be _no_ state of SDL in ANESE core!
I still haven't figured out the smearing issue, but I _did_ figure
out how to greatly-improve compatibility with many titles!
I added the ability to "pad" the screen, cutting-off any artifacts
at the edge. This means that with a bit of tweaking, games like
SMB3 and MC Kids work near flawlessly!
It _should_ be possible to guess "good" padding values for games by
using some heuristic that relies on current mirroring mode, scroll
direction, and if the PPUMASK is on...
I also updated the README some more, putting a "teaser" for wideNES
on the main page, but splitting off the details into it's own page.