Calculating the color palette of the VIC II

v1 / Feb 2017

Reimplementing the wheel

Black , White , Red , Cyan , Purple , Green , Blue , Yellow Orange , Brown , Lt.Red , Dk.Grey , Md.Grey , Lt.Green , Lt.Blue , Lt.Grey

Lookup Table

var levels = { mc : [ 0 ] , fr : [ 0 ] } ; // Black (luma switched off) with ( levels ) { // most common mc[ 0x6 ] = mc[ 0x9 ] = 8 ; // Blue, Brown mc[ 0xb ] = mc[ 0x2 ] = 10 ; // Dk.Grey, Red mc[ 0x4 ] = mc[ 0x8 ] = 12 ; // Purple, Orange mc[ 0xc ] = mc[ 0xe ] = 15 ; // Md.Grey, Lt.Blue mc[ 0x5 ] = mc[ 0xa ] = 16 ; // Green, Lt.Red mc[ 0xf ] = mc[ 0x3 ] = 20 ; // Lt.Grey, Cyan mc[ 0x7 ] = mc[ 0xd ] = 24 ; // Yellow, Lt.Green mc[ 0x1 ] = 32 ; // White // first revision fr[ 0x2 ] = fr[ 0x6 ] = fr[ 0x9 ] = fr[ 0xb ] = 8 * 1 ; fr[ 0x4 ] = fr[ 0x5 ] = fr[ 0x8 ] = fr[ 0xa ] = fr[ 0xc ] = fr[ 0xe ] = 8 * 2 ; fr[ 0x3 ] = fr[ 0x7 ] = fr[ 0xd ] = fr[ 0xf ] = 8 * 3 ; fr[ 0x1 ] = 8 * 4 ; } var angles = [] ; angles[ 0x4 ] = 2 ; // Purple angles[ 0x2 ] = angles[ 0xa ] = 4 ; // Red angles[ 0x8 ] = 5 ; // Orange angles[ 0x9 ] = 6 ; // Brown angles[ 0x7 ] = 7 ; // Yellow angles[ 0x5 ] = angles[ 0xd ] = 2 + 8 ; // Green angles[ 0x3 ] = 4 + 8 ; // Cyan angles[ 0x6 ] = angles[ 0xe ] = 7 + 8 ; // Blue

Video components

function compose( index , revision , brightness , contrast , saturation ) { // constants var sector = 360 / 16 ; var origin = sector / 2 ; var radian = Math.PI/ 180 ; var screen = 1 / 5 ; // normalize brightness - = 50 ; contrast / = 100 ; saturation * = 1 - screen ; // construct var components = { u : 0 , v : 0 } ; // monochrome (chroma switched off) if ( angles[ index ] ) { var angle = ( origin + angles[ index ] * sector ) * radian ; components.u = Math.cos( angle ) * saturation ; components.v = Math.sin( angle ) * saturation ; } components.y = 8 * levels[ revision ][ index ] + brightness ; for ( var i in components ) { components[ i ] * = contrast + screen ; } return components ; }

Colorspace conversion

function convert( components ) { // matrix transformation var color = {} ; color.r = components.y + 1.140 * components.v ; color.g = components.y - 0.396 * components.u - 0.581 * components.v ; color.b = components.y + 2.029 * components.u ; // gamma correction var source = 2.8 ; // PAL var target = 2.2 ; // sRGB for ( var i in color ) { color[ i ] = Math.max( Math.min( color[ i ] , 255 ) , 0 ) ; color[ i ] = Math.pow( 255 , 1 - source ) * Math.pow( color[ i ] , source ) ; color[ i ] = Math.pow( 255 , 1 - 1 / target ) * Math.pow( color[ i ] , 1 / target ) ; color[ i ] = Math.round( color[ i ] ) ; } return color ; }

Generating the palette

for ( var i = 0 ; i < 16 ; i ++ ) { console.log( convert( compose( i , "mc" , 50 , 100 , 50 ) ) ) ; }

Beyond color

Colodore vs. Pepto

Coming Soonish

The VIC II was designed to generate a video signal that is compatible with analog television , that's why colors are composed of Luma (brightness) and Chroma (hue & saturation) components. During the timeframe that computers utilizing it were on sale, MOS produced several different, that mainly differed in how much voltage is required for operation, or what TV standard is used for color encoding.One particularly visible change was performed soon after the VIC II started gaining larger distribution. The veryoffered only 4 uniform luma levels in addition to Black, which of course meant that it was impossible to distinguish a whole bunch of colors on monochrome monitors . In order to fix this, the amount of levels was doubled, so that only two colors had to share a single luma level at most. This improved version is considered thely encountered, as it was used for all following chip revisions. Values for both versions are included in the calculation that follows.The aim of this project, is to build a, based on the underlying system of how the palette gets generated in general. Measurements have been quantized carefully, in order to represent all VIC II revisions in a faithful manner.According to engineers who were involved in its creation, smallin signal output were deemed acceptable, as a primary design goal of the chip, was to keep manufacturing costs as low as possible. As a consequence, I'm not interested in documenting things like tiny variances found when comparing chip revisions.The palette offers 16, consisting of 8and 8A unified approach to what palette entries in video chips like the VIC VIC II and TED consist of, can be summed up as pairs of one in 16 uniform angles on the color wheel (or none – for monochromes) and one in 32 uniform levels on the luminance scale (or none – for black level ).Except for the monochromes of course, all colors of the VIC II palette appear to use anof saturation, that's why it suffices to classify them by their angle.The values specified here, are based on my research into oscilloscope measurements by Marko Mäkelä and my own observations using a vectorscope and various frame grabbers Considering how popular Javascript is nowadays, I decided to use its syntax for describing the math involved.Analog video monitors offerandcontrols, which areto adjust the overall appearance of the color palette. How these controls are set up, depends on what the user of a system prefers personally. In order to include the major influencing parameters in the calculation,and should be broken out to users, if you plan to implement this in your own application.I observed that shifting percentage-based contrast and saturation values by a certain amount (see screen variable), helped the display-control logic to behave like Commodore 's own 1084s monitor, which is a very popular choice in this field.When converting YUV components to sRGB , the result requires Gamma correction (for PAL in this case).Attempts to imitate the VIC II palette were usually named in the past, so I decided to call this modelRunning the above code for all 16 palette colors, with theamount of luma levels and aof brightness, contrast & saturation values...In order to ease the process of doing your own adjustments and better show how platform-specific graphics look, I implemented a web-app capable of palette-file generation at colodore.com . In addition to the technique described in this document, it emulates the following artefacts of the respective video signals: Aspect ratio (non-square pixels, as documented by Groepaz Scanlines (darkened odd lines, using slightly offset, inverted Luma as alpha , for a more CRT -like look) Hanover Bars (22.5 degrees of hue roation for YUV's V only on odd lines) Delay Line (mixing Chroma of each line, with Chroma of the previous line) Chroma Subsampling (half horizontal resolution for Chroma)In my opinion this achieves to look more similar to real gear, than previous attempts.This isn't my first attempt at calculating an RGB version of the VIC II palette. In 2001, I published an exemplery calculation on my website. This basic model was implemented in quite a few tools and emulators over the years. People interested in VIC II colors started just calling it, as that's my nickname.While fairly accurate for its time and an improvement to what was available previously, I wasn't ultimately satisfied with how some colors looked, when using higher saturation. I had a hard time getting stable read-outs on the vectorscope originally, as it was very picky about signals not following specs precisely. In retrospect I think, that maybe the hanover bars might have leaked into my measurements, which could explain the slightly phase-shifted nature of the inaccuracy.Long story short, I found back my motivation to work on this, when I learned that some guys were doing a book with mostly C64 graphics of the demoscene . I found that re-adjusting the purple/green angle and phase-shifting all colors a tiny notch, resulted in a more accurate representation of the VIC II colors. I also got to grips with calculating gamma values and was able to contribute to the book just in time. VIC and TED • Improved descriptionsCheers,pepto