SNES color palette in emulators

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

Moderator: Moderators

User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

SNES color palette in emulators

Post by DRW »

As far as I see, the R, G and B components of colors in SNES emulators like ZSNES are converted like this:

PcValue = SnesValue * 256 / 32

This has the strange behavior that white is 248,248,248 instead of 255,255,255.

Then I've read some stuff about replicating the top three bits into the bottom three bits to get to the full range. Which sounds totally random and nonsensical to me. Why should you ever do this? In how far do the upper and the lower bits have any connection to each other to ever justify this kind of behavior?

Why don't they simply use the formula:

PcValue = SnesValue * 255 / 31

In this case, white is actually 255,255,255 and black is still 0,0,0.

And the colors (well, their exact values, not the rounded integers) are still evenly distributed.

So, why this crappy calculation with 32 and 256 instead of 31 and 255? And why some strange hack about replicating bits that have nothing to do with each other?

If calculating with 31 and 255 is a speed issue: Just declare a lookup array. It takes you exactly 32 bytes of space. Then you can do:
PcValue = AllPcValues[SnesValue]
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: SNES color palette in emulators

Post by Bregalad »

PcValue = SnesValue * 255 / 31
Indeed, that's the correct way to do it - mapping linear values from 0 to 31 to another linear space from 0 to 255.
Then I've read some stuff about replicating the top three bits into the bottom three bits to get to the full range. Which sounds totally random and nonsensical to me. Why should you ever do this?
It's not random, it's roughly equivalent to the formula you proposed. The forumula you call bullshit nonsensical would be that :

Code: Select all

pc_colour = (SNES_colour << 3) | (SNES_colour >> 2)
Which is equivalent to

Code: Select all

pc_colour = (SNES_colour * 8) + (SNES_colour / 4)
Which is equivalent to

Code: Select all

pc_colour = SNES_colour * 33 / 4
In both cases, we're linearly mapping colours by multiplying by an integer slightly bigger than 8, because multiplying by 8 leads to the problem that whites are not pure white. Whether this integer is 255/31 (8.2258) or 33/4 (8.25) is almost insignificant, since the new value will be rounded to an integer anyway.

I've tested this on excel. Basically it either makes no difference or there's a difference of '1' which is basically a rounding error. The first column is using the fraction 255/31, the second using 33/4, in both cases rounded towards 0 (floor).

Code: Select all

0	  0	  0
1	  8	  8
2	 16	 16
3	 24	 24
4	 32	 33
5	 41	 41
6	 49	 49
7	 57	 57
8	 65	 66
9	 74	 74
10	82	 82
11	90	 90
12	98	 99
13	106	107
14	115	115
15	123	123
16	131	132
17	139	140
18	148	148
19	156	156
20	164	165
21	172	173
22	180	181
23	189	189
24	197	198
25	205	206
26	213	214
27	222	222
28	230	231
29	238	239
30	246	247
31	255	255
As to why ZSNES did not map colours the proper way, I have no idea but the most likely explanation is that they were just lazy :)
Last edited by Bregalad on Mon Jun 26, 2017 7:44 am, edited 1 time in total.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: SNES color palette in emulators

Post by tepples »

That and / is a fairly expensive operation that's hard to pipeline. A multiplication by 8 or by 33/4 might allow more throughput on an old Pentium than a formula involving a division by 31.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: SNES color palette in emulators

Post by DRW »

Bregalad wrote:The forumula you call bullshit
I didn't call it that.

But thanks for the elaboration. I didn't really understand what they meant.
I would still prefer the 31 and 255 calculation though. It just looks cleaner to me.
tepples wrote:That and / is a fairly expensive operation that's hard to pipeline. A multiplication by 8 or by 33/4 might allow more throughput on an old Pentium than a formula involving a division by 31.
But shouldn't an emulator strive to be as accurate as possible and not use some cheapshots just because of a simple division?
As I said: If the processor is too slow, it's a mere 32 bytes for a lookup table here.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: SNES color palette in emulators

Post by Bregalad »

DRW wrote: I didn't call it that.
Sorry, I fixed my post.
I would still prefer the 31 and 255 calculation though. It just looks cleaner to me.
Both calculations sets a linear slope so that 0->0 and 31 -> 255. But it all comes down to rounding, the version based on bit shifts ignores the bits shifted out, so it actually sets the second point to 31 -> 255.75 because 2 set bits are shifted out on the right. So both can be seen as technically correct, it depends if you consider full white to be "exactly" 255 or if you consider it "all bits set" (including bits which are eventually dropped).
But shouldn't an emulator strive to be as accurate as possible and not use some cheapshots just because of a simple division?
ZSNES is definitely inaccurate - their goal were to run as many SNES games as possible on late-1990s PCs. It's pretty much the Nesticle of SNES emulation. As I said lazyness is the only reason I see why they didn't scale colours properly.
Since the screen is entirely a bit more dim, I guess the eyes just get used to it and see (240, 240, 240) as white, even though it's technically not the brightest possible colour.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: SNES color palette in emulators

Post by tokumaru »

Bregalad wrote:Both calculations sets a linear slope so that 0->0 and 31 -> 255. But it all comes down to rounding
It's not like an off-by-one error in some values makes any difference in this case, though. Also, there are so few input values that you can easily build a look-up table for this and have the output be as precise as you want.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: SNES color palette in emulators

Post by DRW »

So, which emulator is the Nestopia of the Super Nintendo?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
TmEE
Posts: 960
Joined: Wed Feb 13, 2008 9:10 am
Location: Norway (50 and 60Hz compatible :P)
Contact:

Re: SNES color palette in emulators

Post by TmEE »

bsnes/higan
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: SNES color palette in emulators

Post by calima »

DRW wrote:As I said: If the processor is too slow, it's a mere 32 bytes for a lookup table here.
Your perception is colored by the NES. Memory access on PC platforms is not 1-2 cycles slower like on the NES, it's often 100 cycles slower. For something executed for every pixel, it really matters on slow processors.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: SNES color palette in emulators

Post by DRW »

calima wrote:Your perception is colored by the NES.
Actually, my perception is colored by writing programs for regular PCs where a simple division or an array lookup was never really the bottleneck when any of my programs were slow, even on a computer from 1999.
But yeah, I don't really know in how far this would be an issue for an emulator.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: SNES color palette in emulators

Post by Pokun »

Bsnes/higan is not only Nestopia but also the Nintendulator of SNES emulators I guess. It's designed to be as hardware accurate as possible. Zsnes is a very old emulator and not very good anymore. It used to be very popular because of its decent compatibility, nice built-in gui and the fact that no highly accurate emulators existed for SNES back then.
ccovell
Posts: 1045
Joined: Sun Mar 19, 2006 9:44 pm
Location: Japan
Contact:

Re: SNES color palette in emulators

Post by ccovell »

DRW wrote:Then I've read some stuff about replicating the top three bits into the bottom three bits to get to the full range. Which sounds totally random and nonsensical to me. Why should you ever do this? In how far do the upper and the lower bits have any connection to each other to ever justify this kind of behavior?
They have a connection with each other because you are doing a division in which the denominator will always generate a repeating fraction in decimal. The same also applies to any number base system (binary, in this case). The repeating values to the right of the decimal point will use values from the left of the decimal. (I explained it a bit more in this post: viewtopic.php?f=5&t=12739&p=146789#p146789 )
User avatar
rainwarrior
Posts: 8735
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: SNES color palette in emulators

Post by rainwarrior »

DRW wrote:Then I've read some stuff about replicating the top three bits into the bottom three bits to get to the full range. Which sounds totally random and nonsensical to me. Why should you ever do this? In how far do the upper and the lower bits have any connection to each other to ever justify this kind of behavior?
It's a pretty reasonable approximation to the ideal 255 / 31 conversion:

Code: Select all

; three equivalent operations;
31 * 256 / 32 = 248
31 * 8 = 248
31 << 3 = 248 ; note how the low 3 bits are unused

; attempting to fill the empty 3 bits with a scaled down version of the result:
248 + (248 >> 5) = 255
248 + (248 / 32) = 255.75
31 * (8 + (8/32)) = 255.75
31 * 8.25 = 255.75

; note how close this is to the ideal:
31 * (255 / 31) = 255
31 * ~8.226 = ~255

; another way of looking at the same approximation is
; the original shifted left to fill the top 5 bits,
; and shifted right to fill the bottom 3 bits:
(31 << 3) + (31 >> 2) = 255
(31 * 8) + (31 / 4) = 255.75
In this approximation, the low 3 bits go from 0-7 across the input range 0-31, and the high 5 bits go from 0-31. It results in all bits set at 31, and all bits clear at 0, and has an regular monotonic increase in between.

It's similar to the way that you can represent a multiplication with a shift and sum, just working the other way for division:

Code: Select all

x * 248
= x * (128 + 64 + 32 + 16 + 8)
= (x << 7) + (x << 6) + (x << 5) + (x << 4) + (x << 3)
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: SNES color palette in emulators

Post by DRW »

Thanks for all the information.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
nitro2k01
Posts: 252
Joined: Sat Aug 28, 2010 9:01 am

Re: SNES color palette in emulators

Post by nitro2k01 »

calima wrote:
DRW wrote:As I said: If the processor is too slow, it's a mere 32 bytes for a lookup table here.
Your perception is colored by the NES. Memory access on PC platforms is not 1-2 cycles slower like on the NES, it's often 100 cycles slower. For something executed for every pixel, it really matters on slow processors.
The only time it's going to be 100 times slower is if the table causes a cache miss on high FSB ratio menory. Realistically, that's only going to happen for the first access in a tight loop doing tens of thousands of iterations. Slow processors (if by slow you mean one where the CPU might be a bottleneck for SNES emulation) typically won't have those extreme FSB ratios that would create that problem in the first place. In that case, a TLB miss is more likely to cause that problem. But even so, only on the first access.
Post Reply