base:commodore_vic-ii_color_analysis
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:commodore_vic-ii_color_analysis [2015-04-17 04:31] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Commodore VIC-II Color Analysis ====== | ||
+ | Written by Pepto. FTC cleaned up some initial comments about lack of time etc that were not exactly relevant to the topic itself. The original article is available [[http:// | ||
+ | |||
+ | The whole issue of VIC-II color-emulation is so mis-guiding and irritating, because every c64-emulator uses different palettes and these have been created by using cheap frame-grabbers/ | ||
+ | |||
+ | But let's come to the C=64 colors which will be featured here first... | ||
+ | |||
+ | The C=64 (with its VIC-II chip) features a palette of 16 colors. | ||
+ | |||
+ | ^ # ^ Name ^ | ||
+ | | 0 | black | | ||
+ | | 1 | white | | ||
+ | | 2 | red | | ||
+ | | 3 | cyan | | ||
+ | | 4 | purple | ||
+ | | 5 | green | | ||
+ | | 6 | blue | | ||
+ | | 7 | yellow | ||
+ | | 8 | orange | ||
+ | | 9 | brown | | ||
+ | | A | light red | | ||
+ | | B | dark grey | | ||
+ | | C | grey | | ||
+ | | D | light green | | ||
+ | | E | light blue | | ||
+ | | F | light grey | | ||
+ | |||
+ | Black, White and the three Greys are no colors and the " | ||
+ | |||
+ | Since the color-palette of the VIC-II has been made for the TV-system, we aren't talking a RGB-color-space, | ||
+ | |||
+ | " | ||
+ | |||
+ | If you just measure the " | ||
+ | |||
+ | Here's a table of both of those luma-versions, | ||
+ | |||
+ | ^ early VIC-II luma ^ | ||
+ | | 0 | | ||
+ | | 2, 6, 9, B | | ||
+ | | 4, 5, 8, A, C, E | | ||
+ | | 3, 7, D, F | | ||
+ | | 1 | | ||
+ | |||
+ | ^ late VIC-II luma ^ | ||
+ | | 0 | | ||
+ | | 6, 9 | | ||
+ | | 2, B | | ||
+ | | 4, 8 | | ||
+ | | C, E | | ||
+ | | 5, A | | ||
+ | | 3, F | | ||
+ | | 7, D | | ||
+ | | 1 | | ||
+ | |||
+ | You can of course also verify this by minimizing color-saturation on your monitor, or just plugging " | ||
+ | |||
+ | However if you measure the luma-levels with an oscilloscope (Marko Mäkelä did so in 1996), you are able to see, that all of those levels are perfectly dividable by 32. I made a little Illustration here: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | As we need to stuff the luma-values into 8 bits (0 to 255) for later calculation, | ||
+ | |||
+ | ^ ^^^ | ||
+ | | 08 * 7,96875 | = 63,75 | = 64 | | ||
+ | | 10 * 7,96875 | = 79, | ||
+ | | 12 * 7,96875 | = 95, | ||
+ | | 15 * 7,96875 | = 119,53125 | = 120 | | ||
+ | | 16 * 7,96875 | = 127,5 | = 128 | | ||
+ | | 20 * 7,96875 | = 159, | ||
+ | | 24 * 7,96875 | = 191, | ||
+ | | 32 * 7,96875 | = 255,0 | = 255 | | ||
+ | |||
+ | So... That's it for the brightness of the colors, let's come to the hue... | ||
+ | |||
+ | If you measure the chroma-signal (" | ||
+ | |||
+ | ^ ^^^ | ||
+ | | (light) blue | 0,0° | 22,5° * 0 | | ||
+ | | purple | ||
+ | | (light) red | 112,5° | 22,5° * 5 | | ||
+ | | orange | ||
+ | | brown | 157,5° | 22,5° * 7 | | ||
+ | |||
+ | The missing three angles are on the opposite side of the color-wheel from above mentioned angles. Yellow is "blue + 180°", | ||
+ | |||
+ | If you want to calculate " | ||
+ | |||
+ | < | ||
+ | U = 100 * cos(angle) | ||
+ | V = 100 * sin(angle) | ||
+ | </ | ||
+ | |||
+ | In order to calculate the 4 voltage-levels in percent, calculate " | ||
+ | |||
+ | < | ||
+ | 100 * sin(157, | ||
+ | 100 * sin( 45,0°) = 70, | ||
+ | 100 * sin(112, | ||
+ | 100 * cos( 0,0°) = 100, | ||
+ | </ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Now " | ||
+ | |||
+ | I found out the desired value with the brute force method by calculating around with different values in order to more and more close up to the needed value which produces Brown' | ||
+ | |||
+ | Please note however, that monitors/ | ||
+ | |||
+ | What is maybe interesting for you to know is, that John ' | ||
+ | |||
+ | But let's continue with the calculation... ;-) | ||
+ | |||
+ | ^ # ^ name ^ angle ^ y (" | ||
+ | | 0 | black | n/a | 0 * ( 255 : 32 ) | 0 | 0 | | ||
+ | | 1 | white | n/a | 32 * ( 255 : 32 ) | 0 | 0 | | ||
+ | | 2 | red | 5 * ( 360° : 16 ) | 10 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | 3 | cyan | 5 * ( 360° : 16 ) + 180° | 20 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | 4 | purple | ||
+ | | 5 | green | 2 * ( 360° : 16 ) + 180° | 16 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | 6 | blue | 0 * ( 360° : 16 ) | 8 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | 7 | yellow | ||
+ | | 8 | orange | ||
+ | | 9 | brown | 7 * ( 360° : 16 ) | 8 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | A | light red | 5 * ( 360° : 16 ) | 16 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | B | dark grey | n/a | 10 * ( 255 : 32 ) | 0 | ||
+ | | C | grey | n/a | 15 * ( 255 : 32 ) | 0 | 0 | | ||
+ | | D | light green | 2 * ( 360° : 16 ) + 180° | 24 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | E | light blue | 0 * ( 360° : 16 ) | 15 * ( 255 : 32 ) | peak * cos(angle) | peak * sin(angle) | | ||
+ | | F | light grey | n/a | 20 * ( 255 : 32 ) | 0 | 0 | | ||
+ | |||
+ | ...and the result of this calculation is: | ||
+ | |||
+ | ^ # | name ^ angle ^ y (late) | ||
+ | | 0 | black | n/a | 0,0 | 0 | 0 | | ||
+ | | 1 | white | n/a | 255,0 | 0 | 0 | | ||
+ | | 2 | red | 112,5° | 79, | ||
+ | | 3 | cyan | 292,5° | 159, | ||
+ | | 4 | purple | ||
+ | | 5 | green | 225,0° | 127,5 | -24, | ||
+ | | 6 | blue | 0,0° | 63,75 | +34, | ||
+ | | 7 | yellow | ||
+ | | 8 | orange | ||
+ | | 9 | brown | 157,5° | 63,75 | -31, | ||
+ | | A | light red | 112,5° | 127,5 | -13, | ||
+ | | B | dark grey | n/a | 79, | ||
+ | | C | grey | n/a | 119,53125 | 0 | 0 | | ||
+ | | D | light green | 225,0° | 191, | ||
+ | | E | light blue | 0,0° | 119,53125 | +34, | ||
+ | | F | light grey | n/a | 159, | ||
+ | |||
+ | Now we need to convert YUV to RGB. Here's the formula: | ||
+ | |||
+ | < | ||
+ | R = Y + 1,140 * V | ||
+ | G = Y - 0,396 * U - 0,581 * V | ||
+ | B = Y + 2,029 * U | ||
+ | </ | ||
+ | |||
+ | ...and here's the result: | ||
+ | |||
+ | ^ # ^ name ^ r ^^ g ^^ b ^^ | ||
+ | | 0 | black | 0,0 | (0) | 0,0 | (0) | 0,0 | (0) | | ||
+ | | 1 | white | 255,0 | (255) | 255,0 | (255) | 255,0 | (255) | | ||
+ | | 2 | red | 115, | ||
+ | | 3 | cyan | 123, | ||
+ | | 4 | purple | ||
+ | | 5 | green | 100, | ||
+ | | 6 | blue | 63,75 | (64) | 50, | ||
+ | | 7 | yellow | ||
+ | | 8 | orange | ||
+ | | 9 | brown | 78, | ||
+ | | A | light red | 163, | ||
+ | | B | dark grey | 79, | ||
+ | | C | grey | 119, | ||
+ | | D | light green | 163, | ||
+ | | E | light blue | 119, | ||
+ | | F | light grey | 159, | ||
+ | |||
+ | Now you need to gamma-correct the rgb-colors. Please note, that the gamma-correction is always the last thing you do to the palette. If you want to change brightness, contrast, saturation, mix-colors for interlace-emu, | ||
+ | |||
+ | I'm not 100% sure about the used gamma-values in the following calculation, | ||
+ | |||
+ | In order to correct the PAL-Gamma for VGA-Output you need to calculate each r, g and b value with an exponent of "2,5 : 2,2" (which is 1,136) and stretch the results back proportionaly to 8 bit valid values (between 0 and 255). There' | ||
+ | |||
+ | Here are the results, after the gamma-correction: | ||
+ | |||
+ | ^ # ^ name ^ r ^^ g ^^ b ^^ | ||
+ | | 0 | black | 0,0 | (0) | 0,0 | (0) | 0,0 | (0) | | ||
+ | | 1 | white | 254, | ||
+ | | 2 | red | 103, | ||
+ | | 3 | cyan | 111, | ||
+ | | 4 | purple | ||
+ | | 5 | green | 88, | ||
+ | | 6 | blue | 52, | ||
+ | | 7 | yellow | ||
+ | | 8 | orange | ||
+ | | 9 | brown | 66, | ||
+ | | A | light red | 153, | ||
+ | | B | dark grey | 67, | ||
+ | | C | grey | 107, | ||
+ | | D | light green | 154, | ||
+ | | E | light blue | 107, | ||
+ | | F | light grey | 149, | ||
+ | |||
+ | Finished... Now here's a comparison of how some c64-pics look with the palette which is included in ccs64 v2.0 beta (this is just an example) and with the palette we just calculated... | ||
+ | |||
+ | ^ ccs64 v2.0b ^ my palette ^ | ||
+ | | {{: | ||
+ | |||
+ | ^ ccs64 v2.0b ^ my palette ^ | ||
+ | | {{: | ||
+ | |||
+ | ^ ccs64 v2.0b ^ my palette ^ | ||
+ | | {{: | ||
+ | |||
+ | And here's the palette in hex-format for easier usage in certain emulators: | ||
+ | |||
+ | < | ||
+ | 00 00 00 | ||
+ | FF FF FF | ||
+ | 68 37 2B | ||
+ | 70 A4 B2 | ||
+ | 6F 3D 86 | ||
+ | 58 8D 43 | ||
+ | 35 28 79 | ||
+ | B8 C7 6F | ||
+ | 6F 4F 25 | ||
+ | 43 39 00 | ||
+ | 9A 67 59 | ||
+ | 44 44 44 | ||
+ | 6C 6C 6C | ||
+ | 9A D2 84 | ||
+ | 6C 5E B5 | ||
+ | 95 95 95 | ||
+ | </ | ||
+ | |||
+ | Have fun using it... ;-) (watch out -- work in progress -- more to come...) | ||
+ | Sorry again for poor documentation and maybe typos, but remember that this is a preview... | ||
+ | |||
+ | |||
+ | Philip " | ||
+ | |||
+ | |||
+ | P.S.: Here's an interesting eMail which Bob Yannes (co-developer of the VIC-II) sent to me. Please note that I can't disclose Bob's eMail address to you, as he's very concerned about his privacy and the only way to get in touch with him myself, was through a third person, who forwarded our mails to eachother. In other words, I don't have his eMail-address myself, so don't ask. Additionally please note that Bob talks about the NTSC color wheel. NTSC uses YIQ instead of PAL's YUV, but in order to convert from YIQ to YUV you just have to rotate everything by 33° and exchange the color-difference axis. This is what they probably did in hardware in order to make the VIC-II work with PAL and so NTSC and PAL-VIC' | ||
+ | |||
+ | < | ||
+ | Subject: "Re: VIC-II colors" | ||
+ | From: Robert ' | ||
+ | To: Philip ' | ||
+ | Date: 27.09.1999 | ||
+ | |||
+ | I was involved with the development of the VIC-II, however the | ||
+ | actual implementation of the design, including the Color Palette, | ||
+ | was done by someone else. I have forwarded your message to him, | ||
+ | but it is up to him if he wants to respond. | ||
+ | |||
+ | I can tell you that the design was based on the principle that | ||
+ | adding a sine wave of a particular frequency and amplitude to an | ||
+ | inverted version of the same sine wave at a different amplitude | ||
+ | produces a phase-shifted sine wave of the same frequency. The | ||
+ | amount of phase shift is directly proportional to the amplitudes | ||
+ | of the two sine waves. | ||
+ | |||
+ | The VIC-II used the 14.31818 MHz master clock input (4 times the | ||
+ | NTSC color burst frequency of 3.579545 MHz) to produce | ||
+ | quadrature square-wave clocks. These clock signals were then | ||
+ | integrated into triangle waves using analog integrators. The | ||
+ | triangle waves were then integrated again into sine waves | ||
+ | (actually rounded triangle waves, but good enough for this | ||
+ | application). This produced a 3.579545 MHz sine wave, inverse | ||
+ | sine wave, cosine wave and inverse cosine wave. | ||
+ | |||
+ | An analog summer was used to create the phase-shifts in the | ||
+ | Chroma signal by adding together the appropiate two waveforms at | ||
+ | the appropiate amplitudes. The Color Palette data went to a | ||
+ | look-up table that specified the amplitude of the waves by | ||
+ | selecting different resistors in the gain path of the summer. | ||
+ | The end result was that we could create any hue we wanted by | ||
+ | looking at the NTSC color wheel to determine the phase-shift and | ||
+ | then picking the appropiate resistor values to produce that | ||
+ | phase-shift. | ||
+ | |||
+ | Color Saturation was controlled by scaling the gain of the | ||
+ | summer. When we picked the resistor values to determine the | ||
+ | output phase-shift, | ||
+ | output amplitude. Luminance was controlled using a simple | ||
+ | voltage divider which switched different pull-down resistors | ||
+ | into the open-drain output. We could create any Luminance we | ||
+ | wanted by choosing the desired resistor value. | ||
+ | |||
+ | I'm afraid that not nearly as much effort went into the color | ||
+ | selection as you think. Since we had total control over hue, | ||
+ | saturation and luminance, we picked colors that we liked. In | ||
+ | order to save space on the chip, though, many of the colors | ||
+ | were simply the opposite side of the color wheel from ones | ||
+ | that we picked. This allowed us to reuse the existing resistor | ||
+ | values, rather than having a completely unique set for each | ||
+ | color. | ||
+ | |||
+ | I believe that Commodore actually got a patent on this | ||
+ | technique. It was certainly superior to the Apple or Atari | ||
+ | approach at the time, as they ended up with whatever colors | ||
+ | that came out--ours allowed the designer to freely select Hue, | ||
+ | Saturation and Luminance. | ||
+ | |||
+ | Since all of this was based on selecting different resistor | ||
+ | values and resistance varied from chip lot to chip lot, there | ||
+ | was variation from one Commodore 64 to another. It wasn't as | ||
+ | bad as it could have been though, since all of the Chrominance | ||
+ | selection was based on resistor ratios, which could be kept | ||
+ | constant even if the actual resistor values varied. Luminance | ||
+ | was more of a problem. A trimmer resistor should really have | ||
+ | been used to pull up the output. This would have allowed the | ||
+ | Luminance to be adjusted for consistency from unit to unit, | ||
+ | however Commodore didn't care enough about consistency to | ||
+ | bother with adjusting each unit. | ||
+ | |||
+ | Robert ' | ||
+ | </ |
base/commodore_vic-ii_color_analysis.txt · Last modified: 2015-04-17 04:31 by 127.0.0.1