Fix sprite clipping, add display wait, and whole-pixel LO-RES scrolling - #29
Open
HarianthK wants to merge 1 commit into
Open
Fix sprite clipping, add display wait, and whole-pixel LO-RES scrolling#29HarianthK wants to merge 1 commit into
HarianthK wants to merge 1 commit into
Conversation
…RES when asked Three things from kurtjd#22, plus a fourth found on the way. Clipping. A sprite drawn past the edge of the screen never appeared, because the start position was only wrapped when clipping was off. The start always wraps; clipping only decides what happens to the part of the sprite that hangs over the edge. Separately, the S-CHIP 1.1 rule that counts rows falling off the bottom of the screen into VF was applied to every HI-RES draw, so a sprite well inside the screen added a negative number to VF. It now only counts rows that actually fall off. Display wait. The original hardware could only draw once per screen refresh, and programs written for it rely on that to pace themselves. A new quirk, off in legacy mode and toggled with -w, makes a second draw in the same frame run again on the next one. The timers now count down on one free-running tick which also releases the waiting draw, because a program timing its frames against the delay timer has to see them agree. Before, the delay timer only accumulated time while it was running, so its phase against the refresh depended on when it was set. Scrolling. The buffer is always 128x64, and in LO-RES each pixel is two cells of it, so scrolling by n moved half a LO-RES pixel per unit. That is what the HP48 did and it is kept as the default. A new quirk, toggled with -g and off in XO-CHIP mode, scrolls whole LO-RES pixels the way modern S-CHIP and XO-CHIP interpreters do. Also, -9 was never in the getopt string, so that flag was rejected, and the test's quirk initialiser was one entry short. With these the quirks test passes every row in all four of its modes (CHIP-8, S-CHIP modern, S-CHIP legacy, XO-CHIP), the scrolling test shows the complete picture on all five of its paths, and the opcode, flags and keypad tests are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This covers the three items in #22, and a fourth thing I ran into on the way.
Clipping
chip8_drawonly wrapped the start position when clipping was off (and that block was commented out anyway). So in S-CHIP mode a sprite drawn at, say, (110, 50) never appeared at all. The start position always wraps around the screen; the clipping quirk only decides what happens to the part that hangs over the edge. That is theERR2the quirks test was showing.There was a second problem in HI-RES. The S-CHIP 1.1 rule that adds the number of rows falling off the bottom of the screen to
VFwas applied to every HI-RES draw asVF += (y + rows) - 63, which goes negative for any sprite that does not reach the bottom and wrapsVFto garbage. That is why the HI-RES half of the check disagreed with the LO-RES half and the row saidERR3. It now only counts rows that actually fall off.Display wait
The original hardware could only draw one sprite per screen refresh, and programs written for it use that to pace themselves. This adds quirk 10, on by default (no wait, as S-CHIP), off in legacy mode, and toggled with
-w. With it off, a secondDxynin the same frame stepsPCback and runs again after the next tick.Getting this to pass the test needed one more change. The delay timer only accumulated time while it was running, so its tick phase depended on when
DTwas last set, while the refresh tick had a fixed phase. A program that draws once per frame and counts frames with the delay timer would see them agree or disagree by luck. The timers now count down on one free-running tick, which is also what releases the waiting draw. That is how the original interrupt worked, and it makes the result the same at any CPU speed (I checked 1000, 1800, 3000, 10000 and 50000 Hz).LO-RES scrolling
The buffer is always 128x64 and a LO-RES pixel is two cells of it, so scrolling by
nmoved half a LO-RES pixel per unit. That is what the HP48 did and the scrolling test's "legacy" path already passed. Modern S-CHIP interpreters and XO-CHIP scroll whole pixels, so this adds quirk 11, on by default, off in XO-CHIP mode, and toggled with-g, which doubles the distance in LO-RES.Also
-9was never in thegetoptstring, so that flag was rejected even though there was a case for it. And the quirk initialiser intests/test_opcodes.chad nine entries, which did not matter until the array grew.How I checked
I compiled
src/chip8.cinto a small headless harness (no SDL,__LIBRETRO__defined for deterministic timing) and ran the test suite ROMs through it, comparing against an interpreter that passes the suite.Quirks test, all six rows, going through the menus:
-las CHIP-8-was S-CHIP legacy-xas XO-CHIPScrolling test: S-CHIP legacy LO-RES already showed the complete picture; S-CHIP modern LO-RES (with
-g) and XO-CHIP LO-RES now do too, and both HI-RES paths are unchanged. The opcode, flags and keypad tests are pixel for pixel unchanged in every mode.tests/test_opcodes.cpasses, andmain.candlibretro.ccompile clean with-Wall -Wextra(the one sign-compare warning inlibretro.cwas already there). I could not link the full SDL app on this machine, so the front end has only been compiled, not run.One thing to be aware of:
chip8_dumpwrites the raw struct, and the struct has changed (two more quirks, a new flag, and the two timer accumulators merged into one), so old dump files will not load.