Logo  

Home - Old Man Programmer

Displaying demos/hack/hack.html

<!DOCTYPE html>
<html>
<head>
 <title> Hacking </title>
 <meta charset='utf-8'>
 <link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet"> 
 <style>
 * { font-family: "Arial"; }
 body {
   background: black;
   overflow: hidden;
 }
 #title {
   font-family: 'VT323', monospace;
   margin: .5in auto 0;
   font-size: 50px;
   text-align: center;
 }
 .progress {
   position: absolute;
   top: 40vh;
   left: 10vw;
   height: 20vh;
   width: 80vw;
   color: green;
 }
 .ptext {
   font-family: 'VT323', monospace;
   padding-top: 25px;
   font-size: 100px;
   text-align: center;
 }
 #codebox {
   position: absolute;
   top: 0px;
   left: 0px;
   width: 100vw;
   height: 100vw;
   overflow: hidden;
   z-index: -1;
 }
 #code {
   margin-left: 1in;
   color: green;
   position: relative;
   font-family: 'VT323', monospace;
   font-size: 36pt;
   white-space: pre;
 }
 #message {
   position: absolute;
   font-family: 'VT323', monospace;
   color: red;
   font-size: 50px;
   top: 65vh;
   width: 100vw;
   margin: 0 auto;
   text-align: center;
 }
 </style>
 <script>
 var messages=[
   "Initializing...", "Bypassing antivirus", "Overflowing buffers",
   "Injecting code", "Rooting devices", "pwning systems", "Installing rootkits",
   "Covering up evidence"
 ];
 var pwd="313374DEADBEEF11";
 var hex="0123456789ABCDEF";
 
 var progressspeed=.05;
 var codescroll=10;
 var coderotspeed=.01;
 
 var codep=0, codeh, coderot = 0, codefs=24;
 var pro=0;
 var hsize=50, hdir=1;
 function animate() {
   if (hsize > 200) hdir=-1;
   if (hsize < 50) hdir=1;
   hsize+=hdir;
   red=Math.floor(2.55*hsize);
   var t = document.getElementById("title");
   t.style.fontSize = hsize + "px";
   t.style.color = "rgb("+red+",0,0)";
   if (pro <= 100) {
     pro+=progressspeed;
     document.getElementById("progress").value = Math.min(100,pro);
     var p=Math.floor(16*(pro/100));
     var i, s = "0x";
     for(i=0; i < p; i++) s += pwd[i];
     for(;i < 16; i++) s += hex[Math.floor(Math.random()*16)];
     document.getElementById("pwd").innerHTML = s;
     var msg=Math.floor(messages.length*(pro/100));
     document.getElementById("message").innerHTML = "Status: " + messages[msg];
   } else {
     document.getElementById("message").innerHTML = "Status: Hacking complete!";
   }
   codep -= codescroll;
   coderot += coderotspeed;
   var c = document.getElementById("code")
   c.style.top = codep + "px";
   document.getElementById("codebox").style.transform = "rotate("+coderot+"deg)";
 }
 function start() {
   codeh = document.getElementById("code").clientHeight;
   setInterval(animate,20);
 }
 </script>
</head>
<body onload='start();'>
<div id='title'> !!HACKING!! </div>
<progress class='progress' id='progress' min=0 max=100 value=0></progress>
<div id='pwd' class='progress ptext'> 0x0000000000000000</div>
<div id='message'> Status: Initializing... </div>
<div id='codebox'>
<div id='code'>
#include "c64.h"
#include "instr.h"

/*
+-+-+-+-+-+-+-+-+
|N|V| |B|D|I|Z|C|  PROCESSOR STATUS REG "P"
+-+-+-+-+-+-+-+-+
 | |   | | | | |
 | |   | | | | +>  CARRY         1=TRUE
 | |   | | | +-->  ZERO          1=RESULT ZERO
 | |   | | +---->  IRQ DISABLE   1=DISABLE
 | |   | +------>  DECIMAL MODE  1=TRUE
 | |   +-------->  BRK COMMAND
 | |
 | +------------>  OVERFLOW      1=TRUE
 +-------------->  NEGATIVE      1=NEG
*/

extern FILE *_log, *_ilog;
extern FILE *_cialog;
extern struct writelog _wlog[10];
extern int _widx;
extern int _timerA1, _timerA1L, _keydown;
extern uint8_t _ics1;

enum {
  P_CARRY = 1, P_ZERO = 2, P_IRQDIS = 4, P_DECIMAL = 8, P_BRK = 16,
  P_OVERFLOW = 64, P_NEGATIVE = 128
};
uint16_t _PC;
uint8_t _A, _X, _Y, _S, _P, _IR;
int _HWIRQ = 0, _NMI = 0;

extern struct memory _page[64];

int crosspage(uint16_t addr1, uint16_t addr2)
{
  return (addr1&0xFF00) != (addr2&0xFF00);
}

uint8_t immediate_value(void)
{
  uint8_t v = load(_PC++);
  if (_log) fprintf(_log, "#%d", v);
  return v;
}

uint16_t immediate(void)
{
  uint16_t addr = _PC++;
  if (_log) fprintf(_log, "#%d", load(addr));
  return addr;
}

uint16_t branchaddr(int *cpb)
{
  int8_t v = (int8_t)load(_PC++);
  uint16_t addr;
  addr = _PC + v;
  if (_log) fprintf(_log, "%04X", addr);
  if (cpb) *cpb = crosspage(_PC-1, addr);
  return addr;
}

/* Absolute */
uint16_t absolute(void)
{
  uint16_t addr;
  uint8_t l, h;
  l = load(_PC++);
  h = load(_PC++);
  addr = (h<<8 | l);
  if (_log) fprintf(_log, "%04X",addr);
  return addr;
}

/* Absolute,[X|Y] */
uint16_t absolute_indexed(uint8_t idx)
{
  uint16_t addr;
  uint8_t l, h;
  l = load(_PC++);
  h = load(_PC++);
  addr = (h<<8 | l);
//  if (_P & P_CARRY) idx++;
  if (_log) fprintf(_log, "%04X,%d",addr, idx);
  return addr + idx;
}

/* Zero-page[,X|Y] */
uint16_t zero_page(uint8_t idx)
{
  uint8_t l;
  l = load(_PC++);
  if (_log) fprintf(_log, "%02X,%d", l, idx);
  l += idx;
  return (0x0000 | l);
}

/* (Zero-page),Y */
uint16_t indirect_indexed(void)
{
  uint16_t addr;
  uint8_t l, h;
  l = load(_PC++);
  addr = (0x0000 | l);
  if (_log) fprintf(_log, "(%02X),Y:%d",l, _Y);
  l = load(addr);
  h = load(addr+1);
  return (h<<8|l) + _Y;
}

/* (Zero-page,X) */
uint16_t indexed_indirect()
{
  uint16_t addr;
  uint8_t l, h;
  l = load(_PC++) + _X;
  addr = 0x0000 | l;
  if (_log) fprintf(_log, "(%02X,X:%d)\n",l, _X);
  l = load(addr);
  h = load(addr+1);
  return (h<<8|l);
}

void push(uint8_t data)
{
  store(0x0100|_S--,data);
}

uint8_t pop()
{
  return load(0x0100|++_S);
}

void adc(uint16_t addr)
{
  uint8_t m = load(addr), r;
  int v;

  v = _A + m + ((_P&P_CARRY)? 1 : 0);
  r = _A + m + (uint8_t)((_P&P_CARRY)? 1 : 0);
  _P &= ~(P_CARRY|P_NEGATIVE|P_ZERO|P_OVERFLOW);
  if (((_A^r)&0x80) && ((m^r)&0x80)) _P |= P_OVERFLOW;
  if (v > 255) _P |= P_CARRY;
  if (r == 0) _P |= P_ZERO;
  if (r&0x80) _P |= P_NEGATIVE;
  _A = r;
}

void sbc(uint16_t addr)
{
  uint8_t m = load(addr), r;
  int v;

  m = 255 - m;
  v = _A + m + ((_P&P_CARRY)? 1 : 0);
  r = _A + m + (uint8_t)((_P&P_CARRY)? 1 : 0);
  _P &= ~(P_CARRY|P_NEGATIVE|P_ZERO|P_OVERFLOW);
  if (((_A^r)&0x80) && ((m^r)&0x80)) _P |= P_OVERFLOW;
  if (v > 255) _P |= P_CARRY;
  if (r == 0) _P |= P_ZERO;
  if (r&0x80) _P |= P_NEGATIVE;
  _A = r;
}

uint8_t ror(uint8_t m)
{
  int c = _P & P_CARRY;
  _P &= ~(P_CARRY|P_ZERO|P_NEGATIVE);
  if (m & 0x01) _P |= P_CARRY;
  m >>= 1;
  if (c) m |= 0x80;
  else m &= 0x7F;
  if (m == 0) _P |= P_ZERO;
  if (m & 0x80) _P |= P_NEGATIVE;
  return m;
}

uint8_t rol(uint8_t m)
{
  int c = _P & P_CARRY;
  _P &= ~(P_CARRY|P_ZERO|P_NEGATIVE);
  if (m & 0x80) _P |= P_CARRY;
  m <<= 1;
  if (c) m |= 0x01;
  if (m == 0) _P |= P_ZERO;
  if (m & 0x80) _P |= P_NEGATIVE;
  return m;
}

uint8_t lsr(uint8_t m)
{
  _P &= ~(P_ZERO | P_CARRY | P_NEGATIVE);
  if (m & 0x01) _P |= P_CARRY;
  m>>=1;
  if (m == 0) _P |= P_ZERO;
  return m;
}

uint8_t asl(uint8_t m)
{
  _P &= ~(P_ZERO | P_CARRY | P_NEGATIVE);
  if (m & 0x80) _P |= P_CARRY;
  m<<=1;
  if (m == 0) _P |= P_ZERO;
  if (m & 0x80) _P |= P_NEGATIVE;
  return m;
}

void ora(uint16_t addr)
{
  uint8_t m = load(addr);
  _A |= m;
  _P &= ~(P_NEGATIVE|P_ZERO);
  if (_A == 0) _P |= P_ZERO;
  if (_A & 0x80) _P |= P_NEGATIVE;
}

void lda(uint16_t addr)
{
  _A = load(addr);
  _P &= ~(P_NEGATIVE | P_ZERO);
  if (_A == 0) _P |= P_ZERO;
  if (_A & 0x80) _P |= P_NEGATIVE;
}

void ldx(uint16_t addr)
{
  _X = load(addr);
  _P &= ~(P_NEGATIVE | P_ZERO);
  if (_X == 0) _P |= P_ZERO;
  if (_X & 0x80) _P |= P_NEGATIVE;
}

void ldy(uint16_t addr)
{
  _Y = load(addr);
  _P &= ~(P_NEGATIVE | P_ZERO);
  if (_Y == 0) _P |= P_ZERO;
  if (_Y & 0x80) _P |= P_NEGATIVE;
}

void inc(uint16_t addr)
{
  uint8_t m = load(addr);
  _P &= ~(P_ZERO | P_NEGATIVE);
  m++;
  if (m == 0) _P |= P_ZERO;
  if (m & 0x80) _P |= P_NEGATIVE;
  store(addr, m);
}

void dec(uint16_t addr)
{
  uint8_t m = load(addr);
  _P &= ~(P_ZERO | P_NEGATIVE);
  m--;
  if (m == 0) _P |= P_ZERO;
  if (m & 0x80) _P |= P_NEGATIVE;
  store(addr, m);
}

void eor(uint16_t addr)
{
  uint8_t m = load(addr);
  _P &= ~(P_ZERO | P_NEGATIVE);
  _A ^= m;
  if (_A == 0) _P |= P_ZERO;
  if (_A & 0x80) _P |= P_NEGATIVE;
}

/* a = register, b = memory */
void cmp(uint8_t a, uint16_t addr)
{
  uint8_t b = load(addr);
  if (_log) fprintf(_log," (%d/%d) ",a,b);
  _P &= ~(P_ZERO | P_NEGATIVE | P_CARRY);
  if (a == b) _P |= P_ZERO;
  if (a >= b) _P |= P_CARRY;
  a = a-b;
  if (a&0x80) _P |= P_NEGATIVE;
}

void and(uint16_t addr)
{
  uint8_t m = load(addr);
  _P &= ~(P_ZERO | P_NEGATIVE);
  _A &= m;
  if (_A == 0) _P |= P_ZERO;
  if (_A & 0x80) _P |= P_NEGATIVE;  
}

char *status(uint8_t P)
{
  static char f[8];
  f[0] = P & P_NEGATIVE? 'N' : '-';
  f[1] = P & P_ZERO? 'Z' : '-';
  f[2] = P & P_CARRY? 'C' : '-';
  f[3] = P & P_IRQDIS? 'I' : '-';
  f[4] = P & P_DECIMAL? 'D' : '-';
  f[5] = P & P_OVERFLOW? 'V' : '-';
  f[6] = 0;
  return f;
}

int run() {
  int i, cycles = 0, clocks = 0;
  uint16_t addr;
  uint8_t l, h;
  while(1) {
    _IR = load(_PC++);
    if (_log) fprintf(_log, "%04X %02X:%s ", _PC-1, _IR, _instr[_IR]);

    switch(_IR) {
      case 0x00: // BRK
	_PC++;
	push(_PC>>8);
	push(_PC&0xFF);
	push(_P | P_BRK);
	_P |= P_IRQDIS;
	_PC = load(0x0317)<<8 | load(0x0316);
	cycles = 7;
	break;
      case 0x01: // ORA (Indirect,X)
	ora(indexed_indirect());
	cycles = 6;
	break;
      case 0x05: // ORA Zero-page
	ora(zero_page(0));
	cycles = 3;
	break;
      case 0x06: // ASL Zero-page
	l = asl(load(addr = zero_page(0)));
	store(addr, l);
	cycles = 5;
	break;
      case 0x08: // PHP
	push(_P);
	cycles = 3;
	break;
      case 0x09: // ORA Immediate
	ora(immediate());
	cycles = 2;
	break;
      case 0x0A: // ASL Accumulator
	_A = asl(_A);
	cycles = 2;
	break;
      case 0x0D: // ORA Absolute
	ora(absolute());
	cycles = 4;
	break;
      case 0x0E: // ASL Absolute
	l = asl(load(addr = absolute()));
	store(addr, l);
	cycles = 6;
	break;
      case 0x10: // BPL
	l = immediate_value();
	cycles = 2;
	if (!(_P & P_NEGATIVE)) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0x11: // ORA (Indirect),Y
	ora(indirect_indexed());
	cycles = 5;
	break;
      case 0x15: // ORA Zero-Page,X
	ora(zero_page(_X));
	cycles = 4;
	break;
      case 0x16: // ASL Zero-Page,X
	l = asl(load(addr = zero_page(_X)));
	store(addr, l);
	cycles = 6;
	break;
      case 0x18: // CLC
	_P &= ~P_CARRY;
	cycles = 2;
	break;
      case 0x19: // ORA Absolute,Y
	ora(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x1D: // ORA Absolute,X
	ora(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0x1E: // ASL Absolute,X
	l = asl(load(addr = absolute_indexed(_X)));
	store(addr, l);
	cycles = 7;
	break;
      case 0x20: // JSR
	addr = _PC+1;
	push(addr>>8);
	push(addr&0xFF);
	_PC = absolute();
	cycles = 6;
	break;
      case 0x21: // AND (Indirect,X)
	and(indexed_indirect());
	cycles = 6;
	break;
      case 0x24: // BIT Zero-page
	l = load(zero_page(0));
	_P &= ~(P_NEGATIVE|P_ZERO|P_OVERFLOW);
	_P |= (l&0xC0);
	_P |= (_A&l? 0 : P_ZERO);
	cycles = 3;
	break;
      case 0x25: // AND Zero-page
	and(zero_page(0));
	cycles = 3;
	break;
      case 0x26: // ROL Zero-page
	l = rol(load(addr = zero_page(0)));
	store(addr, l);
	cycles = 5;
	break;
      case 0x28: // PLP
	_P = pop();
	cycles = 4;
	break;
      case 0x29: // AND Immediate
	and(immediate());
	cycles = 2;
	break;
      case 0x2A: // ROL Accumulator
	_A = rol(_A);
	cycles = 2;
	break;
      case 0x2C: // BIT Absolute
	l = load(absolute());
	_P &= ~(P_NEGATIVE|P_ZERO|P_OVERFLOW);
	_P |= (l&0xC0);
	_P |= (_A&l? 0 : P_ZERO);
	cycles = 4;
	break;
      case 0x2D: // AND Absolute
	and(absolute());
	cycles = 4;
	break;
      case 0x2E: // ROL Absolute
	l = rol(load(addr = absolute()));
	store(addr, l);
	cycles = 6;
	break;
      case 0x30: // BMI
	l = immediate_value();
	cycles = 2;
	if (_P & P_NEGATIVE) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0x31: // AND (Indirect),Y
	and(indirect_indexed());
	cycles = 5;
	break;
      case 0x35: // AND Zero-page,X
	and(zero_page(_X));
	cycles = 4;
	break;
      case 0x36: // ROL Zero-page,X
	l = rol(load(addr = zero_page(_X)));
	store(addr, l);
	cycles = 6;
	break;
      case 0x38: // SEC
	_P |= P_CARRY;
	cycles = 2;
	break;
      case 0x39: // AND Absolute,Y
	and(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x3D: // AND Absolute,X
	and(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0x3E: // ROL Absolute,X
	l = rol(load(addr = absolute_indexed(_X)));
	store(addr, l);
	cycles = 7;
	break;
      case 0x40: // RTI
	_P = pop();
	l = pop();
	h = pop();
	_PC = h<<8 | l;
	if (_ilog) {
	  fprintf(_log, "PC-> %04X", _PC);
	  fprintf(_log, " S:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
	  _log = NULL;
	}
	break;
      case 0x41: // EOR (Indirect,X)
	eor(indexed_indirect());
	cycles = 6;
	break;
      case 0x45: // EOR Zero-page
	eor(zero_page(0));
	cycles = 3;
	break;
      case 0x46: // LSR Zero-page
	l = lsr(load(addr = zero_page(0)));
	store(addr,l);
	cycles = 5;
	break;
      case 0x48: // PHA
	push(_A);
	cycles = 3;
	break;
      case 0x49: // EOR Immediate
	eor(immediate());
	cycles = 2;
	break;
      case 0x4A: // LSR Accumulator
	_A = lsr(_A);
	cycles = 2;
	break;
      case 0x4C: // JMP Absolute
	_PC = absolute();
	cycles = 3;
	break;
      case 0x4D: // EOR Absolute
	eor(absolute());
	cycles = 4;
	break;
      case 0x4E: // LSR Absolute
	l = lsr(load(addr = absolute()));
	store(addr,l);
	cycles = 6;
	break;
      case 0x50: // BVC
	l = immediate_value();
	cycles = 2;
	if (!(_P & P_OVERFLOW)) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0x51: // EOR (Indirect),Y
	eor(addr = indirect_indexed());
	cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x55: // EOR Zero-page,X
	eor(zero_page(_X));
	cycles = 4;
	break;
      case 0x56: // LSR Zero-page,X
	l = lsr(load(addr = zero_page(_X)));
	store(addr,l);
	cycles = 6;
	break;
      case 0x58: // CLI
	_P &= ~(P_IRQDIS);
	cycles = 2;
	break;
      case 0x59: // EOR Absolute,Y
	eor(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x5D: // EOR Absolute,X
	eor(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0x5E: // LSR Absolute,X
	l = lsr(load(addr = absolute_indexed(_X)));
	store(addr,l);
	cycles = 7;
	break;
      case 0x60: // RTS
	l = pop();
	h = pop();
	_PC = h<<8 | l;
	_PC++;
	break;
      case 0x61: // ADC (Indirect,X)
	adc(indexed_indirect());
	cycles = 6;
	break;
      case 0x65: // ADC Zero-page
	adc(zero_page(0));
	cycles = 3;
	break;
      case 0x66: // ROR Zero-page
	l = ror(load(addr = zero_page(0)));
	store(addr,l);
	cycles = 5;
	break;
      case 0x68: // PLA
	_A = pop();
	_P &= ~(P_ZERO|P_NEGATIVE);
	if (_A == 0) _P |= P_ZERO;
	if (_A&0x80) _P |= P_NEGATIVE;
	cycles = 4;
	break;
      case 0x69: // ADC Immediate
	adc(immediate());
	cycles = 2;
	break;
      case 0x6A: // ROR Accumulator
	_A = ror(_A);
	cycles = 2;
	break;
      case 0x6C: // JMP Indirect
	addr = absolute();
	l = load(addr);
	if ((addr&0x00FF) == 0x00FF) {
	  fprintf(stderr,"Possible bad indirect jump (addr=%04X)\n", addr);
	  exit(0);
	}
	h = load(addr+1);
	_PC = h<<8 | l;
	cycles = 5;
	break;
      case 0x6D: // ADC Absolute
	adc(absolute());
	cycles = 4;
	break;
      case 0x6E: // ROR Absolute
	l = ror(load(addr = absolute()));
	store(addr, l);
	cycles = 6;
	break;
      case 0x70: // BVS
	l = immediate_value();
	cycles = 2;
	if (_P & P_OVERFLOW) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0x71: // ADC (Indirect),Y
	adc(addr = indirect_indexed());
	cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x75: // ADC Zero-page,X
	adc(zero_page(_X));
	cycles = 4;
	break;
      case 0x76: // ROR Zero-page,X
	l = ror(load(addr = zero_page(_X)));
	store(addr, l);
	cycles = 6;
	break;
      case 0x78: // SEI
	_P |= P_IRQDIS;
	cycles = 2;
	break;
      case 0x79: // ADC Absolute,Y
	adc(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0x7D: // ADC Absolute,X
	adc(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0x7E: // ROR Absolute,X
	l = ror(load(addr = absolute_indexed(_X)));
	store(addr, l);
	cycles = 7;
	break;
      case 0x81: // STA (Indirect,X)
	store(indexed_indirect(), _A);
	cycles = 6;
	break;
      case 0x84: // STY Zero-page
	store(zero_page(0), _Y);
	cycles = 3;
	break;
      case 0x85: // STA Zero-page
	store(zero_page(0), _A);
	cycles = 3;
	break;
      case 0x86: // STX Zero-page
	store(zero_page(0), _X);
	cycles = 3;
	break;
      case 0x88: // DEY
	_Y--;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_Y == 0) _P |= P_ZERO;
	if (_Y & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0x8A: // TXA
	_A = _X;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_A == 0) _P |= P_ZERO;
	if (_A & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0x8C: // STY Absolute
	store(absolute(), _Y);
	cycles = 4;
	break;
      case 0x8D: // STA Absolute
	store(absolute(), _A);
	cycles = 4;
	break;
      case 0x8E: // STX Absolute
	store(absolute(), _X);
	cycles = 4;
	break;
      case 0x90: // BCC
	l = immediate_value();
	cycles = 2;
	if (!(_P & P_CARRY)) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0x91: // STA (Indirect),Y
	store(indirect_indexed(), _A);
	cycles = 6;
	break;
      case 0x94: // STY Zero-page,X
	store(zero_page(_X), _Y);
	cycles = 4;
	break;
      case 0x95: // STA Zero-page,X
	store(zero_page(_X), _A);
	cycles = 4;
	break;
      case 0x96: // STX Zero-page,Y
	store(zero_page(_Y), _X);
	cycles = 4;
	break;
      case 0x98: // TYA
	_A = _Y;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_A == 0) _P |= P_ZERO;
	if (_A & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0x99: // STA Absolute,Y
	store(absolute_indexed(_Y), _A);
	cycles = 5;
	break;
      case 0x9A: // TXS
	_S = _X;
	cycles = 2;
	break;
      case 0x9D: // STA Absolute,X
	store(absolute_indexed(_X), _A);
	cycles = 5;
	break;
      case 0xA0: // LDY Immediate
	ldy(immediate());
	cycles = 2;
	break;
      case 0xA1: // LDA (Indirect,X)
	lda(indexed_indirect());
	cycles = 6;
	break;
      case 0xA2: // LDX Immediate
	ldx(immediate());
	cycles = 2;
	break;
      case 0xA4: // LDY Zero-page
	ldy(zero_page(0));
	cycles = 3;
	break;
      case 0xA5: // LDA Zero-page
	lda(zero_page(0));
	cycles = 3;
	break;
      case 0xA6: // LDX Zero-page
	ldx(zero_page(0));
	cycles = 3;
	break;
      case 0xA8: // TAY
	_Y = _A;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_Y == 0) _P |= P_ZERO;
	if (_Y & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xA9: // LDA Immediate
	lda(immediate());
	cycles = 2;
	break;
      case 0xAA: // TAX
	_X = _A;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_X == 0) _P |= P_ZERO;
	if (_X & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xAC: // LDY Absolute
	ldy(absolute());
	cycles = 4;
	break;
      case 0xAD: // LDA Absolute
	lda(absolute());
	cycles = 4;
	break;
      case 0xAE: // LDX Absolute
	ldx(absolute());
	cycles = 4;
	break;
      case 0xB0: // BCS
	l = immediate_value();
	cycles = 2;
	if (_P & P_CARRY) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0xB1: // LDA (Indirect),Y
	lda(addr = indirect_indexed());
	cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0xB4: // LDY Zero-page,X
	ldy(zero_page(_X));
	cycles = 4;
	break;
      case 0xB5: // LDA Zero-page,X
	lda(zero_page(_X));
	cycles = 4;
	break;
      case 0xB6: // LDX Zero-page,Y
	ldx(zero_page(_Y));
	cycles = 4;
	break;
      case 0xB8: // CLV
	_P &= ~P_OVERFLOW;
	cycles = 2;
	break;
      case 0xB9: // LDA Absolute,Y
	lda(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0xBA: // TSX
	_X = _S;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_X == 0) _P |= P_ZERO;
	if (_X & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xBC: // LDY Absolute,X
	ldy(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1: 0 ;
	break;
      case 0xBD: // LDA Absolute,X
	lda(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0xBE: // LDX Absolute,Y
	ldx(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1: 0 ;
	break;
      case 0xC0: // CPY Immediate
	cmp(_Y, immediate());
	cycles = 2;
	break;
      case 0xC1: // CMP (Indirect,X)
	cmp(_A, indexed_indirect());
	cycles = 6;
	break;
      case 0xC4: // CPY Zero-page
	cmp(_Y, zero_page(0));
	cycles = 3;
	break;
      case 0xC5: // CMP Zero-page
	cmp(_A, zero_page(0));
	cycles = 3;
	break;
      case 0xC6: // DEC Zero-page
	dec(zero_page(0));
	cycles = 5;
	break;
      case 0xC8: // INY
	_Y++;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_Y == 0) _P |= P_ZERO;
	if (_Y & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xC9: // CMP Immediate
	cmp(_A, immediate());
	cycles = 2;
	break;
      case 0xCA: // DEX
	_X--;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_X == 0) _P |= P_ZERO;
	if (_X & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xCC: // CPY Absolute
	cmp(_Y, absolute());
	cycles = 4;
	break;
      case 0xCD: // CMP Absolute
	cmp(_A, absolute());
	cycles = 4;
	break;
      case 0xCE: // DEC Absolute
	dec(absolute());
	cycles = 6;
	break;
      case 0xD0: // BNE
	l = immediate_value();
	cycles = 2;
	if (!(_P & P_ZERO)) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0xD1: // CMP (Indirect),Y 
	cmp(_A, addr = indirect_indexed());
	cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0xD5: // CMP Zero-page,X
	cmp(_A, zero_page(_X));
	cycles = 4;
	break;
      case 0xD6: // DEC Zero-page,X
	dec(zero_page(_X));
	cycles = 6;
	break;
      case 0xD8: // CLD
	_P &= ~(P_DECIMAL);
	cycles = 2;
	break;
      case 0xD9: // CMP Absolute,Y
	cmp(_A, addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0xDD: // CMP Absolute,X
	cmp(_A, addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0xDE: // DEC Absolute,X
	dec(absolute_indexed(_X));
	cycles = 7;
	break;
      case 0xE0: // CPX Immediate
	cmp(_X, immediate());
	cycles = 2;
	break;
      case 0xE1: // SBC (Indirect,X)
	sbc(indexed_indirect());
	cycles = 6;
	break;
      case 0xE4: // CPX Zero-page
	cmp(_X,zero_page(0));
	cycles = 3;
	break;
      case 0xE5: // SBC Zero-page
	sbc(zero_page(0));
	cycles = 3;
	break;
      case 0xE6: // INC Zero-page
	inc(zero_page(0));
	cycles = 5;
	break;
      case 0xE8: // INX
	_X++;
	_P &= ~(P_ZERO | P_NEGATIVE);
	if (_X == 0) _P |= P_ZERO;
	if (_X & 0x80) _P |= P_NEGATIVE;
	cycles = 2;
	break;
      case 0xE9: // SBC Immediate
	sbc(immediate());
	cycles = 2;
	break;
      case 0xEA: // NOP
	cycles = 2;
	break;
      case 0xEC: // CPX Absolute
	cmp(_X,absolute());
	cycles = 4;
	break;
      case 0xED: // SBC Absolute
	sbc(absolute());
	cycles = 4;
	break;
      case 0xEE: // INC Absolute
	inc(absolute());
	cycles = 6;
	break;
      case 0xF0: // BEQ
	l = immediate_value();
	cycles = 2;
	if (_P & P_ZERO) {
	  addr = _PC;
	  _PC = _PC + (int8_t)l;
	  cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
	}
	break;
      case 0xF1: // SBC (Indirect),Y
	sbc(indirect_indexed());
	cycles = 5;
	break;
      case 0xF5: // SBC Zero-page,X
	sbc(zero_page(_X));
	cycles = 4;
	break;
      case 0xF6: // INC Zero-page,X
	inc(zero_page(_X));
	cycles = 6;
	break;
      case 0xF8: // SED
	fprintf(stderr,"SED HAS BEEN SET!\n");
	exit(1);
	_P |= P_DECIMAL;
	cycles = 2;
	break;
      case 0xF9: // SBC Absolute,Y
	sbc(addr = absolute_indexed(_Y));
	cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
	break;
      case 0xFD: // SBC Absolute,X
	sbc(addr = absolute_indexed(_X));
	cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
	break;
      case 0xFE: // INC Absolute,X
	inc(absolute_indexed(_X));
	cycles = 7;
	break;
      default: // Future Exapansion
	fprintf(stderr,"Illegal instruction!!! %02X\n", _IR);
	exit(0);
	break;
    }
    clocks += cycles;
    if (clocks > 1000) {
      clocks -= 1000;
      usleep(250);
    }
    if (_keydown > 0) _keydown -= cycles;
    if (_log) {
      fprintf(_log, "\tS:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
      for(i=0;i<_widx;i++) {
	fprintf(_log,"  %04X -> %02X/%d\n", _wlog[i].addr, _wlog[i].data, _wlog[i].data);
      }
    }
    _widx = 0;
    if (_timerA1) {
      _timerA1 -= cycles;
      if (_timerA1 <= 0) {
	if (!(_P & P_IRQDIS)) {
	  _HWIRQ = 1;
	  _ics1 |= 0x01;
	}
	if (_timerA1L) _timerA1 += _timerA1L;
	else _timerA1 = 0;
      }
    }
    if (_HWIRQ) {
      if (_ilog) {
	_log = _ilog;
	fprintf(_log, "PC-> %04X", _PC);
	fprintf(_log, " S:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
      }
      _IR = 0;
      push(_PC>>8);
      push(_PC&0xFF);
      push(_P & ~P_BRK);
      _PC = load(0XFFFF) <<8 | load(0xFFFE);
      _HWIRQ = 0;
    }
    if (_NMI) {
      _IR = 0;
      push(_PC>>8);
      push(_PC&0xFF);
      push(_P & ~P_BRK);
      _PC = load(0XFFFB) <<8 | load(0xFFFA);
      _NMI = 0;
    }
  }
}

void reset()
{
  _IR = 0;
  _A = 0xAA;
  _X = _Y = 0;
  _P = P_BRK;
  _S = 0xFD;
  _PC = load(0xFFFD) <<8 | load(0xFFFC);
  run();
}

</div>
</div>
</body>
</html>