/**
 * Copyright 2009 matsondawson@gmail.com
 * 
 * Not reproducible in any way without permission. 
 *    
 */

var cvsDat = null, d = null;

var screenScale = 1;
var screenTypeHash = "";
device_display=0x200;

/**
 * Initialise the display.
 */
function DisplayInit() {
	canvasEl = document.getElementById("canvas");
	if (!canvasEl.getContext) {
		// document.getElementById("badie").style.display="inline";
		alert("Your browser does not support the canvas tag!");
		exit();
	}
	ctx = canvasEl.getContext("2d");
	DisplayRender();
}

var ppb = [0,8,4,0,2,0,0,0,1];
/**
 * Render the current display.
 */ 
function DisplayRender() {
  var offset = device_display;
  if(offset==-1) return;

  var screenBase = m[offset++]+(m[offset++]<<8);
  var paletteBase = m[offset++]+(m[offset++]<<8);
  var width = m[offset++]+(m[offset++]<<8);
  var height = m[offset++]+(m[offset++]<<8);
  var bitdepth = m[offset++];
  var pixelsPerByte = ppb[bitdepth];
  var scanLineBytes = width/pixelsPerByte;
  if (pixelsPerByte<1) return;

  var newScreenTypeHash = width+"x"+height+"@"+bitdepth;
  if (newScreenTypeHash!=screenTypeHash) {
  	// Clear canvas
  	ctx.fillStyle = "#000000";
		ctx.fillRect(0,0,canvasEl.width,canvasEl.height);
    
    if (width<=0 || height<=0) return;
    screenScale = Math.min(Math.floor(canvasEl.width/width),Math.floor(canvasEl.height/height));
    
    var ww = width*screenScale;
    if (ww<=0 || ww>canvasEl.width) return;
    var hh = height*screenScale;
    if (hh<=0 || hh>canvasEl.height) return;
    screenTypeHash = newScreenTypeHash; 

    cvsDat = ctx.getImageData(0,0,ww,hh);
  	d = cvsDat.data;

  	// Set alpha mask
  	for(var loop=0; loop<cvsDat.width*cvsDat.height*4; loop++ ) d[loop] = 0xFF;
  }

	var ix = 0;
	var memloc = screenBase;

  if (screenScale==1) { 
    var a = cvsDat.width<<2;
    var ix2 = a;
   if (bitdepth==4) {
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=2) {
          var col = m[memloc++];
          var po = paletteBase+((col>>2)&60); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
          po = paletteBase+((col&15)<<2); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2;
       }
        ix+=a;
        ix2+=a;
    	}
    }
  }
  else
  if (screenScale==2) { 
    var a = cvsDat.width<<2;
    var ix2 = a;
   if (bitdepth==4) {
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=2) {
          var col = m[memloc++];
          var po = paletteBase+((col>>2)&60); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b;   
          d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;   
          po = paletteBase+((col&15)<<2); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++;
       }
        ix+=a;
        ix2+=a;
    	}
    }
    else if (bitdepth==2) {
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=2) {
          var col = m[memloc++];
          var po = paletteBase+((col>>4)&12); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b;   
          d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;   
          po = paletteBase+((col>>2)&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
          po = paletteBase+(col&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
          po = paletteBase+((col<<2)&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++;
       }
        ix+=a;
        ix2+=a;
    	}
    }
    else if (bitdepth==1) {
      var a = cvsDat.width<<2;
      var ix2 = a;
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=8) {
          var col = m[memloc++];
          var po = paletteBase+((col>>5)&4); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b;   
          d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;   
          po = paletteBase+((col>>4)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; 
          po = paletteBase+((col>>3)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; 
          po = paletteBase+((col>>2)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; 
          po = paletteBase+((col>>1)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; 
          po = paletteBase+(col&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; 
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
          po = paletteBase+((col<<1)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; 
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
          po = paletteBase+((col<<2)&4); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++;
       }
        ix+=a;
        ix2+=a;
    	}
    }
  }
  else if (screenScale==3) { 
    var a = cvsDat.width<<2;
    var ix2 = a;
    var ix3 = ix2+a;
   if (bitdepth==4) {
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=2) {
          var col = m[memloc++];
          var po = paletteBase+((col>>2)&60); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;  d[ix++] = r; d[ix++] = g; d[ix++] = b;   
          d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;   
          d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b;   
          po = paletteBase+((col&15)<<2); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
          d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++;
          d[++ix3] = r; d[++ix3] = g; d[++ix3] = b; ix3+=2; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++;
       }
        ix+=a<<1;
        ix2+=a<<1;
        ix3+=a<<1;
    	}
    }
    else if (bitdepth==2) {
    var a = cvsDat.width<<2;
    var ix2 = a;
    var ix3 = ix2+a;
  	 for(var y=0; y<height; y++) {
    	 for(var x=0; x<width; x+=4) {
          var col = m[memloc++];
          var po = paletteBase+((col>>4)&12); 
          var r = m[po], g=m[po+1], b=m[po+2];
          d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++; d[ix++] = r; d[ix++] = g; d[ix++] = b;   
         // d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;   
        //  d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b;   
          po = paletteBase+((col>>2)&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b;
         // d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
        //  d[++ix3] = r; d[++ix3] = g; d[++ix3] = b; ix3+=2; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b;
          po = paletteBase+(col&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b
        //  d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b;
        //  d[++ix3] = r; d[++ix3] = g; d[++ix3] = b; ix3+=2; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b;
          po = paletteBase+((col<<2)&12); 
          r = m[po], g=m[po+1], b=m[po+2];
          d[++ix] = r; d[++ix] = g; d[++ix] = b; ix+=2; d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
         // d[++ix2] = r; d[++ix2] = g; d[++ix2] = b; ix2+=2; d[ix2++] = r; d[ix2++] = g; d[ix2++] = b; ix2++;
        //  d[++ix3] = r; d[++ix3] = g; d[++ix3] = b; ix3+=2; d[ix3++] = r; d[ix3++] = g; d[ix3++] = b; ix3++;
       }
        ix+=a<<1;
        ix2+=a<<1;
        ix3+=a<<1;
    	}
    }
  }
  else {
  	for(var y=0; y<height; y++) {
  	 for(var sy=0; sy<screenScale; sy++) {
    	 for(var x=0; x<width; x+=pixelsPerByte) {
          var col = m[memloc++];
          
          switch(bitdepth) {
            case 1:
              for(var i=0; i<8; i++) {
                var c = (col>>7)&1;
                var po = paletteBase+(c<<2); 
                var r = m[po], g=m[po+1], b=m[po+2];
                
                for(var sx=0; sx<screenScale; sx++) {
                  d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
                }
                col<<=1;
              }
              break;
            case 2:
              for(var i=0; i<4; i++) {
                var c = (col>>6)&3;
                var po = paletteBase+(c<<2); 
                var r = m[po], g=m[po+1], b=m[po+2];
                
                for(var sx=0; sx<screenScale; sx++) {
                  d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
                }
                col<<=2;
              }
              break;
            case 4:
                var po = paletteBase+(((col>>4)&15)<<2); 
                var r = m[po], g=m[po+1], b=m[po+2];
                
                for(var sx=0; sx<screenScale; sx++) {
                  d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
                }
                var po = paletteBase+((col&15)<<2); 
                r = m[po], g=m[po+1], b=m[po+2];
                
                for(var sx=0; sx<screenScale; sx++) {
                  d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
                }
              
              break;
            case 8:
              var po = paletteBase+(col<<2); 
              var r = m[po], g=m[po+1], b=m[po+2];
              
              for(var sx=0; sx<screenScale; sx++) {
                d[ix++] = r; d[ix++] = g; d[ix++] = b; ix++;
              }
  
              break;
          }
        }
        memloc -= scanLineBytes;
      }
      memloc += scanLineBytes;
  	}
	}

	ctx.putImageData(cvsDat,(canvasEl.width-cvsDat.width)>>1, (canvasEl.height-cvsDat.height)>>1);
}








