Palette swap within the game region?

A place for your artistic side. Discuss techniques and tools for pixel art on the NES, GBC, or similar platforms.

Moderator: Moderators

w7n
Posts: 10
Joined: Wed May 15, 2013 9:33 am

Palette swap within the game region?

Post by w7n » Tue Nov 07, 2017 2:48 am

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?

User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2032
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Palette swap within the game region?

Post by FrankenGraphics » Tue Nov 07, 2017 2:52 am

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.
http://www.frankengraphics.com - personal NES blog

User avatar
dougeff
Posts: 2636
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Palette swap within the game region?

Post by dougeff » Tue Nov 07, 2017 10:29 am

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=15142

Edit. Misspelled.
Last edited by dougeff on Tue Nov 07, 2017 10:32 am, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
rainwarrior
Posts: 7718
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Palette swap within the game region?

Post by rainwarrior » Tue Nov 07, 2017 10:32 am

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 ... 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.

User avatar
dougeff
Posts: 2636
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Palette swap within the game region?

Post by dougeff » Tue Nov 07, 2017 10:43 am

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)
Last edited by dougeff on Tue Nov 07, 2017 5:21 pm, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
rainwarrior
Posts: 7718
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Palette swap within the game region?

Post by rainwarrior » Tue Nov 07, 2017 11:01 am

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.

lidnariq
Posts: 9030
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Palette swap within the game region?

Post by lidnariq » Tue Nov 07, 2017 11:26 am

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.

User avatar
dougeff
Posts: 2636
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Palette swap within the game region?

Post by dougeff » Tue Nov 07, 2017 11:39 am

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?
nesdoug.com -- blog/tutorial on programming for the NES

User avatar
rainwarrior
Posts: 7718
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Palette swap within the game region?

Post by rainwarrior » Tue Nov 07, 2017 11:43 am

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 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.

lidnariq
Posts: 9030
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Palette swap within the game region?

Post by lidnariq » Tue Nov 07, 2017 12:08 pm

rainwarrior wrote:It clears only the top bit of fine Y.
See also: Visual2C02 transistor t15006
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.

User avatar
dougeff
Posts: 2636
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Palette swap within the game region?

Post by dougeff » Tue Nov 07, 2017 1:11 pm

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.
nesdoug.com -- blog/tutorial on programming for the NES

lidnariq
Posts: 9030
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Palette swap within the game region?

Post by lidnariq » Tue Nov 07, 2017 1:37 pm

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.

User avatar
rainwarrior
Posts: 7718
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Palette swap within the game region?

Post by rainwarrior » Tue Nov 07, 2017 9:31 pm

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: Select all

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

w7n
Posts: 10
Joined: Wed May 15, 2013 9:33 am

Re: Palette swap within the game region?

Post by w7n » Fri Nov 10, 2017 12:18 am

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.

User avatar
dougeff
Posts: 2636
Joined: Fri May 08, 2015 7:17 pm
Location: DIGDUG
Contact:

Re: Palette swap within the game region?

Post by dougeff » Fri Nov 10, 2017 8:46 am

"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.
nesdoug.com -- blog/tutorial on programming for the NES

Post Reply