/**
 * Copyright 2009 matsondawson@gmail.com
 * 
 * Not reproducible in any way without permission. 
 *    
 */

// col1, col2, merge line number, R/G/B(0,1,2)
var coltable = new Array(3);
var pred = new Array(1024);

/**
 * Initialise the display.
 */ 
function DisplayInit() {
	for(var i=0; i<1024; i++) {
		pred[i]=i;
	}

	canvasEl = document.getElementById("canvas");
	if (!canvasEl.getContext) {
		document.getElementById("badie").style.display="inline";
		exit();
	}
	ctx = canvasEl.getContext("2d");

	cvsDat = cvsDatHash = null;
	linedat = null;
	fillHash = null;
      
  var low=2, high=6;
  for(var i=0; i<3; i++) {
    coltable[i] = new Array(16);
  	for(var x=0; x<16; x++) {
      coltable[i][x] = new Array(16);
      for(var y=0; y<16; y++) {
        coltable[i][x][y] = colourWeight(borderCols[x], low, borderCols[y], high);
      }
    }
    high-=2;
    low+=2;
  }
}


function colourWeight(col1, w1, col2, w2) {
  
  var r1 = col1>>16, r2 = col2>>16;
  var g1 = (col1>>8)&255, g2 = (col2>>8)&255;
  var b1 = col1&255, b2 = col2&255;
  
  //w1*=w1;
  //w2*=w2;
  
  return (parseInt(((r1*w1) + (r2*w2)) / (w1+w2))<<16)
    + (parseInt(((g1*w1) + (g2*w2)) / (w1+w2))<<8)
    + (parseInt(((b1*w1) + (b2*w2)) / (w1+w2)));
}

/**
 * Vic colour palette.
 */ 
var borderCols = [ 0, 0xFFFFFF, 0x891000, 0x46bfcf,
			0x8614c6, 0x45b705, 0x2713d0, 0xbed215, 0x9a4600, 0xFF9900,
			0xFFC0CB, 0xE0FFFF, 0x9370D8, 0x90EE90, 0xADD8E6, 0xFFFFE0 ];

/**
 * Convert a decimal value to hex string.
 * Used in canvas fill. 
 */ 
function toHex(d, padding) {
    var hex = d.toString(16);
    padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;
    while (hex.length<padding) hex = "0" + hex;
    return hex;
}

/**
 * Render the current display.
 */ 
function DisplayRender() {
	var regCB = m[0x9005] & 0xF;
	var chrom = ((~regCB & 8) << 12) + ((regCB & 7) << 10);
            
	var vb = m[0x9005] >> 4;
	var cr2 = m[0x9002];
	var scmem = ((~vb & 8) << 12) + ((vb & 7) << 10) + ((cr2 >> 7) << 9);
	var colmem = 0x9400 + ((cr2 & 128) << 2);

	var cols = m[0x9002]&0x7F;	
	var rows = (m[0x9003]>>1)&0x3F;
  var cr3 = m[0x9003];
  var charHeightBit = (cr3 & 1);
	var charHeightShift = 3+charHeightBit;
  var charHeightShiftMul = 10<<charHeightBit;
  
  var left = (m[0x9000]&127)<<2;
  var top = m[0x9001]<<1;
 
	if (cols!=0 && rows!=0)
	{
		var newCvsDatHash = cols+","+rows+","+charHeightShiftMul;
		if (cvsDatHash!=newCvsDatHash) {
			cvsDat = ctx.getImageData(0,0,cols*8*2,rows*charHeightShiftMul);
			linedat = ctx.getImageData(0,0,8*2,charHeightShiftMul);
			cvsDatHash = newCvsDatHash;

			// Pre-set alpha mask to 255
			for(var loop=0; loop<linedat.width*linedat.height*4; loop++ ) linedat.data[loop]=0xFF;
		}

    var borderColourBits = m[0x900f] & 7;
		var borderColour = borderCols[borderColourBits];

		// Dont wanna refill if we don't have to
		var newFillHash = newCvsDatHash+","+borderColour; // Todo add LEFT,RIGHT
	  if (newFillHash!=fillHash) {
			ctx.fillStyle = "#"+toHex(borderColour,6);
		  ctx.fillRect(0,0,canvasEl.width,canvasEl.height);
			fillHash = newFillHash;
		}

		var b = m[0x900f]>>4;
		var bb = borderCols[b];
		var d = linedat.data;
		var rowadd = (cvsDat.width<<2)-62;
		var aux = m[0x900e] >> 4;
		var multicol = [b,borderColourBits,0,aux];
		var sighash = borderColourBits+(cols*rows)+aux+b<<4;
		var xxxreset= (canvasEl.width-(cols<<4))>>1;
		var predc=0;
	  var yyy=((canvasEl.height-(rows<<3<<charHeightBit))>>1)-23;
	  for(var yy=0; yy<rows; yy++) {
	    var xxx = xxxreset;
			for(var xx=0; xx<cols; xx++) {
	
				var ch = m[scmem++];
				var co=chrom+(ch<<charHeightShift);
				if (co>=0x2000 && co<0x8000) co+=0x6000;
				var colb = m[colmem++];
				var sig = sighash^((modCount[(co>>3)]+(charHeightBit?(modCount[(co>>3)+1]<<8):0)))+(ch<<16)+colb<<2;
				if (pred[++predc]==sig) {
					//ix+=64;
				}
				else {
				  var ix = 0;
					pred[predc] = sig;
					
					if (colb&8) {
						multicol[2]=colb & 7;
	
						for(var k=0; k<2<<charHeightBit; k++) {
		      		var cl = m[co++];					
							var fc = borderCols[multicol[cl>>6]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[(cl>>4)&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[(cl>>2)&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[cl&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							
							var clp = 0;
	  					for(var i=0; i<3; i++) {
	  					  var ct = coltable[i];
	  					   
	              // 0,1
	    					clp = cl;
	    					cl = m[co++];
								if (cl==clp) {
									fc = borderCols[multicol[cl>>6]];
					        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
									fc = borderCols[multicol[(cl>>4)&3]];
					        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
									fc = borderCols[multicol[(cl>>2)&3]];
					        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
									fc = borderCols[multicol[cl&3]];
					        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
								} else {
		    					fc = ct[ multicol[cl>>6] ][ multicol[clp>>6] ];
		              d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
								  fc = ct[ multicol[(cl>>4)&3] ][ multicol[(clp>>4)&3] ];
		              d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
								  fc = ct[ multicol[(cl>>2)&3] ][ multicol[(clp>>2)&3] ];
		              d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
		              fc = ct[ multicol[cl&3] ][ multicol[clp&3] ];
		              d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
								}
	            }
	  					
	  					fc = borderCols[multicol[cl>>6]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[(cl>>4)&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[(cl>>2)&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							fc = borderCols[multicol[cl&3]];
			        d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++; d[ix++] = fc>>16; d[ix++] = fc>>8&0xFF; d[ix++] = fc&0xFF; ix++;
							
						}
					}
					else {
					var f = colb & 7;
					var ff = borderCols[f];
					
					for(var k=0; k<2<<charHeightBit; k++) {
					  var cl = m[co++];
  					// 0
  					var col = (cl&128)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&64)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&32)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&16)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&8)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&4)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&2)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&1)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;

					  var clp = 0;
  				for(var i=0; i<3; i++) {
  					  var ct = coltable[i];
    					// 0,1
    					clp = cl;
    					cl = m[co++];
							if (clp==cl) {
								var col = (cl&128)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&64)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&32)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&16)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&8)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&4)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&2)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
		  					col = (cl&1)?ff:bb;
		  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
							} else {
	    					var col = ct[(clp&128)?f:b][(cl&128)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&64)?f:b][(cl&64)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&32)?f:b][(cl&32)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&16)?f:b][(cl&16)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&8)?f:b][(cl&8)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&4)?f:b][(cl&4)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&2)?f:b][(cl&2)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
	    					col = ct[(clp&1)?f:b][(cl&1)?f:b];
	    					d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
							}
            }

            // 0
  					var col = (cl&128)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&64)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&32)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&16)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&8)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&4)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&2)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  					col = (cl&1)?ff:bb;
  	        d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++; d[ix++] = col>>16; d[ix++] = col>>8&0xFF; d[ix++] = col&0xFF; ix++;
  				}
				}
			 ctx.putImageData(linedat, xxx, yyy);
			 

				}
				xxx+=16;
	    }
	    yyy+=charHeightShiftMul;
	  }
	}
}
