It is currently Wed Dec 13, 2017 7:47 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Jun 28, 2016 10:18 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1868
Location: DIGDUG
I made this today. I thought I would share it, because I haven't seen any such code anywhere.

Basically, I'm creating a glitch by doing a X/Y scroll split mid-screen. And, I'm using a series of sprites to cover them.

At startup, they are not in place. Press 'Down' for a little bit to line them up.

Works on real hardware.

If you're wondering what the grey squares are, I'm testing the alignment of the second nametable post split, and making sure there is no jitter.

(file removed, see later post for newer version).

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Last edited by dougeff on Wed Jun 29, 2016 8:15 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 10:59 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
Instead of covering it with sprites, couldn't you just finish the scroll split within hblank and not have any visible glitch?

I mean, I know commercial-era games didn't manage that, but we have cycle accurate emulators now, and it can be done.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 12:19 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
rainwarrior wrote:
Instead of covering it with sprites, couldn't you just finish the scroll split within hblank and not have any visible glitch?

I second this. Why waste sprites hiding something that can be completely avoided in the first place? A full scroll change requires only 4 PPU writes ($2006, $2005, $2005, $2006), out of which only the last 2 need to happen during hblank so there are no glitches. That's less then 8 cycles you have to fit in a ~21 cycle window, so there's A LOT of wiggle room to get the timing right.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 1:13 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6519
Location: Seattle
tokumaru wrote:
less then 8 cycles you have to fit in a ~21 cycle window, so there's A LOT of wiggle room to get the timing right.
Specifically, 5 cycles. (Write Load_Opcode Load_Lo Load_Hi Write).

I guess on 2A07+2C07 it's probably a 19 cycle window ((64 pixels - 2 for jitter) ÷3.2, round down). Still, 14 cycles of slop means you don't need to do anything special, ordinary IRQ or sprite 0 polling is precise enough.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 1:22 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
lidnariq wrote:
Specifically, 5 cycles. (Write Load_Opcode Load_Lo Load_Hi Write).

Yeah, only the last cycle of the first write has to land on hblank, because that's when the write effectively happens.

Quote:
I guess on 2A07+2C07 it's probably a 19 cycle window ((64 pixels - 2 for jitter) ÷3.2, round down).

Oh yeah, I wasn't considering PAL consoles, sorry.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 3:48 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1868
Location: DIGDUG
What if you were using a mapper without scanline counter, and you were using the sprite zero hit elsewhere, and you couldn't be certain of exactly where the hblank was...and, you could only narrow it down to about a 16 pixel window. Glitch.

Then sprites can cover the glitch.

The main thing I'm testing here is..."CAN you cover a glitch with sprites?" And the anwer is yes.

I feel like this is also a good test of emulators of PPU behavior, since half of the emulators I tested didn't look the same as real NES.

I might try again, see if I can hide it in the hblank (again, without a MMC3 scanline counter). I haven't had great success with that, yet.

The idea is that, in a game, you should be able to do logic before and after the split, so, perfectly timed code only helps in a demo like this.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Last edited by dougeff on Tue Jun 28, 2016 4:25 pm, edited 2 times in total.

Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 4:03 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19342
Location: NE Indiana, USA (NTSC)
You may also get more jitter if you attempt more than one split using a CPU cycle counting interval timer such as that in the FME-7. There's a delay of 1 to 7 cycles after /IRQ goes low to complete the processing of the current instruction, and unless you use the mod 256 trick (keeping the cycle counter going while writing only the high byte), this variability compounds.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 5:33 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
dougeff wrote:
What if you were using a mapper without scanline counter, and you were using the sprite zero hit elsewhere, and you couldn't be certain of exactly where the hblank was...

But if you were this lost, you'd need a lot of sprites to be absolute sure the glitch would be covered, wouldn't you?

Quote:
The main thing I'm testing here is..."CAN you cover a glitch with sprites?" And the anwer is yes.

Well, yeah... but is it practical? If the area affected by the glitch isn't just a flat color, you'll still be losing details by covering it with a flat line. You also have to make sure that you have the necessary color available somewhere in your sprite palettes. Also, depending on how large the area affected by the glitch is, the sprites you use could greatly increase sprite flickering near the split.

Quote:
I feel like this is also a good test of emulators of PPU behavior, since half of the emulators I tested didn't look the same as real NES.

Yeah, every time I tried to align things to hblank, emulators would disagree. Nestopia used to give me the most consistent results compared to the real hardware, but it's been a while since I needed this kind of precise timing.

Quote:
I might try again, see if I can hide it in the hblank (again, without a MMC3 scanline counter). I haven't had great success with that, yet.

Make sure to do most of the work beforehand, and have the values for the last 2 writes ready and loaded into different registers so that the last 2 writes can be performed as quickly as possible. Then you just move the whole code using NOPs until there are no more glitches. I used this code in the past, and once it was properly aligned to hblank there were no glitches at all.

Quote:
The idea is that, in a game, you should be able to do logic before and after the split, so, perfectly timed code only helps in a demo like this.

Again, if you're that lost, it's not a few sprites that will give you a steady split. If your timing is really off you can even end up with the part after the split jumping up and down, in case you can't guarantee that the split happens always before or always after the PPU automatically increments the vertical scroll.

If you don't have mapper IRQs, there are 3 basic ways to time raster effects: sprite 0 hits, sprite overflow, and timed code. There's also the DMC IRQ, but that's a totally different beast. Anyway, none of these 3 synchronization techniques introduces enough jitter to make landing a 5-cycle sequence in a 19-cycle window impossible. They can add a delay of 7 or 8 cycles, which still leaves you with 6 or 7 cycles of padding.

What other synchronization techniques are you thinking of that are not precise enough to allow syncing with hblank but will still result in a predictable amount of glitches that can be covered with sprites?


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 6:14 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1868
Location: DIGDUG
I'm actually working on a project that has a HUD at the bottom (sometimes)... a bit like Dizzy.

Regular game play for the first 180 -ish lines. Sprite zero hit, rendering off for about 8 lines, X and Y scroll changed, rendering back on...HUD displayed for 32 lines, then rendering off to the bottom of the screen.

Anyway, I was getting glitches, and jitter, and I was testing if I can cover the glitches with sprites.

BTW, did you notice Dizzy has jitter and glitches? Maybe that's just in the YouTube video I watched...I've never played it on a real NES.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 7:04 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
dougeff wrote:
Regular game play for the first 180 -ish lines. Sprite zero hit

OK...

Quote:
rendering off for about 8 lines

Is this for writing something to VRAM? If you can make this take a constant amount of time, you won't lose any precision after the sprite 0 hit.

Quote:
X and Y scroll changed, rendering back on...HUD displayed for 32 lines

If you have rendering disabled, you can actually change the scroll at any time, and the only thing that will matter is when you turn rendering on (i.e. 1 cycle in a 19-cycle window).

Quote:
then rendering off to the bottom of the screen.

This should be easy if the HUD is followed by at least one blank scanline, so you can turn rendering off at any point in that scanline.

Quote:
BTW, did you notice Dizzy has jitter and glitches?

I've never played any Dizzy games, but I'm not surprised. Many commercial games have split glitches... The worst offender IMO is Mega Man 3, which mangles over half of the scanline every time there's a split, in addition to shifting the background up. Look at what happens when the game starts splitting the screen (right before the boss shows up): https://youtu.be/M1UkE9h2zJg?t=58m56s


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 7:52 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1868
Location: DIGDUG
Quote:
Is this for writing something to VRAM?


It's just a way to get 8 lines of black without having to put them somewhere in the VRAM.

The same reason I'm turning rendering off just below the HUD, to make the rest of the scanlines black.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 8:54 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5896
Location: Canada
I was just suggesting the hblank thing in case you hadn't considered it, not trying to argue you out of the sprites approach.

The other alternative for covering a jittery split is to just have a solid colour on the pixels that will appear in the artifact area (part of both lines involved). This is what most commercial-era games that actually have clean splits did. Battletoads, as always, has some good examples, like its Volkmire's Inferno stage.

I use sprites to cover some background problems myself (e.g. annoying attribute palette limitations), though I try not to do it often because I don't want the background to be subject to sprite flicker; it sends a false signal that it might be an "object". To cover jitter you need three or four sprites on the same horizontal line, which really makes flicker hard to avoid. Depends on where your characters can go onscreen, of course, but might be an undesirable effect.

You might consider vertical displacement on the covering sprites to mitigate this; only one line from the sprite needs to cover the jitter region, so it can be the top of one and the bottom of another, etc.


As far as robustness among emulators, if you do what commercial-era games did (i.e. split during the visible scanline) you'll get the most consistent results. If you split in hblank, I think some emulators will end up off by one line, unfortunately. You might find a timing that works on most popular emulators, if you're lucky, but I don't have any good advice on this front.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 9:49 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1868
Location: DIGDUG
I was able to make a version without any sprites that is glitch free, using tokumaru's suggesion of writing the first $2006, $2005 lines first, during rendering...then the final $2005, $2006 write during Hblank. And, avoiding any writes to $2001.


I also made a change to the actual project I'm working on that also has no glitches (and does involve $2001 writes, as I described). I didn't test it on real NES yet, but works in emulators.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 10:42 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10164
Location: Rio de Janeiro - Brazil
dougeff wrote:
I was able to make a version without any sprites that is glitch free

Cool!

Quote:
I also made a change to the actual project I'm working on that also has no glitches (and does involve $2001 writes, as I described).

For normal scroll updates done during vblank, it's still better to use $2005 and $2001. when you need to change only the horizontal scroll mid-screen, $2005 and $2001 work just fine too. If you need to freely modify the vertical scroll though, then the $2006/5/5/6 combo is the best way.

Quote:
I didn't test it on real NES yet, but works in emulators.

Hopefully you'll be able to make it work consistently across most emulators and the real console.


Top
 Profile  
 
PostPosted: Tue Jun 28, 2016 11:39 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
dougeff wrote:
I also made a change to the actual project I'm working on that also has no glitches (and does involve $2001 writes, as I described). I didn't test it on real NES yet, but works in emulators.

Let me know if you need someone to test it on actual hardware.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group