var curView = 'hex';
var srcOutp = ';Disassembler output';
var hexOutp = '';
var srcMsgs = '';
  function viewSwitch(view)
  {
	for (var i = 0; i < 2; i++)// uncheck all radio buttons (this is so that I can invoke viewSwitch not only by th onClick handle ,but from my code as well)
	{
	  document.editor.rad[i].checked = false;
	}

	if (curView == 'hex')
	{
	hexOutp = document.editor.codeWindow.value;
	srcMsgs = document.editor.outpMsgs.value;
	}
	if (view == 'srcOutp')
	{
	  curView = 'src';
	  document.editor.codeWindow.value = srcOutp;
	  document.editor.outpMsgs.value = srcMsgs;
	  document.editor.rad[1].checked = true;
	  statBar('Diassember Output View');
	}
	if (view == 'hex')
	{
	  curView = 'hex';
	  document.editor.codeWindow.value = hexOutp;
	  document.editor.rad[0].checked = true;
	  statBar('Hex View');

	}
  }



function disasm()
{
  if(curView != 'hex')
  {
	alert('Switch to Hex View to Disassemble.');
	return;
  }

  document.editor.outpMsgs.value = '';
  initDisasm();
  addMsg(' Disassembly in progress ...');
  stripHex();

  addMsg('\n Checking hex validity ...  ');
  if(checkHex() == -1)
  {
  	addMsg('\n Disassembly aborted ...   ');
  	return;
  }
  
  addMsg('[ OK ]');
  
  buildMemArry();
  
  addMsg('\n Disassembling ...          ');
  disAll();
  addMsg('[ OK ]');
  
 // addMsg('\n Adding comments ...        ');	
 // addCmmnts();
 // addMsg('[ OK ]');

  addMsg('\n Generating output ...      ');	
  showDisOutp();
  addMsg('[ OK ]');
  
  addMsg('\n Disassembly complete.');
  viewSwitch('srcOutp');
  //alert('Disassembly complete !')
}


var hexLnsArry = Array();
var hexhexLnCntr = 0;

function stripHex()
{
		statBar('Initializing ...');
	   xpnsn = 0;
	   hexLnCntr = 0;
	   hexLnsArry = new Array();
	   var tempBuf1 = document.editor.codeWindow.value;
	   tempBuf1 = trim(tempBuf1); 
	   var tempBuf2 = '';
	   var lstNdxOfNl = 0; //to store last index of '\n'
	   while ( tempBuf1 != "" )
	   {
		 lstNdxOfNl = tempBuf1.lastIndexOf('\n');
		 tempBuf2 = tempBuf1.substring(lstNdxOfNl+1,tempBuf1.length);//put line in tempBuf2
		 hexLnsArry[hexLnCntr] = tempBuf2;
		 tempBuf1 =  tempBuf1.substring(0,lstNdxOfNl);
		 hexLnCntr += 1; 
		}
	   statBar('');
}

function checkHex()// checks and removes unnecessary stuff
{
  	var csum;
  	var lngthOfLmnt;
  	var hexLn;
	for(var i = 0; i < hexLnsArry.length ; i++)
	{
	  	statBar('Checking line :' + i);
	  	hexLnsArry[i] = trim(hexLnsArry[i]); // trim spaces tabs and so on....
	  	lngthOfLmnt = hexLnsArry[i].length;
		if(	hexLnsArry[i] != '' 
			&&
			(hexLnsArry[i].indexOf(':') != 0
			||
			lngthOfLmnt % 2 == 0))
		{
			addMsg('\nInvalid Hex input ! ');
			return -1;
	  	}
		hexLn = hexLnsArry[i].substring(1,lngthOfLmnt-2);
		csum = hexLnsArry[i].substring(lngthOfLmnt-2,lngthOfLmnt);
		hexLnsArry[i] = hexLn; // replace line with csum and colon removed
		//alert(hexLn +'  calculeted csum >>'+ checkSum(hexLn));
		if(csum != checkSum(hexLn))
		{
		  addMsg('\nInvalid Hex input >> Checksum error !');
		  return -1;
		}
	}

	statBar('');
}

var memArry = Array(); //array to store everthyng to do with disassembly
var hexVal = 0; // memArry[][hexVal]
var lblFld = 1; // memArry[][lblFld]
var dSrcLn = 2; // memArry[][dSrcLn]
var cmmntFld = 3; //memArry[][cmmntFld] //comments
function buildMemArry()
{
  var adrsPntr =0;
  var wordsArry;// array to store words from a single HEX line
  for(var i = hexLnsArry.length -1 ; i >= 0 ; i--)
  	{
	  wordsArry = getWords(hexLnsArry[i]);
	  adrsPntr = getAdrs(hexLnsArry[i]);
	  for(var q = 0; q < wordsArry.length ; q++)
	  {
		memArry[adrsPntr] = Array();
		memArry[adrsPntr][hexVal] = parseInt(wordsArry[q],16);
		//memArry[adrsPntr][hexVal] = wordsArry[q],16;
		adrsPntr++
	  }
	}
}

function initDisasm()
{	
	lblNmbr = 1;
	srcOutp = ';Disassembler output';
	memArry = null;
	memArry = new Array();
}

function getWords(hexLn)// returns array of words from hexLn passed
{
  	var wordsArry = Array();
	var nWords = getNBytes(hexLn) / 2;
	//alert('nWords = '+ nWords  );
	var q = 8
	var p = 12
	for(var i = 0;nWords > i ; i++)
	{
		wordsArry[i] = swpByts(hexLn.substring(q,p));
		//alert(wordsArry[i])
		q += 4;
		p += 4;
	}
	return wordsArry;
}

function getNBytes(hexLn)
{
	var nBytes = parseInt(hexLn.substring(0,2),16);
	//alert('nBytes '+nBytes);
	return nBytes;
}

function getAdrs(hexLn)
{
	var adrs = parseInt(hexLn.substring(2,6),16);
	//alert(adrs)  ;
	return adrs/2;
}

function disAll()
{
  for(var i=0;i < memArry.length; i++)
  {
	disALn(i)
  }
}

function disALn(i)
{
	if (memArry[i] != null)
	{
	  var tmpHexVal = memArry[i][hexVal];
	  //var q
	  for(var j=0;j<instrTab.length;j++ )
	  {
		if((instrTab[j][disasmMask]&tmpHexVal) == instrTab[j][opcode])
		{
		  //alert(instrTab[j][instruction]);
		  eval('dis_'+instrTab[j][rule]+'('+'i'+','+'j'+')');//opcode str, i ,j
		  return;
		}
	  }	
	  //if hex val is not an instruction bu data :
	  memArry[i][dSrcLn] = 'data 0x '+ baseDisp(tmpHexVal,16);
	}
		//memArry[i][dSrcLn] =  instrTab[j][instruction];
		//alert(baseDisp(instrTab[j][disasmMask]&tmpHexVal,16)+'\n'+baseDisp(instrTab[j][opcode],16)+'\n'+instrTab[j]);
	
	//alert(hexVal);
}

var dispLocHex = false;
function showDisOutp()
{
  srcOutp = '';
  for(var i=0;i < memArry.length; i++)
  {
	if(memArry[i] != null)
	{	
		if(i > 0 && memArry[i-1] == null)
		{ if(dispLocHex)
		  srcOutp += '\t\t';
		  srcOutp += 'ORG 0x' +  baseDisp(i,16) +'\n';//+memArry[i][dSrcLn]
		}
		if(dispLocHex)
	  	srcOutp += baseDisp(i,16) +'\t'+ baseDisp(memArry[i][hexVal],16) +'\t'
	  	
	  	if(memArry[i][lblFld] != null)
	  	srcOutp += memArry[i][lblFld];
	  	srcOutp += '\t' + memArry[i][dSrcLn];
	  	if(memArry[i][cmmntFld] != null)
	  	srcOutp += '\t' + memArry[i][cmmntFld];
	  	srcOutp += '\n';
	  	
	}
  }
}

function dis_dualAWDst(i,j)
{
  	var tBuf1 = memArry[i][hexVal] & 0x7F;
	memArry[i][dSrcLn] =  instrTab[j][instruction] + ' '+ getReg(tBuf1)+ getDestBit(memArry[i][hexVal]);

}

var lblNmbr = 1;// label number counter
function dis_oneArg(i,j)
{
	var tBuf1 = memArry[i][hexVal] & instrTab[j][maxVal];
	var instr = instrTab[j][instruction]
	if(	instr == 'call'
		||
		instr == 'goto')
	{
		
		if(memArry[tBuf1] == null)
		{
			memArry[tBuf1] = Array();
			memArry[tBuf1][lblFld] = 'lbl_' +lblNmbr;
		}
		if(memArry[tBuf1][lblFld] == null)
		{
			memArry[tBuf1][lblFld] = 'lbl_' +lblNmbr;
		}
		else
		{
			memArry[i][dSrcLn] =  instr +' '+ memArry[tBuf1][lblFld];
			return;
		}
		memArry[i][dSrcLn] =  instr +' '+'lbl_' + lblNmbr;
		cmmntLn('lbl_' + lblNmbr + ' = 0x'+ baseDisp(tBuf1,16),i);
		lblNmbr++;
		return;
	}
	if(	instr == 'clrf'
		||
		instr == 'movwf')
	{
		memArry[i][dSrcLn] = instr + ' '+ getReg(tBuf1);
		return;
	}
	
	memArry[i][dSrcLn] = instr + ' '+ baseDisp(tBuf1,16);
	cmmntLn( 'd\''+ baseDisp(tBuf1,10)+'\''+ ' b\''+ baseDisp(tBuf1,2)+'\'' +' a\''+ asciiTable.charAt(tBuf1)+'\'',i);
	

}

function dis_bit(i,j)
{
  	var typ ='';
	var ramLoc = memArry[i][hexVal] & 0x7F;
	var reg = getReg(ramLoc);
	if(reg == 'status')typ = 3;
	if(reg == 'intcon')typ = 4;
	if(reg == 'option')typ = 5;
	if(reg == 'eecon1')typ = 6;
	var bNmbr = (memArry[i][hexVal] & 0x380)/128
	//alert(bNmbr);
	var bit = getBit(bNmbr,typ);
	memArry[i][dSrcLn] =  instrTab[j][instruction] + ' '+reg + ','+bit;
	//if(memArry[i][hexVal] == 0x1283){page = 0 }
	//else if(memArry[i][hexVal] == 0x1683){page = 1}

   if(memArry[i][hexVal] == 0x1683) //1683 bsf  STATUS,RP0	; select register bank 1
	{
	  cmmntLn('switch to bank 1',i);
	  page = 1;
	}
	else
	if(memArry[i][hexVal] == 0x1283) //1283 bcf  STATUS,RP0	; select register bank 0
	{
	  cmmntLn('switch to bank 0',i);
	  page = 0;
	}

}

function dis_asIs(i,j)
{
	memArry[i][dSrcLn] =  instrTab[j][instruction];
}

var page = 0;
//var lastRegNdx = 0;
function getReg(ramLoc)
{
  	if(	page == 1
  		&&
  		ramLoc != 2 //this ln and below are reg files availble on both pages
  		&&
  		ramLoc != 3
  		&&
  		ramLoc != 4
  		&&
  		ramLoc != 0xA
  		&&
  		ramLoc != 0xB)
  	{
  		ramLoc = ramLoc | 0x80;
  	}
	for(var i = 2;i<18;i++)
	{
	  	if(ramLoc == equArry[i][equStrVal])
		{
	  		//lastRegNdx = i;
	 		return equArry[i][equStr];
		}
	}
	//lastRegNdx = i;
	return '0x'+baseDisp(ramLoc,16);
}

function getBit(nmbr,typ)
{
  	if(typ == '')return nmbr;
	for(var i=18;i<48;i++)
	{
		if(	equArry[i][clrNdx] == typ
			&&
			equArry[i][equStrVal]== nmbr)
		{
		  return equArry[i][equStr];
		}
	}

	return nmbr;
}

function getConfigBit()
{

}

var showDestBit = true;
function getDestBit(hexOpcd)
{
	if((hexOpcd & 0x80) == 128)
	return ',f';
	else
	return ',w';
	//alert(hexOpcd & 0x80);
}
/*
function addCmmnts()
{
  for(var i=0;i < memArry.length; i++)
  {
  	if(memArry[i] != null)
  	{
  	
	  if(memArry[i][hexVal] == 0x1683) //1683 bsf  STATUS,RP0	; select register bank 1
	  {
		cmmntLn('select register bank 1',i);
	  }
	  else
	  if(memArry[i][hexVal] == 0x1283) //1283 bcf  STATUS,RP0	; select register bank 0
	  {
		cmmntLn('select register bank 0',i);
	  }
	  else
	  if((memArry[i][hexVal] & 0xFC00) == 0x3400)//retlw",     "*",   0x3400,	"oneArg",	0xFC00,	0x00FF);
	  {
	  	cmmntLn(asciiTable.charAt(memArry[i][hexVal] & 0x00FF)+' '+ baseDisp(memArry[i][hexVal] & 0x00FF,16) ,i);
	  }
	  
	}
  }
}

*/

function cmmntLn(cmmntTxt,loc) //comment text, location
{
	if(memArry[loc][cmmntFld] != null)
		memArry[loc][cmmntFld] += cmmntTxt;
	else
		memArry[loc][cmmntFld] = '; ' + cmmntTxt;
	return;
}
