This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Revolutionarry method to reduce jittering

Revolutionarry method to reduce jittering
by on (#49479)
I've just made a demo that show a Fire Emblem screenshot WITHOUT using the MMC4 auto-CHR switch features. It does all switching manually with very very fine tuned timings.
The goal was to test mid-scanline CHR bankswitching. Unfortunately, since under normal conditions, there is a 7-cycle jittering (which means up to 21 (NTSC) or 23 (PAL) pixel jittering), which means 3 tiles should be "shared" by both pattern tables, which is a lot.

However, after having a few headaches I found an idea to reduce the jittering and make it happen on only one dozen of pixels (2 tiles), and that for both PAL and NTSC. The idea is that when the sprite zero hit happens at a fixed place, the amount of cycles between when the flag is clear and where it's set is constant. Then it's possible to count the number of times we have to poll $2002 in order to get the sprite hit with an index register (altough the loop takes 9 cycles intead of 7). Then by using this count value, it either is fixed (useless) or oscillate between 2 adjascent values. By placing the sprite zero in a fine tuned way so that it oscillate between 2 values at about 50%-50% probatilty, I'm able to check which one it is and waste a different amount of cycles on each case, halving the jittering.
Here you are the code for that :
Code:
-   bit $2002
   bvs -         ;Wait for the flag to be clear
   ldx #$00
-   bit $2002    ;Wait for the flag to be set, count itterations
   inx
   bvc -
   cpx #Value    ;You should check Nintendulator's debugger to get a reliable value here
   bcs +
   nop        ;This wastes 3 more cycles x >= value, reducting the jittering
   nop
+


Unfortunatlely this is all theorical, I can't test it on real hardware, not even the PAL version because one of my EEPROMs I used to use on my CNROM devcard seems to stopped working :cry:

I have uploaded the demo here, both PAL and NTSC versions available, for both MMC1 and CNROM (sorry no CNROM NTSC version right now). Someone please test them for me (if possible different people test PAL and NTSC version) and tell me the results.

Emulator reults so far :
Latest Nintendulator : Works perfect
Latest Nestopia : Works perfect
Nintendulator 0.950 : PAL version has glitches on the left (switching too early)
Nestopia 1.09 : both versions have a flickering tile after the switch not at the same place tough
FCEUltra (all versions) : PAL version perfect, NTSC has two flickering tiles after the switch
VitruaNES : Givies all kinds of terrible messy graphics
Nesticle : All bankswitching is ignored :wink:
Rew : The screen doesn't even look like it's supposed to

So on this one I can really not rely on emulators, even Nestopia and Nintendulator revisions disagree between them :(
Probably because I rely one the exact $2002 poll number which makes most emulator breaks.

PS : Before anyone ask, no, I'm NOT preparing a Fire Emblem mapper hack, I was just experiencing midscanline CHR bankswitching

by on (#49480)
I tried it on the powerpak. The CNROM version has all sorts of graphical glitches. MMC1 Works, But there is a little glitch around the 1 next to Marth's Quest. If you hit reset however there is all sorts of glitching.

by on (#49481)
Marble Madness just used timed code starting from NMI to switch between the left and right pattern table while displaying the "Adding Time for Beginner Race" prompts. No sprite hit there, except at the bottom to turn off the screen early.

by on (#49489)
Super-Hampster wrote:
I tried it on the powerpak. The CNROM version has all sorts of graphical glitches. MMC1 Works, But there is a little glitch around the 1 next to Marth's Quest. If you hit reset however there is all sorts of glitching.

Well, have you a PAL or NTSC NES ? I assume you have NTSC, which would make the CNROM version fail because it's supposed to be for PAL.

Because the '1' glitches, that's not how the latest Nestopia and Nintendulator behaves ! Who it's the first time I ever see this ! Then it would be Nestopia 1.09 the only one who is right on this one I think. Weird.

Someone could please test the PAL version on a PAL NES please ? I would do it myself if my second EEPROM worked :(

@dwedit : Yes, this could also reduce jittering depnding on what code is executed before the interrupt. If a random code is executed, there is also a 7-cycle jitter (because the longest instruction available is 7-cycle long). But if you are in a standard wait loop there would be down to 3-cycle jutter. I tried that, but it looked to jitter as much as the sprite-zero mechod. Maybe I should insist on doing that since it would probably work in more emus.

by on (#49531)
Ok, DWedit were completely right, it was supid doing it with a sprite-zero hit with 7 cycles jitter when doing it inside the NMI routine gives me typically only 3 cycles jitter, which is ridiculously better (the reason it didn't work for me before is because I was doing something stupid).
Yet my method to deduce jittering with sprite zero hits may interest some people in case where it can't be avoided to use sprite zero hit (for many reasons).

So I updated the demo here, again there is a 2-tile band that must be shared between both pattern tables on left and on the right of the boxes. And it works under much more emulators !

Emulator results so far :
Nintendulator (all versions) : Perfect
Nestopia (all versions) : Perfect
FCEUltra (all versionos) : Perfect
Virtua NES (after setting render method to "tile" mode) : Glitches on the tile before the status bar on NTSC version, crap graphics on PAL version
RockNES : Glitches on the tile before the status bar on NTSC version (how do you make RockNES emulate a PAL NES ?)
Nesticle : All CHR bankswitching ignored :wink:
Rew : Crap flickering graphics

If someone could plese test if for me on the real HW it would be cool (at least NTSC because I can't test it, and PAL too if possible until I can again).

by on (#49550)
- RockNES has no PAL mode support.

by on (#49559)
Bregalad wrote:
again there is a 2-tile band that must be shared between both pattern tables on left and on the right of the boxes. And it works under much more emulators !


That's a pretty cool trick. 2 tiles is a fine size for a window border, and that's an easy trade-off for being able to show any CHR tile.

Actually something like that was one of the 'modes' I had in mind for Squeedo. The PIC had a counter for NES CPU cycles, and also controlled the CHR banking. So theoretically, the NES would give the PIC a 'timing script' of when to change banks. However I hadn't seriously considered mid-scanline banking, but that would be far more interesting if it could be automated. Jitter would be a problem still (it would depend on the NES's program's NMI routine). The PIC would have the raw NES clock available to it, if it could "lock in" to the right value somehow.

Also the sprite #0 jitter-reducing trick is very cool! This could free up more cycles during hblank. Which is pretty big deal, because there aren't very many of them. Sprite #0 would be better than NMI timing if it's not a full-screen effect (or is further down on the screen or something).

Also I wouldn't worry about the emulators. Look at all the references to people working their emulators around games like Marble Madness and other stuff by Rare. If it works on the system and breaks a lot of emus, that is even better.

by on (#49572)
Quote:
Actually something like that was one of the 'modes' I had in mind for Squeedo. The PIC had a counter for NES CPU cycles, and also controlled the CHR banking. So theoretically, the NES would give the PIC a 'timing script' of when to change banks. However I hadn't seriously considered mid-scanline banking, but that would be far more interesting if it could be automated.

Sounds awesome. Altough the MMC2 and MMC4 already does auto-midscanline bankswitching, that would be a more flexible way to do it (without forcing the user to use tiles $fd and $fe on split points).
Quote:
That's a pretty cool trick. 2 tiles is a fine size for a window border, and that's an easy trade-off for being able to show any CHR tile.

Definitely. The first/last column is the border of the window, so it's only a real deal for the second/second-last row. By the way anyone have an indea why Dragon Quest and Fire Emblem games always have those stars at the begining of a paragraph ? Is it some japan culture trick ?

Quote:


Also the sprite #0 jitter-reducing trick is very cool! This could free up more cycles during hblank. Which is pretty big deal, because there aren't very many of them. Sprite #0 would be better than NMI timing if it's not a full-screen effect (or is further down on the screen or something).

Well, in fact it reduces jittering from 7 cycles to 4 cycles in the best case, but you need to execute the code before the sprite flag is clear, so before the start of the frame which makes it stupid since doing it from NMI directly directly gives me 3 cycle jitter (better) ! This could be usefull if you really can't have your NMI routine taking a fixed amount of cycles for some reason.

Quote:
Also I wouldn't worry about the emulators. Look at all the references to people working their emulators around games like Marble Madness and other stuff by Rare. If it works on the system and breaks a lot of emus, that is even better.

Well, I still don't know how well works on hardware :cry: