Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce flicker in UI #11

Open
jakerr opened this issue Feb 7, 2015 · 3 comments
Open

Reduce flicker in UI #11

jakerr opened this issue Feb 7, 2015 · 3 comments

Comments

@jakerr
Copy link
Member

jakerr commented Feb 7, 2015

Problem

Chip-8 emulation has inherent flicker problems because the DRW command is dual purpose. Not only is it used to draw pixels but also to un-draw them. So to move a sprite first it is erased, and then drawn in it's new position. If the emulated screen is redrawn during the erase and redraw the sprite will momentarily disappear. More discussion on the topic here Flicker - Chip8 Wiki

Possible solution

One potential solution is to expose an abstraction of the screen, rather than its raw bytes, when vm.screen_rows() is called.

In the vm, at execution of the Draw op, there would be some logic watching for draws that result in only erase of pixels. The pixels that were erased would be tagged with a deadline to be erased later, something like 10 or 20 emulated cycles later. Until the deadline the higher-level vm.screen_rows() would continue to return those pixels as lit. Upon either the deadline being reached, or another Draw command being executed (one which isn't another un-draw), the pixels would finally reflect as un-lit in the higher layer.

This solution shouldn't effect the interpreter accuracy in any way, as all of the memory that could be inspected by the executing Ops would be consistent. It only affects the display layer.

The behavior should be made optional and switchable at runtime.

@robo9k
Copy link

robo9k commented Feb 7, 2015

I have no experience with 2d graphics and their interaction with a game's event/draw loop.

The deadline sounds like something that would depend on the individual code of a ROM? If so, it should be configurable (e.g. assign two keys to increase/decrease it at runtime).

The Chip8 wiki also mentions a fade screen solution. I could imagine having a last time flipped associated with each pixel, so it could be drawn with some opacity instead of being binary lit/un-lit. I don't really know how this would look like in practice (the fade factor of time * opacity might also need configuration) or if it is any better than your first proposed solution.

@jakerr
Copy link
Member Author

jakerr commented Feb 7, 2015

Yeah, the "correct" deadline, would depend on the ROM's code, however I suspect that we could improve the flicker with a naive deadline since most sprite moves will be a simple: erase, and redraw. Those are represented by only a few ops such as

DRW v0, v1 # Erase
ADD v0, 1  # Increment X by 1  <- Game loop drawing in here will cause flicker
ADD v1, 1  # Increment Y by 1  <- ...
DRW v0, v1 # Draw again        <- If deadline hasn't expired, we'll commit the previous Erase and clear the deadline.

With this proposal I actually wouldn't expect to hit the deadline in most cases, the next draw call short circuit the deadline and commit the erase before adding new pixels, clearing the deadline. The deadline is more there to not leave erased pixels on the screen when a program reaches a steady state where it's not drawing anything new.

I think it would be fun to have a few of these modes and let them be configurable as you suggested. I think the last time flipped solution and deadline one can use the same data layout for storing that meta information and just treat it differently.

I'll probably give it a try soon.

@robo9k
Copy link

robo9k commented Feb 7, 2015

I think it's best to go ahead and try how well these possible solutions work with a few ROMs in practice.
Looking forward for your first try! 🎦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants