#include "a6502.h"
#include <stdlib.h>
#include <stdio.h>

#define HSYNC 228
#define tick(a) clock += (a);

//***********************constructor************************************
m6502::m6502(void)
{
   power_up();
   ram = (Byte far *) farmalloc(0x10000L);
   rom = (Byte far *) farmalloc(0x10000L);
   for (unsigned i=0;i<65535U;i++) ram[i]=rom[i]=0;

}

//************************initializer***********************************
void m6502::power_up(void)
{
   pc = 0xfffc;
   reset_ = 1;
   //set flags
   i_ = 1;		//disable interrupts
   //Apparently these flags are undefined for the 6502 at power up
   //but I will define them anyway.  Some program may expect to see
   //a particular value at power up, so keep this in mind.
   n=v=b=d=z=c=0;
   a=x=y=0;
   s = 0x00;
   opcode_setup();	//generate an array of function pointers
   opcode = 0x4c;
}

//*************************RESET************************************
void m6502::reset(void)
{
   pc = 0xfffc;
   reset_ = 1;
   //set flags
   i_ = 1;		//disable interrupts
   s = 0x00;
   a=x=y=0;
   opcode = 0x4c;
}

void m6502::interrupt_(void)
{
#ifdef DEBUG
   puts("interrupt starts");
#endif

   if (!i_)
   {
      ram[SP+ s--] = ((pc-1)>>8)&0xff;
      ram[SP+ s--] = (pc-1)&0xff;
      fPHP();
      pc = 0xfffe;
      opcode = 0x4c;
   }
}

void m6502::copy_bytes(Word addr, Word num, Byte huge *mem)
{
   for (Word i=0;i<num;i++)
   {
      ram[addr+i] = mem[i];
//	  printf("\naddress = %x data = %x",addr+i, ram[addr+i]);
      if ((long(addr)+long(i)) > 0xffff )
	  break;
   }
}

void m6502::nmi_(void)
{
   ram[SP+ s--] = ((pc-1)>>8)&0xff;
   ram[SP+ s--] = (pc-1)&0xff;
   fPHP();
   pc = 0xfffa;
   opcode = 0x4c;
}

void m6502::print_reg(void)
{
   puts("\n pc   a  x  y  s  nv_bdizc");

   printf("%4x %2x %2x %2x %2x  %1x%1x %1x%1x%1x%1x%1x    ",
   unsigned(pc-1),unsigned(a),x,y,s,n,v,b,d,i_,z,c);
}

void m6502::setup_print(void)
{
   FILE *fin;
   ch_optab = (char far *) farmalloc(224);
   optab = (Byte far *) farmalloc(1456);

   if (optab==NULL || ch_optab==NULL) {puts("out of memory"); exit(0);}

   fin = fopen("choptab.dat","rb");
   for (int i=0;i<56;i++)
      fscanf(fin, "%s",&ch_optab[i*4]);
   fclose(fin);

   fin = fopen("optab.dat","rb");
   for (i=0;i<56;i++)
      fscanf(fin, "%x %x %x %x %x %x %x %x %x %x %x %x %x",&optab[i*13],
	 &optab[i*13+1], &optab[i*13+2],&optab[i*13+3],&optab[i*13+4],
	 &optab[i*13+5], &optab[i*13+6], &optab[i*13+7], &optab[i*13+8],
	 &optab[i*13+9], &optab[i*13+10], &optab[i*13+11], &optab[i*13+12]);
   fclose(fin);

}
void m6502::print_opcode(void)
{
   int i,k, row, col;
   for (i=0;i<56;i++)
      for (k=0;k<13;k++)
	 if (optab[i*13+k] == opcode) {row = i; col = k;break;}

   i = row;
   k = col;
   Word addr;
   switch (k)
   {
      case 0: printf("%2x %2x      %s #$%x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], ram[pc]); break;
      case 1: addr = Word(ram[pc])+(Word(ram[pc+1])<<8);
	      printf("%2x %2x %2x   %s $%x      =%2x",
		 ram[pc-1], ram[pc], ram[pc+1], &ch_optab[i*4],
		 addr, ram[addr] );
	      break;
      case 2: printf("%2x %2x      %s $%x      =%2x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], ram[pc],
		 ram[ram[pc]]);
	      break;
      case 3: printf("%2x         %s A", ram[pc-1], &ch_optab[i*4]); break;
      case 4: printf("%2x         %s", ram[pc-1], &ch_optab[i*4]); break;
      case 5: addr = ram[ram[pc]+x]+(ram[ram[pc]+x+1]<<8);
	      printf("%2x %2x      %s ($%x,X)      =%2x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], ram[pc], ram[addr]);
	      break;
      case 6: addr = ram[ram[pc]]+(ram[ram[pc]+1]<<8)+y;
	      printf("%2x %2x      %s ($%x),Y      =%2x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], ram[pc], ram[addr]);
	      break;
      case 7: addr = ram[pc];
	      printf("%2x %2x      %s $%x,X      =%2x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], addr, ram[addr+x]);
	      break;
      case 8: addr = Word(ram[pc])+(Word(ram[pc+1])<<8);
	      printf("%2x %2x %2x   %s $%x,X      =%2x",
		 ram[pc-1], ram[pc], ram[pc+1], &ch_optab[i*4], addr,
		 ram[addr+x]);
	      break;
      case 9: addr =  Word(ram[pc])+(Word(ram[pc+1])<<8);
	      printf("%2x %2x %2x   %s $%x,Y      =%2x",
		 ram[pc-1], ram[pc], ram[pc+1], &ch_optab[i*4], addr,
		 ram[addr+y]);
	      break;
      case 10: printf("%2x %2x      %s $%x",
		 ram[pc-1], ram[pc], &ch_optab[i*4],
		 int(pc+1)+int((signed char)(ram[pc])));
	       break;
      case 11: printf("%2x %2x %2x   %s ($%x)",
		 ram[pc-1], ram[pc], ram[pc+1], &ch_optab[i*4],
		 Word(ram[pc])+(Word(ram[pc+1])<<8));
	       break;
      case 12: printf("%2x %2x      %s $%x,Y      =%2x",
		 ram[pc-1], ram[pc], &ch_optab[i*4], ram[pc],
		 ram[ram[pc]+y]);
	       break;
      default: break;
   }
   puts("");
   printf ("stack: ");
   for (i=0xff;i>s;i--)
      printf("%x ", ram[SP+i]);
   puts("");
}

void m6502::opcode_setup(void)
{
//OpCodes  for 6502
   func[0x00] = &m6502::fBRK;
   func[0x01] = &m6502::fORA_IND_X;
   func[0x02] = &m6502::fNOP_;
   func[0x03] = &m6502::fNOP_;
   func[0x04] = &m6502::fNOP_;
   func[0x05] = &m6502::fORA_ZP;
   func[0x06] = &m6502::fASL_ZP;
   func[0x07] = &m6502::fNOP_;
   func[0x08] = &m6502::fPHP;
   func[0x09] = &m6502::fORA_IMM;
   func[0x0a] = &m6502::fASL_A;
   func[0x0b] = &m6502::fNOP_;
   func[0x0c] = &m6502::fNOP_;
   func[0x0d] = &m6502::fORA_ABS;
   func[0x0e] = &m6502::fASL_ABS;
   func[0x0f] = &m6502::fNOP_;

   func[0x10] = &m6502::fBPL;
   func[0x11] = &m6502::fORA_IND_Y;
   func[0x12] = &m6502::fNOP_;
   func[0x13] = &m6502::fNOP_;
   func[0x14] = &m6502::fNOP_;
   func[0x15] = &m6502::fORA_ZP_X;
   func[0x16] = &m6502::fASL_ZP_X;
   func[0x17] = &m6502::fNOP_;
   func[0x18] = &m6502::fCLC_;
   func[0x19] = &m6502::fORA_ABS_Y;
   func[0x1A] = &m6502::fNOP_;
   func[0x1B] = &m6502::fNOP_;
   func[0x1C] = &m6502::fNOP_;
   func[0x1D] = &m6502::fORA_ABS_X;
   func[0x1E] = &m6502::fASL_ABS_X;
   func[0x1F] = &m6502::fNOP_;

   func[0x20] = &m6502::fJSR;
   func[0x21] = &m6502::fAND_IND_X;
   func[0x22] = &m6502::fNOP_      ;
   func[0x23] = &m6502::fNOP_;
   func[0x24] = &m6502::fBIT_ZP;
   func[0x25] = &m6502::fAND_ZP;
   func[0x26] = &m6502::fROL_ZP;
   func[0x27] = &m6502::fNOP_;
   func[0x28] = &m6502::fPLP;
   func[0x29] = &m6502::fAND_IMM;
   func[0x2A] = &m6502::fROL_A;
   func[0x2B] = &m6502::fNOP_;
   func[0x2C] = &m6502::fBIT_ABS;
   func[0x2D] = &m6502::fAND_ABS;
   func[0x2E] = &m6502::fROL_ABS;
   func[0x2F] = &m6502::fNOP_;

   func[0x30] = &m6502::fBMI;
   func[0x31] = &m6502::fAND_IND_Y;
   func[0x32] = &m6502::fNOP_;
   func[0x33] = &m6502::fNOP_;
   func[0x34] = &m6502::fNOP_;
   func[0x35] = &m6502::fAND_ZP_X;
   func[0x36] = &m6502::fROL_ZP_X;
   func[0x37] = &m6502::fNOP_;
   func[0x38] = &m6502::fSEC;
   func[0x39] = &m6502::fAND_ABS_Y;
   func[0x3A] = &m6502::fNOP_;
   func[0x3B] = &m6502::fNOP_;
   func[0x3C] = &m6502::fNOP_;
   func[0x3D] = &m6502::fAND_ABS_X;
   func[0x3E] = &m6502::fROL_ABS_X;
   func[0x3F] = &m6502::fNOP_;

   func[0x40] = &m6502::fRTI;
   func[0x41] = &m6502::fEOR_IND_X;
   func[0x42] = &m6502::fNOP_;
   func[0x43] = &m6502::fNOP_;
   func[0x44] = &m6502::fNOP_;
   func[0x45] = &m6502::fEOR_ZP;
   func[0x46] = &m6502::fLSR_ZP;
   func[0x47] = &m6502::fNOP_;
   func[0x48] = &m6502::fPHA;
   func[0x49] = &m6502::fEOR_IMM;
   func[0x4A] = &m6502::fLSR_A;
   func[0x4B] = &m6502::fNOP_;
   func[0x4C] = &m6502::fJMP_ABS;
   func[0x4D] = &m6502::fEOR_ABS;
   func[0x4E] = &m6502::fLSR_ABS;
   func[0x4F] = &m6502::fNOP_;

   func[0x50] = &m6502::fBVC;
   func[0x51] = &m6502::fEOR_IND_Y;
   func[0x52] = &m6502::fNOP_;
   func[0x53] = &m6502::fNOP_;
   func[0x54] = &m6502::fNOP_;
   func[0x55] = &m6502::fEOR_ZP_X;
   func[0x56] = &m6502::fLSR_ZP_X;
   func[0x57] = &m6502::fNOP_;
   func[0x58] = &m6502::fCLI_;
   func[0x59] = &m6502::fEOR_ABS_Y;
   func[0x5A] = &m6502::fNOP_;
   func[0x5B] = &m6502::fNOP_;
   func[0x5C] = &m6502::fNOP_;
   func[0x5D] = &m6502::fEOR_ABS_X;
   func[0x5E] = &m6502::fLSR_ABS_X;
   func[0x5F] = &m6502::fNOP_;

   func[0x60] = &m6502::fRTS;
   func[0x61] = &m6502::fADC_IND_X;
   func[0x62] = &m6502::fNOP_;
   func[0x63] = &m6502::fNOP_;
   func[0x64] = &m6502::fNOP_;
   func[0x65] = &m6502::fADC_ZP;
   func[0x66] = &m6502::fROR_ZP;
   func[0x67] = &m6502::fNOP_;
   func[0x68] = &m6502::fPLA;
   func[0x69] = &m6502::fADC_IMM;
   func[0x6A] = &m6502::fROR_A;
   func[0x6B] = &m6502::fNOP_;
   func[0x6C] = &m6502::fJMP_IND;
   func[0x6D] = &m6502::fADC_ABS;
   func[0x6E] = &m6502::fROR_ABS;
   func[0x6F] = &m6502::fNOP_;

   func[0x70] = &m6502::fBVS;
   func[0x71] = &m6502::fADC_IND_Y;
   func[0x72] = &m6502::fNOP_;
   func[0x73] = &m6502::fNOP_;
   func[0x74] = &m6502::fNOP_;
   func[0x75] = &m6502::fADC_ZP_X;
   func[0x76] = &m6502::fROR_ZP_X;
   func[0x77] = &m6502::fNOP_;
   func[0x78] = &m6502::fSEI;
   func[0x79] = &m6502::fADC_ABS_Y;
   func[0x7A] = &m6502::fNOP_;
   func[0x7B] = &m6502::fNOP_;
   func[0x7C] = &m6502::fNOP_;
   func[0x7D] = &m6502::fADC_ABS_X;
   func[0x7E] = &m6502::fROR_ABS_X;
   func[0x7F] = &m6502::fNOP_;

   func[0x80] = &m6502::fNOP_;
   func[0x81] = &m6502::fSTA_IND_X;
   func[0x82] = &m6502::fNOP_;
   func[0x83] = &m6502::fNOP_;
   func[0x84] = &m6502::fSTY_ZP;
   func[0x85] = &m6502::fSTA_ZP;
   func[0x86] = &m6502::fSTX_ZP;
   func[0x87] = &m6502::fNOP_;
   func[0x88] = &m6502::fDEY;
   func[0x89] = &m6502::fNOP_;
   func[0x8A] = &m6502::fTXA;
   func[0x8B] = &m6502::fNOP_;
   func[0x8C] = &m6502::fSTY_ABS;
   func[0x8D] = &m6502::fSTA_ABS;
   func[0x8E] = &m6502::fSTX_ABS;
   func[0x8F] = &m6502::fNOP_;

   func[0x90] = &m6502::fBCC;
   func[0x91] = &m6502::fSTA_IND_Y;
   func[0x92] = &m6502::fNOP_;
   func[0x93] = &m6502::fNOP_;
   func[0x94] = &m6502::fSTY_ZP_X;
   func[0x95] = &m6502::fSTA_ZP_X;
   func[0x96] = &m6502::fSTX_ZP_Y;
   func[0x97] = &m6502::fNOP_;
   func[0x98] = &m6502::fTYA;
   func[0x99] = &m6502::fSTA_ABS_Y;
   func[0x9A] = &m6502::fTXS;
   func[0x9B] = &m6502::fNOP_;
   func[0x9C] = &m6502::fNOP_;
   func[0x9D] = &m6502::fSTA_ABS_X;
   func[0x9E] = &m6502::fNOP_;
   func[0x9F] = &m6502::fNOP_;

   func[0xA0] = &m6502::fLDY_IMM;
   func[0xA1] = &m6502::fLDA_IND_X;
   func[0xA2] = &m6502::fLDX_IMM;
   func[0xA3] = &m6502::fNOP_;
   func[0xA4] = &m6502::fLDY_ZP;
   func[0xA5] = &m6502::fLDA_ZP;
   func[0xA6] = &m6502::fLDX_ZP;
   func[0xA7] = &m6502::fNOP_;
   func[0xA8] = &m6502::fTAY;
   func[0xA9] = &m6502::fLDA_IMM;
   func[0xAA] = &m6502::fTAX;
   func[0xAB] = &m6502::fNOP_;
   func[0xAC] = &m6502::fLDY_ABS;
   func[0xAD] = &m6502::fLDA_ABS;
   func[0xAE] = &m6502::fLDX_ABS;
   func[0xAF] = &m6502::fNOP_;

   func[0xB0] = &m6502::fBCS;
   func[0xB1] = &m6502::fLDA_IND_Y;
   func[0xB2] = &m6502::fNOP_;
   func[0xB3] = &m6502::fNOP_;
   func[0xB4] = &m6502::fLDY_ZP_X;
   func[0xB5] = &m6502::fLDA_ZP_X;
   func[0xB6] = &m6502::fLDX_ZP_Y;
   func[0xB7] = &m6502::fNOP_;
   func[0xB8] = &m6502::fCLV_;
   func[0xB9] = &m6502::fLDA_ABS_Y;
   func[0xBA] = &m6502::fTSX;
   func[0xBB] = &m6502::fNOP_;
   func[0xBC] = &m6502::fLDY_ABS_X;
   func[0xBD] = &m6502::fLDA_ABS_X;
   func[0xBE] = &m6502::fLDX_ABS_Y;
   func[0xBF] = &m6502::fNOP_;

   func[0xC0] = &m6502::fCPY_IMM;
   func[0xC1] = &m6502::fCMP_IND_X;
   func[0xC2] = &m6502::fNOP_;
   func[0xC3] = &m6502::fNOP_;
   func[0xC4] = &m6502::fCPY_ZP;
   func[0xC5] = &m6502::fCMP_ZP;
   func[0xC6] = &m6502::fDEC_ZP;
   func[0xC7] = &m6502::fNOP_;
   func[0xC8] = &m6502::fINY;
   func[0xC9] = &m6502::fCMP_IMM;
   func[0xCA] = &m6502::fDEX;
   func[0xCB] = &m6502::fNOP_;
   func[0xCC] = &m6502::fCPY_ABS;
   func[0xCD] = &m6502::fCMP_ABS;
   func[0xCE] = &m6502::fDEC_ABS;
   func[0xCF] = &m6502::fNOP_;

   func[0xD0] = &m6502::fBNE;
   func[0xD1] = &m6502::fCMP_IND_Y;
   func[0xD2] = &m6502::fNOP_;
   func[0xD3] = &m6502::fNOP_;
   func[0xD4] = &m6502::fNOP_;
   func[0xD5] = &m6502::fCMP_ZP_X;
   func[0xD6] = &m6502::fDEC_ZP_X;
   func[0xD7] = &m6502::fNOP_;
   func[0xD8] = &m6502::fCLD_;
   func[0xD9] = &m6502::fCMP_ABS_Y;
   func[0xDA] = &m6502::fNOP_;
   func[0xDB] = &m6502::fNOP_;
   func[0xDC] = &m6502::fNOP_;
   func[0xDD] = &m6502::fCMP_ABS_X;
   func[0xDE] = &m6502::fDEC_ABS_X;
   func[0xDF] = &m6502::fNOP_;

   func[0xE0] = &m6502::fCPX_IMM;
   func[0xE1] = &m6502::fSBC_IND_X;
   func[0xE2] = &m6502::fNOP_;
   func[0xE3] = &m6502::fNOP_;
   func[0xE4] = &m6502::fCPX_ZP;
   func[0xE5] = &m6502::fSBC_ZP;
   func[0xE6] = &m6502::fINC_ZP;
   func[0xE7] = &m6502::fNOP_;
   func[0xE8] = &m6502::fINX;
   func[0xE9] = &m6502::fSBC_IMM;
   func[0xEA] = &m6502::fNOP_;
   func[0xEB] = &m6502::fNOP_ ;
   func[0xEC] = &m6502::fCPX_ABS;
   func[0xED] = &m6502::fSBC_ABS;
   func[0xEE] = &m6502::fINC_ABS;
   func[0xEF] = &m6502::fNOP_;

   func[0xF0] = &m6502::fBEQ;
   func[0xF1] = &m6502::fSBC_IND_Y;
   func[0xF2] = &m6502::fNOP_;
   func[0xF3] = &m6502::fNOP_;
   func[0xF4] = &m6502::fNOP_;
   func[0xF5] = &m6502::fSBC_ZP_X;
   func[0xF6] = &m6502::fINC_ZP_X;
   func[0xF7] = &m6502::fNOP_;
   func[0xF8] = &m6502::fSED;
   func[0xF9] = &m6502::fSBC_ABS_Y;
   func[0xFA] = &m6502::fNOP_;
   func[0xFB] = &m6502::fNOP_;
   func[0xFC] = &m6502::fNOP_;
   func[0xFD] = &m6502::fSBC_ABS_X;
   func[0xFE] = &m6502::fINC_ABS_X;
   func[0xFF] = &m6502::fNOP_;
}

//OpCodes  for 6502
//*************************inline instructions*************************
void m6502::fNOP_(void)  {tick(2);}		//do nothing

//*********************direct flag operation***************************
void m6502::fCLC_(void) {c = 0; tick(2);}
void m6502::fSEC(void) {c = 1; tick(2);}
void m6502::fSEI(void) {i_ = 1; tick(2);}
void m6502::fCLI_(void){i_ = 0; tick(2);}
void m6502::fSED(void) {d = 1; tick(2);}
void m6502::fCLD_(void) {d = 0; tick(2);}
void m6502::fCLV_(void) {v = 0; tick(2);}
//*****************exchange registers**********************************
void m6502::fTSX(void) {x = s;n = (x>>7)&0x01; z = (x==0)?1:0;tick(2);}
void m6502::fTAX(void) {x = a;n = (x>>7)&0x01; z = (x==0)?1:0;tick(2);}
void m6502::fTAY(void) {y = a;n = (y>>7)&0x01; z = (y==0)?1:0;tick(2);}
void m6502::fTXA(void) {a = x;n = (x>>7)&0x01; z = (x==0)?1:0;tick(2);}
void m6502::fTYA(void) {a = y;n = (y>>7)&0x01; z = (y==0)?1:0;tick(2);}
void m6502::fTXS(void) {s = x;tick(2);}
void m6502::fDEX(void) {--x; n = (x>>7)&0x01; z = (x==0)?1:0; tick(2);}
void m6502::fDEY(void) {--y; n = (y>>7)&0x01; z = (y==0)?1:0; tick(2);}
void m6502::fINY(void) {++y; n = (y>>7)&0x01; z = (y==0)?1:0; tick(2);}
void m6502::fINX(void) {++x;n = (x>>7)&0x01; z = (x==0)?1:0; tick(2);}

//***************************push and pop********************************
void m6502::fPHP(void)
{
   //I have implement the flags as seperate variables so I must
   //recombine them here
   int p = (n<<7)+(v<<6)+(b<<4)+(d<<3)+(i_<<2)+(z<<1)+(c);
   ram[SP + s--] = p;
   tick(3);
}

void m6502::fPLP(void)
{
   int p = Word(ram[SP + ++s]);
   n = (p>>7)&0x01;
   v = (p>>6)&0x01;
   b = (p>>4)&0x01;
   d = (p>>3)&0x01;
   i_ = (p>>2)&0x01;
   z = (p>>1)&0x01;
   c = p&0x01;
   tick(4);
}

void m6502::fPHA(void) {ram[SP + s--] = a;tick(3);}
void m6502::fPLA(void) {a = ram[SP + ++s]; z = (a)?1:0;
			n = (a>>7)&0x01; tick(4);}

//********************Program flow chages*********************************
//verified 05/18/94 using jsrtest.asm
void m6502::fJSR(void)
{
   ram[SP + s--] = ((pc+1)>>8)&0xff;
   ram[SP + s--] = (pc+1)&0xff;
   pc = Word(ram[pc])+(Word(ram[pc+1])<<8);
   tick(6);
   steal_jsr(pc);
}
//currently I abort on brk
void m6502::fBRK(void) {b = 1; interrupt_();tick(7);}

//verified 05/18/94 using jsrtest.asm
void m6502::fRTS(void)
{
   pc = Word(ram[SP + ++s]);
   pc += (Word(ram[SP + ++s])<<8);
   pc++;
   tick(6);
}

void m6502::fRTI(void)
{
   fPLP();
   pc = Word(ram[SP + ++s]);
   pc += (Word(ram[SP + ++s])<<8);
   tick(6);
}
//verified 05/18/94 using jsrtest.asm
void m6502::fJMP_ABS(void) {pc = Word(ram[pc])+(Word(ram[pc+1])<<8);tick(3);}

//verified 05/18/94 using jsrtest.asm
void m6502::fJMP_IND(void)
{address = Word(ram[pc++]);address += Word(ram[pc])<<8;
pc = Word(ram[address])+(Word(ram[address+1])<<8);
tick(5);}

//brk functions verified using brktest.asm 05/19/94
void m6502::fBVC(void) {if (!v) pc += int((signed char)(ram[pc]));pc++;tick(2);}
void m6502::fBVS(void) {if (v) pc += int((signed char)(ram[pc]));pc++;tick(2);}
void m6502::fBCC(void){if (!c) pc += int((signed char)(ram[pc]));pc++;tick(2);}
void m6502::fBCS(void){if (c) pc += int((signed char)(ram[pc]));pc++;tick(2);}

//verified 05/18/94 using jsrtest.asm
void m6502::fBNE(void){if (!z) pc += int((signed char)(ram[pc]));pc++;tick(2);}

//verified 05/18/94 using jsrtest.asm
void m6502::fBEQ(void){if (z) pc += int((signed char)(ram[pc]));pc++;tick(2);}

void m6502::fBMI(void){if (n) pc += int((signed char)(ram[pc]));pc++;tick(2);}
void m6502::fBPL(void){if (!n) pc += int((signed char)(ram[pc]));pc++;tick(2);}

//**********************ORA*******************************************
void m6502::fORA_IND_X(void)
{
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];
   register int acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(6);
}

void m6502::fORA_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(3);
}

void m6502::fORA_IMM(void)
{
   operand = ram[pc++];		//get immediate operand
   a = a|operand;
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(2);
}

void m6502::fORA_ABS(void)
{
   register int acc;
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}

void m6502::fORA_IND_Y(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(5);
}

void m6502::fORA_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}

void m6502::fORA_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}

void m6502::fORA_ABS_Y(void)
{
   register int acc;
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   acc = a|operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}

//**********************EOR*******************************************
void m6502::fEOR_IND_X(void)
{
   register int acc;
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(6);
}
void m6502::fEOR_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(3);
}
void m6502::fEOR_IMM(void)
{
   operand = ram[pc++];		//get immediate operand
   a = a^operand;
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(2);
}
void m6502::fEOR_ABS(void)
{
   register int acc;
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8);
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fEOR_IND_Y(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(5);
}
void m6502::fEOR_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fEOR_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fEOR_ABS_Y(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   acc = a^operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}

//**********************AND********************************************
void m6502::fAND_IND_X(void)
{
   register int acc;
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(6);
}
void m6502::fAND_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(3);
}
void m6502::fAND_IMM(void)
{
   operand = ram[pc++];		//get immediate operand
   a = a&operand;
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(2);
}
void m6502::fAND_ABS(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fAND_IND_Y(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(5);
}
void m6502::fAND_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fAND_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fAND_ABS_Y(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   acc = a&operand;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
//**********************ADC********************************************
void m6502::fADC_IND_X(void)
{
   register int acc, acch, accl;
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];

   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x1;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(6);
}

void m6502::fADC_ZP(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(3);
}

void m6502::fADC_IMM(void)
{
   register int acc, acch, accl;
   operand = ram[pc++];		//get immediate operand
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(2);
}

void m6502::fADC_ABS(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   if (!d)
      acc = unsigned(a)+unsigned(operand)+unsigned(c);
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fADC_IND_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(5);
}

void m6502::fADC_ZP_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fADC_ABS_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);
   address += ((Word(ram[pc++])<<8)+x);
   operand = ram[address];
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fADC_ABS_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   if (!d)
      acc = a+operand+c;
   else
   {
       acc = DEC(a)+DEC(operand)+c;
       acch = acc%100;
       accl = acch%10;
       acc = ((acc>acch)<<8) + ((acch/10)<<4) + accl;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = (operand>>7)&0x01;
   a = Byte(acc);
   //only effects two flags
   z = (a==0);
   c = ((acc&0x100)!=0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

//**********************SBC********************************************
//**STATUS:
//** The routines for the flags appear to be correct
//*********************************************************************
void m6502::fSBC_IND_X(void)
{
   register int acc, acch, accl;
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {
       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }

   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effcts three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(6);
}

void m6502::fSBC_ZP(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(3);
}

void m6502::fSBC_IMM(void)
{
   register int acc, acch, accl;
   operand = ram[pc++];		//get immediate operand
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(2);
}

void m6502::fSBC_ABS(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fSBC_IND_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(5);
}

void m6502::fSBC_ZP_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fSBC_ABS_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

void m6502::fSBC_ABS_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   if (!d)
   {
      acc = int(a - operand - !c);
      if (acc<0) {acc += 0x100; c = 0;}
      else c = 1;
   }
   else
   {

       acc = DEC(a) - DEC(operand) - !c;
       if (acc<0) {acc += 100; c = 0;}
       else c = 1;
       acch = acc/100;
       accl = acc/10;
       acc = ((acch!=0)*0x100) + (accl<<4) + acc%10;
       a = acc&0xff;
   }
   n = (acc>>7)&0x01;
   Byte a7 = (a>>7)&0x01;
   Byte o7 = !((operand>>7)&0x01);
   a = Byte(acc);
   //only effects three flags
   z = (a==0);
   v =  (a7 & o7 & (!n)) || ((!a7) & (!o7) & n);
   tick(4);
}

//**********************CMP********************************************
void m6502::fCMP_IND_X(void)
{
   register int acc, acch, accl;
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}
void m6502::fCMP_ZP(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(3);
}
void m6502::fCMP_IMM(void)
{
   register int acc, acch, accl;
   operand = ram[pc++];		//get immediate operand
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(2);
}
void m6502::fCMP_ABS(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(4);
}
void m6502::fCMP_IND_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(5);
}

void m6502::fCMP_ZP_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   operand = ram[address];

   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(4);
}

void m6502::fCMP_ABS_X(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(4);
}

void m6502::fCMP_ABS_Y(void)
{
   register int acc, acch, accl;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+y;
   operand = ram[address];
   acc = int(a-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;

   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;

   tick(4);
}

void m6502::fCPY_ABS(void)
{
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8); operand = ram[address];
   register int acc;;
   acc = int(y-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
   tick(4);
}
void m6502::fCPY_ZP(void)
{   operand = ram[Word(ram[pc++])];
   register int acc;;
   acc = int(y-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
    tick(3);
}

void m6502::fCPY_IMM(void)
{   operand = ram[pc++];
   register int acc;;
   acc = int(y-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
    tick(2);
}

void m6502::fCPX_ABS(void)
{
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8); operand = ram[address];
   register int acc;;
   acc = int(x-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
   tick(4);
}
void m6502::fCPX_ZP(void)
{   operand = ram[Word(ram[pc++])];
    register int acc;;
   acc = int(x-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
    tick(3);
}

void m6502::fCPX_IMM(void)
{   operand = ram[pc++];
   register int acc;;
   acc = int(x-operand);
   if (acc<0) {acc += 0x100; c = 0;}
   else c = 1;
   z = ((acc&0xff)==0); n = (a>>7)&0x01;
    tick(2);
}

//************************ASL*****************************************
void m6502::fASL_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = operand<<1;
   write_ram( Byte(acc));
   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(5);
}

void m6502::fASL_A(void)
{
   register int acc;
   acc = a<<1;
   a = Byte(acc);
   //effects three flags
   z = (a==0);
   n = (a>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(2);
}


void m6502::fASL_ABS(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   acc = operand<<1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(6);
}



void m6502::fASL_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++])+x;
   operand = ram[address];
   acc = operand<<1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(6);
}

void m6502::fASL_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = operand<<1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(7);
}

//************************LSR*****************************************
void m6502::fLSR_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = operand>>1;
   c = operand&0x1;
   write_ram( Byte(acc));
   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(5);
}

void m6502::fLSR_A(void)
{
   register int acc;
   c = a&0x1;
   acc = a>>1;
   a = Byte(acc);
   //effects three flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(2);
}


void m6502::fLSR_ABS(void)
{
   register int acc;
   address = Word(ram[pc++])+(Word(ram[pc++])<<8);
   operand = ram[address];
   acc = operand>>1;
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fLSR_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++])+x;
   operand = ram[address];
   acc = operand>>1;
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fLSR_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++])+(Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = operand>>1;
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(7);
}

//************************ROL*****************************************
void m6502::fROL_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = (operand<<1)|c;
   write_ram( Byte(acc));
   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(5);
}

void m6502::fROL_A(void)
{
   register int acc;
   acc = (a<<1)|c;
   a = Byte(acc);
   //effects three flags
   z = (a==0);
   n = (a>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(2);
}


void m6502::fROL_ABS(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8);
   operand = ram[address];
   acc = (operand<<1)|c;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(6);
}

void m6502::fROL_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++])+x;
   operand = ram[address];
   acc = (operand<<1)|c;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(6);
}

void m6502::fROL_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]); address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = (operand<<1)|c;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(7);
}

//************************ROR*****************************************
void m6502::fROR_ZP(void)
{
   register int acc;
   address = Word(ram[pc++]);		//get zero page address
   operand = ram[address];
   acc = (operand>>1)|(c<<7);
   c = operand&0x1;
   write_ram( Byte(acc));
   //only effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(5);
}

void m6502::fROR_A(void)
{
   register int acc;
   acc = (a>>1)|(c<<7);
   c = a&0x1;
   a = Byte(acc);
   //effects three flags
   z = (a==0);
   n = (a>>7)&0x01;
   c = ((acc&0x100)!=0);
   tick(2);
}


void m6502::fROR_ABS(void)
{
   register int acc;
   address = Word(ram[pc++])+(Word(ram[pc++])<<8);
   operand = ram[address];
   acc = (operand>>1)|(c<<7);
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fROR_ZP_X(void)
{
   register int acc;
   address = Word(ram[pc++])+x;
   operand = ram[address];
   acc = (operand>>1)|(c<<7);
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fROR_ABS_X(void)
{
   register int acc;
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   operand = ram[address];
   acc = (operand>>1)|(c<<7);
   c = operand&0x1;
   write_ram( Byte(acc));
   //effects three flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(7);
}

void m6502::fBIT_ZP(void)
{
   operand = ram[pc++];
   z = ((a&operand)==0);
   n = ((operand&b7)!=0);
   v = ((operand&b6)!=0);
   tick(2);
}

void m6502::fBIT_ABS(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8);
   operand = ram[address];
   z = ((a&operand)==0); n = ((operand&b7)!=0); v = ((operand&b6)!=0);
   tick(4);
 }

//**********************STA********************************************
void m6502::fSTA_IND_X(void)
{
   address = (Word(ram[pc++])+x)&0xff;	//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   write_ram();		//ram[address] = a
   tick(6);
}
void m6502::fSTA_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   write_ram();		//ram[address] = a
   tick(3);
}
void m6502::fSTA_ABS(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8);
   write_ram();		//ram[address] = a
   tick(4);
}
void m6502::fSTA_IND_Y(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   write_ram();		//ram[address] = a
   tick(6);
}
void m6502::fSTA_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   write_ram();		//ram[address] = a
   tick(4);
}
void m6502::fSTA_ABS_X(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   write_ram();		//ram[address] = a
   tick(5);
}
void m6502::fSTA_ABS_Y(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+y;
   write_ram();		//ram[address] = a
   tick(5);
}

//**********************LDA*******************************************
void m6502::fLDA_IND_X(void)
{
   address = (Word(ram[pc++])+x)&0xff;		//discard carry
   address = Word(ram[address])+(Word(ram[address+1])<<8);  //(ind,x)
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(6);
}
void m6502::fLDA_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   a = ram[address];
   //effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(3);
}
void m6502::fLDA_IMM(void)
{
   a = Word(ram[pc++]);		//get immediate operand
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(2);
}
void m6502::fLDA_ABS(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fLDA_IND_Y(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = Word(ram[address])+(Word(ram[address+1])<<8)+y;
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(6);
}

void m6502::fLDA_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(4);
}
void m6502::fLDA_ABS_X(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(5);
}
void m6502::fLDA_ABS_Y(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+y;
   a = ram[address];
   //only effects two flags
   z = (a==0);
   n = (a>>7)&0x01;
   tick(5);
}

//**********************STY********************************************
void m6502::fSTY_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   write_ram(y);		//ram[address] = a
   tick(4);
}
void m6502::fSTY_ABS(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8);
   write_ram(y);		//ram[address] = a
   tick(4);
}
void m6502::fSTY_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   write_ram(y);		//ram[address] = a
   tick(3);
}

//**********************STX********************************************
void m6502::fSTX_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   write_ram(x);		//ram[address] = a
   tick(4);
}

void m6502::fSTX_ZP_Y(void)
{
   address = (Word(ram[pc++])+y)&0xffff;
   write_ram(x);		//ram[address] = a
   tick(4);
}
void m6502::fSTX_ABS(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8);
   write_ram(x);		//ram[address] = a
   tick(3);
}

//**********************LDY*******************************************
void m6502::fLDY_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   y = ram[address];
   //effects two flags
   z = (y==0);
   n = (y>>7)&0x01;
   tick(3);
}
void m6502::fLDY_IMM(void)
{
   y = Word(ram[pc++]);		//get immediate operand
   //only effects two flags
   z = (y==0);
   n = (y>>7)&0x01;
   tick(2);
}
void m6502::fLDY_ABS(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   y = ram[address];
   //only effects two flags
   z = (y==0);
   n = (y>>7)&0x01;
   tick(4);
}

void m6502::fLDY_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   y = ram[address];
   //only effects two flags
   z = (y==0);
   n = (y>>7)&0x01;
   tick(3);
}
void m6502::fLDY_ABS_X(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   y = ram[address+x];
   //only effects two flags
   z = (y==0);
   n = (y>>7)&0x01;
   tick(4);
}

//**********************LDX*******************************************
void m6502::fLDX_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   x = ram[address];
   //effects two flags
   z = (x==0);
   n = (x>>7)&0x01;
   tick(3);
}
void m6502::fLDX_IMM(void)
{
   x = Word(ram[pc++]);		//get immediate operand
   //only effects two flags
   z = (x==0);
   n = (x>>7)&0x01;
   tick(2);
}
void m6502::fLDX_ABS(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   x = ram[address];
   //only effects two flags
   z = (x==0);
   n = (x>>7)&0x01;
   tick(4);
}
void m6502::fLDX_ABS_Y(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   x = ram[address+y];
   //only effects two flags
   z = (x==0);
   n = (x>>7)&0x01;
   tick(3);
}
void m6502::fLDX_ZP_Y(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+y)&0xff;
   x = ram[address];
   //only effects two flags
   z = (x==0);
   n = (x>>7)&0x01;
   tick(4);
}

//**********************DEC*******************************************
void m6502::fDEC_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   register int acc = (ram[address])-1;
   write_ram(address,acc);
   //effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(5);
}
void m6502::fDEC_ABS(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   register int acc = (ram[address])-1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fDEC_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   register int acc = (ram[address])-1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}
void m6502::fDEC_ABS_X(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   register int acc = (ram[address])-1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(7);
}

//**********************INC*******************************************
void m6502::fINC_ZP(void)
{
   address = Word(ram[pc++]);		//get zero page address
   register int acc = (ram[address])+1;
   write_ram(address,acc);

   //effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(5);
}
void m6502::fINC_ABS(void)
{
   address = Word(ram[pc++]);
   address +=(Word(ram[pc++])<<8);
   register int acc = (ram[address])+1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}

void m6502::fINC_ZP_X(void)
{
   address = Word(ram[pc++]);		//get zero page address
   address = (address+x)&0xff;
   register int acc = (ram[address])+1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(6);
}
void m6502::fINC_ABS_X(void)
{
   address = Word(ram[pc++]);
   address += (Word(ram[pc++])<<8)+x;
   register int acc = (ram[address])+1;
   write_ram(address,acc);
   //only effects two flags
   z = ((acc&0xff)==0);
   n = (acc>>7)&0x01;
   tick(7);
}
