On the topic of palette swaps. I've read a few documents and came to know that palette swapping between an HUD (as long as it doesn't contain sprites) and the game portion is possible and not too hard. If minor graphical glitches are tolerated, then it won't consume too much time either.
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.
So:
> Is it possible at all?
> If not, any alternative solutions to make it involve least noticable graphical glitches?
I don't know a way to avoid it other than making a level so that objects of interest never overlap the seam, which could work on some specific platforming stage layouts.
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.
Quoting bananmos
"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."
Source...
viewtopic.php?f=2&t=15142Edit. Misspelled.
It's feasible to change one palette entry per scanline, during the horizontal blank period, but yeah, having to turn off rendering for this does mean you will lose a the following scanline of sprites too.
lidnariq made a nice timing diagram a while ago of Indiana Jones doing it:
https://forums.nesdev.com/viewtopic.php?p=139925#p139925The 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.
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.
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)
Oh, yeah I forgot about that limitation.
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.
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.
Wut?
Fine Y can be set to 0 through 3, just not 4-7. Fine X can't be changed.
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?
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?
It clears only the top bit of fine Y.
Reference:
Wiki: $2006 first writeThough 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.
rainwarrior wrote:
It clears only the top bit of fine Y.
See also: Visual2C02 transistor t15006
Quote:
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.
And also because the background color is the only thing being displayed when it turns off the screen early.
I ran some tests. (emulators)
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.
I mean, we know the window. Disabling rendering will always break sprites on the following scanline. Disabling rendering at the wrong time will break sprites for the rest of the field.
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)
—
w7n wrote:
a few blank scanlines to spend, but the protagonist's sprites still need to display correctly on these scanlines.
So:
> Is it possible at all?
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.
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).
If rendering is off, yes, it's very convenient to use groups of 4 colours per scanline. Something like:
Code:
BIT $2007 ; skip background colour
STA $2007
STX $2007
STY $2007
It's only 16 cycles but it's helpful to have some wiggle room for placement within the horizontal blank. (Also, depending on your TV, parts of that 64-pixel "blank" area might actually be visible.)
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
Thanks everyone, I've got a better grasp of the whole thing. Seems that besides the HUD it could only be used in certain cutscenes at best.
"If rendering is off, yes"
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.
No, you always have to turn it off before you mess with the address.
What I meant is that there's not enough time to turn it off and back on in an hblank, so rendering has to be visibly off if you're updating more than one palette entry (and really even for Indiana Jones' case of just the background colour, rendering is still off for a visible part of the scanline, it's just cleverly concealed).
So, by "rendering off" I meant for multiple scanlines while you do your palette changes.
Also disabling rendering causes OAM corruption if done at the wrong time.