SNES color palette in emulators
Moderator: Moderators
SNES color palette in emulators
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]
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
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: SNES color palette in emulators
Indeed, that's the correct way to do it - mapping linear values from 0 to 31 to another linear space from 0 to 255.PcValue = SnesValue * 255 / 31
It's not random, it's roughly equivalent to the formula you proposed. The forumula you callThen 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?
Code: Select all
pc_colour = (SNES_colour << 3) | (SNES_colour >> 2)
Code: Select all
pc_colour = (SNES_colour * 8) + (SNES_colour / 4)
Code: Select all
pc_colour = SNES_colour * 33 / 4
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
Last edited by Bregalad on Mon Jun 26, 2017 7:44 am, edited 1 time in total.
Re: SNES color palette in emulators
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.
Re: SNES color palette in emulators
I didn't call it that.Bregalad wrote:The forumula you call bullshit
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.
But shouldn't an emulator strive to be as accurate as possible and not use some cheapshots just because of a simple division?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.
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
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: SNES color palette in emulators
Sorry, I fixed my post.DRW wrote: I didn't call it that.
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).I would still prefer the 31 and 255 calculation though. It just looks cleaner to me.
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.But shouldn't an emulator strive to be as accurate as possible and not use some cheapshots just because of a simple division?
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.
Re: SNES color palette in emulators
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.Bregalad wrote:Both calculations sets a linear slope so that 0->0 and 31 -> 255. But it all comes down to rounding
Re: SNES color palette in emulators
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
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: SNES color palette in emulators
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.DRW wrote:As I said: If the processor is too slow, it's a mere 32 bytes for a lookup table here.
Re: SNES color palette in emulators
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.calima wrote:Your perception is colored by the NES.
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
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: SNES color palette in emulators
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.
Re: SNES color palette in emulators
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 )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?
- rainwarrior
- Posts: 8735
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: SNES color palette in emulators
It's a pretty reasonable approximation to the ideal 255 / 31 conversion: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?
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
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)
Re: SNES color palette in emulators
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
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Re: SNES color palette in emulators
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.calima wrote: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.DRW wrote:As I said: If the processor is too slow, it's a mere 32 bytes for a lookup table here.