gt:         case 0xDA:// 65C02 PHX
context: package com.bluepowermod.tileentities.tier3;
  
  import java.io.IOException;
  import java.io.InputStream;
  
  import net.minecraft.init.Blocks;
  
  import com.bluepowermod.BluePower;
  import com.bluepowermod.tileentities.TileBase;
  
  /**
   * @author fabricator77
   */
  public class TileCPU extends TileBase implements IRedBusWindow {
      //config option
      public int cpuStoredCycles = 100000;
      public int cpuForTickCycles = 1; // default is 1000 for 20khz
      //front panel switches
      public byte deviceID = 0;
      public byte screenID = 1;
      public byte discDriveID = 2;
      public boolean halt = false;;
      
      private byte[] memory;
      // registers
      private int programCounter;
      private int stackPointer;
      
      private int reg_X;
      private int reg_Y;
      private int reg_A; // accumulator
      private int reg_B; // 65EL02 ?
      private int reg_D; // ???
      private int reg_I; // 65EL02
      private int reg_R; // 65EL02 ?
      // flags
      private boolean flag_C; // carry
      private boolean flag_D; // ?
      private boolean flag_E; // E flag 65C816
      private boolean flag_M; // M flag 65C816 (true 8 bit mode, false = 16bit)
      private boolean flag_N; // negative
      private boolean flag_O; // overflow
      private boolean flag_X; // ?
      private boolean flag_Z; // zero
      private boolean flag_BRK; // break flag
      private boolean flag_WAI; // wait flag (for virtual IRQ)
      // redbus
      private int redbus_remote_address; // current remote redbus device
      private boolean redbus_timeout;
      private boolean redbus_window_enabled = true;
      private Object redbus_cache;
      
      private int availableCycles;
      public int rtc = 0;
      
      // used in decoding opcodes
      private int effectiveAddress;
      private int BRKaddress;
  
      public TileCPU() {
          //TODO: make memory a config option
          this.memory = new byte[8192];
          powerOnReset();
      }
      
      public void powerOnReset () {
          //TODO: set start addresses
          this.programCounter = 1024;
          BRKaddress = 1024; //8192;
          stackPointer = 512;
          reg_R = 768;
          //front panel switches
          //TODO: read frontpanel from NBT data
          this.memory[0] = this.discDriveID;
          this.memory[1] = this.screenID;
          this.memory[2] = this.redbus_id; // own redbus address
          // clear registers
          reg_A = reg_Y = reg_A = 0;
          //TODO: reset internal CPU flags
          flag_BRK = false;
          
          boolean preloadRam = true;
          if (preloadRam) {
              preLoadRAM();
              return;
          }
          
          
          //load program/OS into memory
          String bootLoader = "/assets/bluepower/software/rpcboot.bin";
          InputStream disc = BluePower.class.getResourceAsStream(bootLoader);
          
          if (disc == null) {
              BluePower.log.info("[BluePowerControl] CPU failed to load bootloader "+bootLoader);
              return;
          }
          
          try {
              BluePower.log.info("[BluePowerControl] CPU loaded bootloader "+bootLoader);
              //loads 256byte boot loader into memory
              disc.read(this.memory, 1024, 256);
              disc.close();
          }
          catch (IOException e) {
              e.printStackTrace();
          }
      }
      
      // temp to load data into memory for testing
      private void preLoadRAM () {
          this.memory[1024] = (byte)0xDB; // STP
      }
      
      //TODO: NBT read/write
      
      public void updateEntity() {
          // 20 ticks per second = 20khz
          if (halt) return;
          this.rtc += 1;
          
          this.flag_WAI = false;
          this.redbus_timeout = false;
          
          availableCycles += cpuForTickCycles;
          if (availableCycles > cpuStoredCycles) {
              availableCycles = cpuStoredCycles;
          }
          while (availableCycles > 0 && !this.flag_WAI && !this.redbus_timeout) {
              executeInstruction();
              // dumpMemory();
          }
      }
      
      private void dumpMemory () {
          
          if (this.programCounter > this.memory.length) {
              availableCycles = -1;
              halt = true;
              return;
          }
          availableCycles -= 1;
          String message = "[BluePowerControl] "+this.programCounter+": ";
          for (int i=0; i<16; i++) {
              message += Integer.toHexString(readMemory(this.programCounter) & 0xFF) + " ";
              this.programCounter++;
          }
          BluePower.log.info(message);
          this.availableCycles -= 1;
      }
  
      private void executeInstruction() {
      
          availableCycles -= 1;
          // TODO: read block of memory etc
          int opcode = readMemory(this.programCounter);
          BluePower.log.info("[BluePowerControl] CPU " + Integer.toHexString(this.programCounter) + ":"+Integer.toHexString(opcode));
          this.programCounter++;
          
          //TODO: sort instruction according to frequency of usage
          // for speed reasons
          // Octal numbers for ease of lookup in documentation.
          // Reference http://www.eloraam.com/nonwp/redcpu.php
          switch (opcode) {
          // row 0
          case 0:// 6502 BRK (calls 65EL02 MMU #0)
              opBRK();
              break;
          case 0x01:// 6502 ORA (indirect,X)
              invalid(opcode);
              break;
          case 0x02:// 65E02 NXT
              invalid(opcode);
              break;
          case 0x03:// 65C816 ORA r,S
              invalid(opcode);
              break;
          case 0x04:// 65C02 TSB zeropage
              invalid(opcode);
              break;
          case 0x05:// 6502 ORA zeropage
              invalid(opcode);
              break;
          case 0x06:// 6502 ASL zeropage
              invalid(opcode);
              break;
          case 0x07:// 65EL02 ORA r,R
              invalid(opcode);
              break;    
          case 0x08:// 6502 PHP
              invalid(opcode);
              break;    
          case 0x09:// 6502 ORA #
              invalid(opcode);
              break;
          case 0x0A:// 6502 ASL A
              invalid(opcode);
              break;
          case 0x0B:// 65EL02 RHI
              invalid(opcode);
              break;
          case 0x0C:// 65C02 STB absolute
              invalid(opcode);
              break;
          case 0x0D:// 6502 ORA absolute
              invalid(opcode);
              break;
          case 0x0E:// 6502 ASL absolute
              invalid(opcode);
              break;
          case 0x0F:// 6502 MUL zeropage
              invalid(opcode);
              break;
              
          // row 1
          case 0x10:// 6502 BPL relative
              invalid(opcode);
              break;
          case 0x11:// 6502 ORA indirect, Y
              invalid(opcode);
              break;
          case 0x12:// 65C02 ORA indirect
              invalid(opcode);
              break;
          case 0x13:// 65C816 ORA (r,S),Y
              invalid(opcode);
              break;
          case 0x14:// 65C02 TRB zeropage
              invalid(opcode);
              break;
          case 0x15:// 6502 ORA zeropage,X
              invalid(opcode);
              break;
          case 0x16:// 6502 ASL zeropage,X
              invalid(opcode);
              break;
          case 0x17:// 65EL02 ORA (r,R),Y
              invalid(opcode);
              break;
          case 0x18:// 6502 CLC
              opCLC();
              break;
          case 0x19:// 6502 ORA absolute,Y
              invalid(opcode);
              break;
          case 0x1A:// 65C02 INC A
              opINC(this.reg_A);
              break;
          case 0x1B:// 65EL02 RHX
              invalid(opcode);
              break;
          case 0x1C:// 65C02 TRB absolute
              invalid(opcode);
              break;
          case 0x1D:// 6502 ORA absolute,X
              invalid(opcode);
              break;
          case 0x1E:// 6502 ASL absolute,X
              invalid(opcode);
              break;
          case 0x1F:// 65EL02 MUL zeropage,X
              invalid(opcode);
              break;
              
          // row 2
          case 0x20:// 6502 JSR absolute
              invalid(opcode);
              break;
          case 0x21:// 6502 AND (indirect,X)
              invalid(opcode);
              break;
          case 0x22:// 65EL02 ENT
              invalid(opcode);
              break;
          case 0x23:// 65C816 AND r,S
              invalid(opcode);
              break;
          case 0x24:// 6502 BIT zeropage
              opBIT();
              break;
          case 0x25:// 6502 AND zeropage
              invalid(opcode);
              break;
          case 0x26:// 6502 ROL zeropage
              invalid(opcode);
              break;
          case 0x27:// 65EL02 AND r,R
              invalid(opcode);
              break;
          case 0x28:// 6502 PLP
              invalid(opcode);
              break;
          case 0x29:// 6502 AND #
              invalid(opcode);
              break;
          case 0x2A:// 6502 ROL A
              invalid(opcode);
              break;
          case 0x2B:// 65EL02 RLI
              invalid(opcode);
              break;    
          case 0x2C:// 6502 BIT absolute
              opBIT();
              break;
          case 0x2D:// 6502 AND absolute
              invalid(opcode);
              break;
          case 0x2E:// 6502 ROL absolute
              invalid(opcode);
              break;
          case 0x2F:// 65EL02 MUL absolute
              invalid(opcode);
              break;
              
          // row 3
          case 0x30:// 6502 BMI relative
              invalid(opcode);
              break;
          case 0x31:// 6502 AND (indirect), Y
              invalid(opcode);
              break;
          case 0x32:// 65C02 AND indirect
              invalid(opcode);
              break;
          case 0x33:// 65C816 AND (r,S),Y
              invalid(opcode);
              break;
          case 0x34:// 65C02 BIT zeropage, X
              invalid(opcode);
              break;
          case 0x35:// 6502 AND zeropage, X
              invalid(opcode);
              break;
          case 0x36:// 6502 ROL zeropage, X
              invalid(opcode);
              break;
          case 0x37:// 65EL02 AND (r,R),Y 
              invalid(opcode);
              break;
          case 0x38:// 6502 SEC
              //set carry flag
          	this.flag_C = true;
              break;
          case 0x39:// 6502 AND absolute, Y
              invalid(opcode);
              break;
          case 0x3A:// 65C02 DEC A
              opDEC(this.reg_A); 
              break;
          case 0x3B:// 65EL02 RLX
              invalid(opcode);
              break;
          case 0x3C:// 65C02 BIT absolute, X
              invalid(opcode);
              break;
          case 0x3D:// 6502 AND absolute, X
              invalid(opcode);
              break;
          case 0x3E:// 6502 ROL absolute, X
              invalid(opcode);
              break;
          case 0x3F:// 65EL02 MUL absolute, X
              invalid(opcode);
              break;
          
          // row 4
          case 0x40:// 6502 RTI
              invalid(opcode);
              break;
          case 0x41:// 6502 EOR (indirect,X)
              invalid(opcode);
              break;
          case 0x42:// 65EL02 NXA
              invalid(opcode);
              break;
          case 0x43:// 65C816 EOR r,S
              invalid(opcode);
              break;
          case 0x44:// 65EL02 REA absolute
              invalid(opcode);
              break;    
          case 0x45:// 6502 EOR zeropage
              invalid(opcode);
              break;
          case 0x46:// 6502 LSR zeropage
              invalid(opcode);
              break;
          case 0x47:// 65EL02 EOR r,R
              invalid(opcode);
              break;
          case 0x48:// 6502 PHA
              invalid(opcode);
              break;
          case 0x49:// 6502 EOR #
              invalid(opcode);
              break;
          case 0x4A:// 6502 LSR A
              invalid(opcode);
              break;
          case 0x4B:// 65EL02 RHA
              invalid(opcode);
              break;
          case 0x4C:// 6502 JMP absolute
              invalid(opcode);
              break;
          case 0x4D:// 6502 EOR absolute
              invalid(opcode);
              break;
          case 0x4E:// 6502 LSR absolute
              invalid(opcode);
              break;
          case 0x4F:// 65EL02 DIV zeropage
              invalid(opcode);
              break;
          
          // row 5
          case 0x50:// 6502 BVC relative
              invalid(opcode);
              break;
          case 0x51:// 6502 EOR (indirect),Y
              invalid(opcode);
              break;
          case 0x52:// 65C02 EOR indirect
              invalid(opcode);
              break;
          case 0x53:// 65C816 EOR (r,S),Y
              invalid(opcode);
              break;
          case 0x54:// 65EL02 REI (zeropage)
              invalid(opcode);
              break;
          case 0x55:// 6502 EOR zeropage,X
              invalid(opcode);
              break;
          case 0x56:// 6502 LSR zeropage,X
              invalid(opcode);
              break;
          case 0x57:// 65EL02 EOR (r,R),Y
              invalid(opcode);
              break;
          case 0x58:// 6502 CLI
              invalid(opcode);
              break;
          case 0x59:// 6502 EOR absolute,Y
              invalid(opcode);
              break;
          case 0x5A:// 65C02 PHY
              invalid(opcode);
              break;
          case 0x5B:// 65EL02 RHY
              invalid(opcode);
              break;
          case 0x5C:// 65EL02 TXI
              opTXI();
              break;
          case 0x5D:// 6502 EOR absolute,X
              invalid(opcode);
              break;
          case 0x5E:// 6502 LSR absolute,X
              invalid(opcode);
              break;
          case 0x5F:// 65EL02 DIV zeropage,X
              invalid(opcode);
              break;
              
          // row 6
          case 0x60:// 6502 RTS
              invalid(opcode);
              break;
          case 0x61:// 6502 ADC (indirect,X)
              invalid(opcode);
              break;
          case 0x62:// 65C816 PER relative
              invalid(opcode);
              break;
          case 0x63:// 65C816 ADC r,S
              invalid(opcode);
              break;
          case 0x64:// 65C02 STZ zeropage
              invalid(opcode);
              break;
          case 0x65:// 6502 ADC zeropage
              invalid(opcode);
              break;
          case 0x66:// 6502 ROR zeropage
              invalid(opcode);
              break;
          case 0x67:// 65EL02 ADC r,R
              invalid(opcode);
              break;
          case 0x68:// 6502 PLA
              invalid(opcode);
              break;
          case 0x69:// 6502 ADC #
              invalid(opcode);
              break;
          case 0x6A:// 6502 ROR A
              invalid(opcode);
              break;
          case 0x6B:// 65EL02 RLA
              invalid(opcode);
              break;
          case 0x6C:// 6502 JMP (indirect)
              invalid(opcode);
              break;
          case 0x6D:// 6502 ADC absolute
              invalid(opcode);
              break;
          case 0x6E:// 6502 ROR absolute
              invalid(opcode);
              break;
          case 0x6F:// 6502 DIV absolute
              invalid(opcode);
              break;
              
          // row 7
          case 0x70:// 6502 BVS relative
              invalid(opcode);
              break;
          case 0x71:// 6502 ADC (indirect),Y
              invalid(opcode);
              break;
          case 0x72:// 65C02 ADC (indirect)
              invalid(opcode);
              break;
          case 0x73:// 65C816 ADC (r,S),Y
              invalid(opcode);
              break;
          case 0x74:// 65C02 STZ zeropage,X
              invalid(opcode);
              break;
          case 0x75:// 6502 ADC zeropage,X
              invalid(opcode);
              break;
          case 0x76:// 6502 ROR zeropage,X
              invalid(opcode);
              break;
          case 0x77:// 65EL02 ADC (r,R),Y
              invalid(opcode);
              break;
          case 0x78:// 6502 SEI
              invalid(opcode);
              break;
          case 0x79:// 6502 ADC absolute,Y
              invalid(opcode);
              break;
          case 0x7A:// 65C02 PLY
              invalid(opcode);
              break;
          case 0x7B:// 65EL02 RLY
              invalid(opcode);
              break;
          case 0x7C:// 65C02 JMP (absolute,X)
              invalid(opcode);
              break;
          case 0x7D:// 6502 ADC absolute,X
              invalid(opcode);
              break;
          case 0x7E:// 6502 ROR absolute,X
              invalid(opcode);
              break;
          case 0x7F:// 6502 DIV absolute,X
              invalid(opcode);
              break;
              
          // row 8
          case 0x80:// 65C02 BRA relative
              invalid(opcode);
              break;
          case 0x81:// 6502 STA (indirect,X)
              invalid(opcode);
              break;
          case 0x82:// 65EL02 RER relative
              invalid(opcode);
              break;
          case 0x83:// 65C816 STA (r,S)
              invalid(opcode);
              break;
          case 0x84:// 6502 STY zeropage
              invalid(opcode);
              break;
          case 0x85:// 6502 STA zeropage
              invalid(opcode);
              break;
          case 0x86:// 6502 STX zeropage
              invalid(opcode);
              break;
          case 0x87:// 65EL02 STA r,R
              invalid(opcode);
              break;
          case 0x88:// 6502 DEY
              invalid(opcode);
              break;
          case 0x89:// 65C02 BIT #
              invalid(opcode);
              break;
          case 0x8A:// 6502 TXA
              opTXA();
              break;
          case 0x8B:// 65EL02 TXR
              opTXR();
              break;
          case 0x8C:// 6502 STY absolute
              invalid(opcode);
              break;
          case 0x8D:// 6502 STA absolute
              invalid(opcode);
              break;
          case 0x8E:// 6502 STX absolute
              invalid(opcode);
              break;
          case 0x8F:// 65EL02 SEA
              opTXR();
              break;
              
          // row 9
          case 0x90:// 6502 BCC relative
              invalid(opcode);
              break;
          case 0x91:// 6502 STA (indirect),Y
              invalid(opcode);
              break;
          case 0x92:// 65C02 STA (indirect)
              invalid(opcode);
              break;
          case 0x93:// 65C816 STA (r, S),Y
              invalid(opcode);
              break;
          case 0x94:// 6502 STY zeropage,X
              invalid(opcode);
              break;
          case 0x95:// 6502 STA zeropage,X
              invalid(opcode);
              break;
          case 0x96:// 6502 STX zeropage,Y
              invalid(opcode);
              break;
          case 0x97:// 65EL02 STA (r,R),X
              invalid(opcode);
              break;
          case 0x98:// 6502 TYA
              opTYA();
              break;
          case 0x99:// 6502 STA absolute,Y
              invalid(opcode);
              break;
          case 0x9A:// 6502 TXS
              opTXS();
              break;
          case 0x9B:// 65C816 TXY
              opTXY();
              break;
          case 0x9C:// 65C02 STZ absolute
              invalid(opcode);
              break;
          case 0x9D:// 6502 STA absolute,X
              invalid(opcode);
              break;
          case 0x9E:// 65C02 STZ absolute,X
              invalid(opcode);
              break;
          case 0x9F:// 65EL02 SEA
              invalid(opcode);
              break;
              
          // row A
          case 0xA0:// 6502 LDY #
              invalid(opcode);
              break;
          case 0xA1:// 6502 LDA (indirect),X
              invalid(opcode);
              break;
          case 0xA2:// 6502 LDA #
              invalid(opcode);
              break;
          case 0xA3:// 65C816 LDA r,S
              invalid(opcode);
              break;
          case 0xA4:// 6502 LDY zeropage
              invalid(opcode);
              break;            
          case 0xA5:// 6502 LDA zeropage
              opLDA();
              break;
          case 0xA6:// 6502 LDY zeropage
              invalid(opcode);
              break;
          case 0xA7:// 65EL02 LDA r,R
              invalid(opcode);
              break;
          case 0xA8:// 6502 TAY
              opTAY();
              break;
          case 0xA9:// 6502 LDA #
              invalid(opcode);
              break;
          case 0xAA:// 6502 TAX
              opTAY();
              break;
          case 0xAB:// 65EL02 TRX
              opTRX();
              break;
          case 0xAC:// 6502 LDY absolute
              invalid(opcode);
              break;
          case 0xAD:// 6502 LDA absolute
              invalid(opcode);
              break;
          case 0xAE:// 6502 LDX absolute
              invalid(opcode);
              break;
          case 0xAF:// 65EL02 TDA
              opTDA();
              break;
              
          // row B
          case 0xB0:// 6502 BCS relative
              invalid(opcode);
              break;
          case 0xB1:// 6502 LDA (indirect), Y
              invalid(opcode);
              break;
          case 0xB2:// 65C02 LDA (indirect)
              invalid(opcode);
              break;
          case 0xB3:// 65C816 LDA (r, S), Y
              invalid(opcode);
              break;
          case 0xB4:// 6502 LDY zeropage, X
              invalid(opcode);
              break;
          case 0xB5:// 6502 LDA zeropage, X
              invalid(opcode);
              break;
          case 0xB6:// 6502 LDX zeropage, Y
              invalid(opcode);
              break;
          case 0xB7:// 65EL02 LDA (r, R), Y
              invalid(opcode);
              break;
          case 0xB8:// 6502 CLV
              invalid(opcode);
              break;
          case 0xB9:// 6502 LDA absolute, Y
              invalid(opcode);
              break;
          case 0xBA:// 6502 TSX
              opTSX();
              break;
          case 0xBB:// 65C816 TYX
              opTYX();
              break;
          case 0xBC:// 6502 LDY absolute, X
              invalid(opcode);
              break;
          case 0xBD:// 6502 LDA absolute, X
              invalid(opcode);
              break;
          case 0xBE:// 6502 LDX absolute, Y
              invalid(opcode);
              break;
          case 0xBF:// 65EL02 TAD
              opTAD();
              break;
              
          // row C
          case 0xC0:// 6502 CDY #
              invalid(opcode);
              break;
          case 0xC1:// 6502 CMP (indirect, X)
              invalid(opcode);
              break;
          case 0xC2:// 65C816 REP #
              opREP();
              break;
          case 0xC3:// 65C816 CMP r, S
              invalid(opcode);
              break;
          case 0xC4:// 6502 CPY zeropage
              invalid(opcode);
              break;
          case 0xC5:// 6502 CMP zeropage
              invalid(opcode);
              break;
          case 0xC6:// 6502 DEC zeropage
              opDEC(decodeMemoryMode(AddressMode.ZEROPAGE));
              break;
          case 0xC7:// 65EL02 CMP r,R
              invalid(opcode);
              break;
          case 0xC8:// 6502 INY
              invalid(opcode);
              break;
          case 0xC9:// 6502 CMP #
              invalid(opcode);
              break;
          case 0xCA:// 6502 DEX
              invalid(opcode);
              break;
          case 0xCB:// 65C02 WAI
              opWAI();
              break;
          case 0xCC:// 6502 CPY absolute
              invalid(opcode);
              break;
          case 0xCD:// 6502 CMP absolute
              invalid(opcode);
              break;
          case 0xCE:// 6502 DEC absolute
              opDEC(decodeMemoryMode(AddressMode.ABSOLUTE));
              break;
          case 0xCF:// 65EL02 PLD
              invalid(opcode);
              break;
              
          // row D
          case 0xD0:// 6502 BNE relative
              invalid(opcode);
              break;
          case 0xD1:// 6502 CMP (indirect), Y
              invalid(opcode);
              break;
          case 0xD2:// 65C02 CMP (indirect)
              invalid(opcode);
              break;
          case 0xD3:// 65C816 CMP (r, S), Y
              invalid(opcode);
              break;
          case 0xD4:// 65C816 PEI (zeropage)
              invalid(opcode);
              break;
          case 0xD5:// 6502 CMP zeropage, X
              invalid(opcode);
              break;
          case 0xD6:// 6502 DEC zeropage, X
              opDEC(decodeMemoryMode(AddressMode.ZEROPAGE,this.reg_X));
              break;
          case 0xD7:// 65EL02 CMP (r, R), Y
              invalid(opcode);
              break;
          case 0xD8:// 6502 CLD
              invalid(opcode);
              break;
          case 0xD9:// 6502 CMP absolute, Y
              invalid(opcode);
              break;
  