Clean screen split without blank area in-between?

You can talk about almost anything that you want to on this board.

Moderator: Moderators

Post Reply
NewRisingSun
Posts: 1510
Joined: Thu May 19, 2005 11:30 am

Clean screen split without blank area in-between?

Post by NewRisingSun »

It seems that when doing a split screen on the NES, for example to show a status bar, one must either allow for several blank lines in-between (R.C. Pro-Am, many others), or accept graphical corruption in the first line after the split (Ys, Conquest of the Crystal Palace). Or is there a game that has a clean screen split without a blank area in-between? Is it even possible in theory, assuming the split requires at least a scroll register write and a CHR ROM bank switch?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Clean screen split without blank area in-between?

Post by tokumaru »

It's perfectly possible to have a clean scroll split from one scanline to the next without any glitches whatsoever. The trick is to use the $2006/5/5/6 method and do most of the work during the scanline, leaving only the last 2 register writes to be done during hblank, because those are the ones that can cause graphical corruption.

As for a CHR-ROM bank switch, that'll depend on the mapper and how many register writes are necessary to switch the amount of tiles you need. There are only 22 or so CPU cycles in hblank before the tiles for the next scanline start being fetched, so if you can cram the mapper write(s) into what's left of those 22 cycles after the scroll writes, then yeah, a clean split is possible.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Clean screen split without blank area in-between?

Post by rainwarrior »

Yes, if you do the split during the horizontal blank between lines, there won't be a visible glitch.

Most commercial era games failed to do this, perhaps not knowing that it was an option. Crystalis has very notably good splits, I think. In addition to the obvious split for the status bar at the bottom, the field actually splits in the middle of the screen to accommodate a lack of nametable wrapping!

Well, at least the field split is in hblank and seamless looking. I guess the status bar has a glitchy line above it. :S
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Clean screen split without blank area in-between?

Post by tepples »

Unless I did something very wrong, the splits in The Curse of Possum Hollow are clean.

You use the $2006-$2005-$2005-$2006 write pattern for the scroll and whatever your particular mapper requires for the background pattern table change. The last two writes of the scroll pattern have to be within the first 64 pixels of horizontal blanking, as they set the fine horizontal scroll and reload the nametable VRAM address. The write to change the background pattern table can be slightly earlier, as the PPU never does anything with the 34th pattern table's tile.

For more specific advice, please answer the following questions:
  1. Status bar at top or bottom?
  2. Does the playfield scroll vertically?
  3. Which mapper?
NewRisingSun
Posts: 1510
Joined: Thu May 19, 2005 11:30 am

Re: Clean screen split without blank area in-between?

Post by NewRisingSun »

My intention for asking is wondering how feasible it is to modify existing commercial games with glitchy splits to look cleaner. I already mentioned Ys and Conquest of the Crystal Palace; Mega Man 3's level selection screen is another ugly offender.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Clean screen split without blank area in-between?

Post by tokumaru »

I think most games with split glitches just timed their register writes badly, probably because testing builds back in the day wasn't as quick and easy as it is today (some developers reportedly had to burn the game to EPROM for each and every test!), so they didn't spend much time tweaking these splits. Guess you'll have to debug the games and see when in the scanline the critical writes are taking place, and see if you can hack the code to delay or anticipate those writes so they fall in the proper hblank window.
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Clean screen split without blank area in-between?

Post by nesrocks »

Can it be done on every "tile line" like in sms black belt? https://www.youtube.com/watch?v=_4Sg0gd4lfU
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Clean screen split without blank area in-between?

Post by pubby »

Yep. You can change the scroll every scanline.

Also, I was under the impression that HBLANK writes can't be timed 100% perfectly unless you keep track of the synchronization. By that I mean use Blargg's code: viewtopic.php?t=6589

Maybe I'm mistaken though?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Clean screen split without blank area in-between?

Post by tokumaru »

Yes, exact synchronization with the PPU is pretty much impossible (AFAIK, even blargg's trick will only get you really close, like, up to 1 pixel off), but for a successful scroll change you only have to fit 5 cycles worth of instructions (last cycle of st* $2005 plus 4 cycles of st* $2006) in a ~22-cycle window, so there's plenty of wiggle room to get it right regardless of any timing fluctuation.

Effects timed from an NMI or an IRQ look jittery because the CPU always waits for the current instruction to finish before calling the interrupt handler, so with instructions ranging from 2 to 7 cycles on the 6502, the position of a raster effects will vary by up to 7 * 3 = 21 pixels. Effects timed from sprite hits or overflows also suffer from this because the flag can get set at any point during the wait loop, meaning it can sometimes take the code longer to realize the flag has been set (e.g. if it gets set right after $2002 is read, a full iteration of the wait loop will happen before the change is detected), which is why it's important to make these loops as short as possible:

Code: Select all

  ;do this:
  lda #%00100000
TestOverflow:
  bit $2002
  beq TestOverflow

  ;instead of this:
TestOverflow:
  lda $2002
  and #%00100000
  beq TestOverflow
Post Reply