However it becomes very problematic if one wants to do a palette swap within the game region e.g. splitting the game region into two blocks and use different palettes for them.
The specific case is, I have a few blank scanlines to spend, but the protagonist's sprites still need to display correctly on these scanlines.
> Is it possible at all?
> If not, any alternative solutions to make it involve least noticable graphical glitches?
- Formerly WheelInventor
- Posts: 2032
- Joined: Thu Apr 14, 2016 2:55 am
- Location: Gothenburg, Sweden
Just switching the common bg colour should be even faster than overwriting a full palette entry, if that helps.
One last option i can think of is playing with timed emphasis bits to get rows of different colour, but again, sprite presentation will be affected.
"1) Turn off BG and sprite rendering using $2001
2) Write palette address to $2006 (though high byte can be latched before step (1)
3) Write palette color to $2007
4) Restore scroll position using $2006 and $2005 writes. (as it is a fixed yscroll location with no xscroll, you can probably get away with writing $2006 only and skip the highest fine Y-scroll bit)
5) Turn on BG and sprite rendering using $2001
And even with all those steps carefully optimised, there is the final gotcha: Any midscreen palette change will corrupt the sprites being fetched for the next line."
lidnariq made a nice timing diagram a while ago of Indiana Jones doing it:
https://forums.nesdev.com/viewtopic.php ... 25#p139925
The only thing special about moving it up and down is that this is just one more factor on top of all the other timing you need to account for. A scanline IRQ (e.g. MMC3) would probably help a lot here.
Therefore, to do more than 1 palette change would be spread out over (8 * # of palette changes) scanlines.
(# of palette changes, minus one, times 8)
Horizontal blank is only about 21 cycles. Time for I guess 4 or 5 writes? You can shift some of the needed writes out into the visible part of the scanline (and some of them can be visually benign), but yeah it's not enough for a full flush of the scroll registers, unfortunately.
Wut?dougeff wrote:BTW, I the Indiana Jones Last Crusade does 2 writes to $2006 to realign the scroll after the palette write. This can only be done at a exactly divisible by 8 Y position.
Fine Y can be set to 0 through 3, just not 4-7. Fine X can't be changed.
It clears only the top bit of fine Y.dougeff wrote:Hmm. Well, I've never tested multiple palette writes mid-screen.
I thought 2 writes to $2006 cleared the fine Y. Is that not correct?
Wiki: $2006 first write
Though it also pays to notice that Indiana Jones is able to do some of its writes early without visual artifacts specifically because it's only changing the background colour.
See also: Visual2C02 transistor t15006rainwarrior wrote:It clears only the top bit of fine Y.
And also because the background color is the only thing being displayed when it turns off the screen early.Though it also pays to notice that Indiana Jones is able to do some of its writes early without visual artifacts specifically because it's only changing the background colour.
I think you can safely change 3 palette colors in 1 H-blank (contiguous palette entries), maybe 4 (I was getting occasional glitchiness when trying 4).
I didn't test how sprites react to this change. It would have to be tested on an actual NES. Maybe another day.
Each scanline has 85px that aren't used for blitting pixels to the display; of those, 64 pixels (the eight sprite fetch periods) can be stolen without breaking background rendering. If the left or right edges of the screen are just the backdrop color you can steal a little more time.
64px is only 21cy; if all the values you're writing can fit in A, X, and Y without loading new values, then you have exactly the amount of time to update one palette entry (6 writes * 4 cycles/write - 3 cycles for the first write being loaded in)
In summary: No. But you could use a horizontal stripe of background tiles that are equivalent to your protagonist's sprite, and set the background scroll appropriately.w7n wrote:a few blank scanlines to spend, but the protagonist's sprites still need to display correctly on these scanlines.
> Is it possible at all?
If rendering is off, yes, it's very convenient to use groups of 4 colours per scanline. Something like:dougeff wrote:I think you can safely change 3 palette colors in 1 H-blank (contiguous palette entries), maybe 4 (I was getting occasional glitchiness when trying 4).
Code: Select all
BIT $2007 ; skip background colour STA $2007 STX $2007 STY $2007
This leaves the PPU address pointing at the next background colour slot, too, so you can leave it there across the next visible scanline without any funny colours showing. ...and of course you're going to want a blank scanline after it to give you an opportunity to reload the scroll and put the renderer back in order.
I do this in my palette display ROM: thread
Oh (slap head). You guys were talking about changing a palette WITHOUT turning rendering off.
I was testing turning rendering off, and writing 3 palette colors, then 2 writes $2006 to set scroll, then screen back on, without glitches.