/* * Copyright (c) 2011, Preston Skupinski * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ function CPU_65816() { // Registers this.r = { a:0, // Accumulator b:0, // "Hidden" Accumulator Register(high byte in 8-bit mode) x:0, // X Index Register y:0, // Y Index Register d:0, // Direct Page Register s:0xff, // Stack Pointer pc:0, // Program Counter dbr:0, // Data Bank Register k:0 // Program Bank Register }; // P register flags. this.p = { e:1, // Emulator (0 = native mode) c:0, // Carry (1 = carry) z:0, // Zero (1 = zero) i:0, // IRQ Disable (1 = disabled) d:0, // Decimal Mode (1 = decimal, 0 = binary) x:0, // Index Register Select (1 = 8-bit, 0 = 16-bit) m:0, // Memory/Accumulator Select (1 = 8-bit, 0 = 16-bit) v:0, // Overflow (1 = overflow) n:0 // Negative (1 = negative) }; this.INTERRUPT = { NO_INTERRUPT: 0, NMI: 1, RESET: 2, ABORT: 3, COP: 4, IRQ: 5, BRK: 6 }; this.interrupt = this.INTERRUPT.NO_INTERRUPT; // This is used to keep the cpu going if started with start(). this.executing = false; // This is set by the WAI operation to stop execution until an interrupt // is received. this.waiting = false; // This is set by the STP operation to stop execution until a RESET // interrupt is received. this.stopped = false; this.raise_interrupt = function(i) { if(this.waiting) { this.waiting = false; if(this.p.i) { if(i===this.INTERRUPT.IRQ) { i = 0; } } this.interrupt = i; this.start(); } else if(this.stopped&&(i===this.INTERRUPT.RESET)) { this.stopped = false; this.start(); } else { this.interrupt = i; } }; this.cycle_count = 0; this.mmu = new MMU(); this.mmu.cpu = this; this.opcode_map = { 0xfb : XCE, 0x18 : CLC, 0x78 : SEI, 0x38 : SEC, 0x58 : CLI, 0xc2 : REP, 0xe2 : SEP, 0xd8 : CLD, 0xf8 : SED, 0xb8 : CLV, 0xeb : XBA, 0xa9 : LDA_const, 0xad : LDA_absolute, 0xaf : LDA_absolute_long, 0xbf : LDA_absolute_long_indexed_x, 0xa5 : LDA_direct_page, 0xbd : LDA_absolute_indexed_x, 0xb5 : LDA_direct_page_indexed_x, 0xb9 : LDA_absolute_indexed_y, 0xa1 : LDA_direct_page_indexed_x_indirect, 0xb2 : LDA_direct_page_indirect, 0xa7 : LDA_direct_page_indirect_long, 0xb7 : LDA_direct_page_indirect_long_indexed_y, 0xb1 : LDA_direct_page_indirect_indexed_y, 0xa3 : LDA_stack_relative, 0xb3 : LDA_stack_relative_indirect_indexed_y, 0xa2 : LDX_const, 0xae : LDX_absolute, 0xa6 : LDX_direct_page, 0xa0 : LDY_const, 0xbc : LDY_absolute_indexed_x, 0xb4 : LDY_direct_page_indexed_x, 0xbe : LDX_absolute_indexed_y, 0xb6 : LDX_direct_page_indexed_y, 0xac : LDY_absolute, 0xa4 : LDY_direct_page, 0xea : NOP, 0x8d : STA_absolute, 0x85 : STA_direct_page, 0x8f : STA_absolute_long, 0x9f : STA_absolute_long_indexed_x, 0x81 : STA_direct_page_indexed_x_indirect, 0x92 : STA_direct_page_indirect, 0x87 : STA_direct_page_indirect_long, 0x97 : STA_direct_page_indirect_long_indexed_y, 0x91 : STA_direct_page_indirect_indexed_y, 0x9d : STA_absolute_indexed_x, 0x99 : STA_absolute_indexed_y, 0x95 : STA_direct_page_indexed_x, 0x83 : STA_stack_relative, 0x93 : STA_stack_relative_indirect_indexed_y, 0x8e : STX_absolute, 0x86 : STX_direct_page, 0x96 : STX_direct_page_indexed_y, 0x8c : STY_absolute, 0x84 : STY_direct_page, 0x94 : STY_direct_page_indexed_x, 0x1a : INC_accumulator, 0xe6 : INC_direct_page, 0xee : INC_absolute, 0xf6 : INC_direct_page_indexed_x, 0xfe : INC_absolute_indexed_x, 0xe8 : INX, 0xc8 : INY, 0x3a : DEC_accumulator, 0xce : DEC_absolute, 0xde : DEC_absolute_indexed_x, 0xc6 : DEC_direct_page, 0xca : DEX, 0x88 : DEY, 0xd6 : DEC_direct_page_indexed_x, 0x9c : STZ_absolute, 0x64 : STZ_direct_page, 0x9e : STZ_absolute_indexed_x, 0x74 : STZ_direct_page_indexed_x, 0x9b : TXY, 0xbb : TYX, 0xaa : TAX, 0xa8 : TAY, 0x8a : TXA, 0x98 : TYA, 0x5b : TCD, 0x7b : TDC, 0x1b : TCS, 0x3b : TSC, 0x4c : JMP_absolute, 0x5c : JMP_absolute_long, 0xdc : JMP_absolute_indirect_long, 0x7c : JMP_absolute_indexed_x_indirect, 0x6c : JMP_absolute_indirect, 0x80 : BRA, 0x82 : BRL, 0xf0 : BEQ, 0xd0 : BNE, 0x90 : BCC, 0xb0 : BCS, 0x50 : BVC, 0x70 : BVS, 0x10 : BPL, 0x30 : BMI, 0x69 : ADC_const, 0x6d : ADC_absolute, 0x61 : ADC_direct_page_indexed_x_indirect, 0x6f : ADC_absolute_long, 0x7f : ADC_absolute_long_indexed_x, 0x65 : ADC_direct_page, 0x72 : ADC_direct_page_indirect, 0x67 : ADC_direct_page_indirect_long, 0x77 : ADC_direct_page_indirect_long_indexed_y, 0x71 : ADC_direct_page_indirect_indexed_y, 0x7d : ADC_absolute_indexed_x, 0x79 : ADC_absolute_indexed_y, 0x75 : ADC_direct_page_indexed_x, 0x63 : ADC_stack_relative, 0x73 : ADC_stack_relative_indirect_indexed_y, 0xe9 : SBC_const, 0xed : SBC_absolute, 0xe5 : SBC_direct_page, 0xef : SBC_absolute_long, 0xff : SBC_absolute_long_indexed_x, 0xf2 : SBC_direct_page_indirect, 0xe1 : SBC_direct_page_indexed_x_indirect, 0xe7 : SBC_direct_page_indirect_long, 0xf7 : SBC_direct_page_indirect_long_indexed_y, 0xf1 : SBC_direct_page_indirect_indexed_y, 0xfd : SBC_absolute_indexed_x, 0xf9 : SBC_absolute_indexed_y, 0xf5 : SBC_direct_page_indexed_x, 0xe3 : SBC_stack_relative, 0xf3 : SBC_stack_relative_indirect_indexed_y, 0xc9 : CMP_const, 0xc5 : CMP_direct_page, 0xcd : CMP_absolute, 0xd2 : CMP_direct_page_indirect, 0xcf : CMP_absolute_long, 0xdf : CMP_absolute_long_indexed_x, 0xc7 : CMP_direct_page_indirect_long, 0xd7 : CMP_direct_page_indirect_long_indexed_y, 0xd5 : CMP_direct_page_indexed_x, 0xc1 : CMP_direct_page_indexed_x_indirect, 0xdd : CMP_absolute_indexed_x, 0xd9 : CMP_absolute_indexed_y, 0xd1 : CMP_direct_page_indirect_indexed_y, 0xc3 : CMP_stack_relative, 0xd3 : CMP_stack_relative_indirect_indexed_y, 0xe0 : CPX_const, 0xec : CPX_absolute, 0xe4 : CPX_direct_page, 0xc0 : CPY_const, 0xcc : CPY_absolute, 0xc4 : CPY_direct_page, 0x29 : AND_const, 0x2d : AND_absolute, 0x25 : AND_direct_page, 0x2f : AND_absolute_long, 0x3f : AND_absolute_long_indexed_x, 0x21 : AND_direct_page_indexed_x_indirect, 0x32 : AND_direct_page_indirect, 0x27 : AND_direct_page_indirect_long, 0x37 : AND_direct_page_indirect_long_indexed_y, 0x31 : AND_direct_page_indirect_indexed_y, 0x3d : AND_absolute_indexed_x, 0x39 : AND_absolute_indexed_y, 0x35 : AND_direct_page_indexed_x, 0x23 : AND_stack_relative, 0x33 : AND_stack_relative_indirect_indexed_y, 0x09 : ORA_const, 0x0f : ORA_absolute_long, 0x0d : ORA_absolute, 0x05 : ORA_direct_page, 0x1f : ORA_absolute_long_indexed_x, 0x12 : ORA_direct_page_indirect, 0x01 : ORA_direct_page_indexed_x_indirect, 0x07 : ORA_direct_page_indirect_long, 0x17 : ORA_direct_page_indirect_long_indexed_y, 0x11 : ORA_direct_page_indirect_indexed_y, 0x1d : ORA_absolute_indexed_x, 0x19 : ORA_absolute_indexed_y, 0x15 : ORA_direct_page_indexed_x, 0x03 : ORA_stack_relative, 0x13 : ORA_stack_relative_indirect_indexed_y, 0x49 : EOR_const, 0x4d : EOR_absolute, 0x4f : EOR_absolute_long, 0x5f : EOR_absolute_long_indexed_x, 0x45 : EOR_direct_page, 0x52 : EOR_direct_page_indirect, 0x41 : EOR_direct_page_indexed_x_indirect, 0x47 : EOR_direct_page_indirect_long, 0x57 : EOR_direct_page_indirect_long_indexed_y, 0x51 : EOR_direct_page_indirect_indexed_y, 0x5d : EOR_absolute_indexed_x, 0x59 : EOR_absolute_indexed_y, 0x55 : EOR_direct_page_indexed_x, 0x43 : EOR_stack_relative, 0x53 : EOR_stack_relative_indirect_indexed_y, 0x4a : LSR_accumulator, 0x4e : LSR_absolute, 0x46 : LSR_direct_page, 0x5e : LSR_absolute_indexed_x, 0x56 : LSR_direct_page_indexed_x, 0x0a : ASL_accumulator, 0x0e : ASL_absolute, 0x06 : ASL_direct_page, 0x1e : ASL_absolute_indexed_x, 0x16 : ASL_direct_page_indexed_x, 0x2a : ROL_accumulator, 0x2e : ROL_absolute, 0x26 : ROL_direct_page, 0x3e : ROL_absolute_indexed_x, 0x36 : ROL_direct_page_indexed_x, 0x6a : ROR_accumulator, 0x6e : ROR_absolute, 0x66 : ROR_direct_page, 0x7e : ROR_absolute_indexed_x, 0x76 : ROR_direct_page_indexed_x, 0x48 : PHA, 0x68 : PLA, 0x5a : PHY, 0x7a : PLY, 0xda : PHX, 0xfa : PLX, 0x08 : PHP, 0x28 : PLP, 0xf4 : PEA, 0xd4 : PEI, 0x8b : PHB, 0xab : PLB, 0x4b : PHK, 0x0b : PHD, 0x2b : PLD, 0x62 : PER, 0x20 : JSR, 0xfc : JSR_absolute_indexed_x_indirect, 0x60 : RTS, 0x22 : JSL, 0x6b : RTL, 0x54 : MVN, 0x44 : MVP, 0x00 : BRK, 0x40 : RTI, 0x02 : COP, 0x89 : BIT_const, 0x2c : BIT_absolute, 0x24 : BIT_direct_page, 0x3c : BIT_absolute_indexed_x, 0x34 : BIT_direct_page_indexed_x, 0x0c : TSB_absolute, 0x04 : TSB_direct_page, 0x1c : TRB_absolute, 0x14 : TRB_direct_page, 0x9a : TXS, 0xba : TSX, 0x42: WDM, 0xcb : WAI, 0xdb : STP }; /** * Load given program into memory and prepare for execution. */ this.load_binary = function(raw_hex, memory_location_start) { var loc = memory_location_start; var byte_buffer = []; for(var i = 0; i < raw_hex.length; i++) { byte_buffer.push(raw_hex[i]); if(byte_buffer.length===2) { this.mmu.store_byte(loc, parseInt(byte_buffer[0]+byte_buffer[1], "16")); loc++; byte_buffer = []; } } }; /** * Step through the processing of a single instruction from the current * location of the program counter. */ this.step = function() { if(this.interrupt&&(!this.p.i|(this.interrupt===this.INTERRUPT.NMI))) { // Load the related interrupt vector in page 0xff of bank zero. if(!this.p.e) { this.mmu.push_byte(this.r.k); } this.mmu.push_byte(this.r.pc>>8); this.mmu.push_byte(this.r.pc&0xff); var p_byte = (this.p.n<<7)|(this.p.v<<6)|(this.p.m<<5)|(this.p.x<<4)| (this.p.d<<3)|(this.p.i<<2)|(this.p.z<<1)|this.p.c; this.mmu.push_byte(p_byte); if(!this.p.e) this.p.d = 0; this.p.i = 1; this.r.k = 0; // Look for where to jump to for the interrupt. if(this.p.e) { // NMI if(this.interrupt===this.INTERRUPT.NMI) { var low_byte = this.mmu.read_byte_long(0xfffa, 0); var high_byte = this.mmu.read_byte_long(0xfffb, 0); this.r.pc = (high_byte<<8)|low_byte; // RESET } else if(this.interrupt===this.INTERRUPT.RESET) { var low_byte = this.mmu.read_byte_long(0xfffc, 0); var high_byte = this.mmu.read_byte_long(0xfffd, 0); this.r.pc = (high_byte<<8)|low_byte; // ABORT } else if(this.interrupt===this.INTERRUPT.ABORT) { var low_byte = this.mmu.read_byte_long(0xfff8, 0); var high_byte = this.mmu.read_byte_long(0xfff9, 0); this.r.pc = (high_byte<<8)|low_byte; // COP } else if(this.interrupt===this.INTERRUPT.COP) { var low_byte = this.mmu.read_byte_long(0xfff4, 0); var high_byte = this.mmu.read_byte_long(0xfff5, 0); this.r.pc = (high_byte<<8)|low_byte; // IRQ or BRK } else if(this.interrupt===this.INTERRUPT.IRQ | this.interrupt==this.INTERRUPT.BRK) { var low_byte = this.mmu.read_byte_long(0xfffe, 0); var high_byte = this.mmu.read_byte_long(0xffff, 0); this.r.pc = (high_byte<<8)|low_byte; } } else { // NMI if(this.interrupt===this.INTERRUPT.NMI) { var low_byte = this.mmu.read_byte_long(0xffea, 0); var high_byte = this.mmu.read_byte_long(0xffeb, 0); this.r.pc = (high_byte<<8)|low_byte; // ABORT } else if(this.interrupt===this.INTERRUPT.ABORT) { var low_byte = this.mmu.read_byte_long(0xffe8, 0); var high_byte = this.mmu.read_byte_long(0xffe9, 0); this.r.pc = (high_byte<<8)|low_byte; // COP } else if(this.interrupt===this.INTERRUPT_COP) { var low_byte = this.mmu.read_byte_long(0xffe4, 0); var high_byte = this.mmu.read_byte_long(0xffe5, 0); this.r.pc = (high_byte<<8)|low_byte; // IRQ } else if(this.interrupt===this.INTERRUPT.IRQ) { var low_byte = this.mmu.read_byte_long(0xffee, 0); var high_byte = this.mmu.read_byte_long(0xffef, 0); this.r.pc = (high_byte<<8)|low_byte; // BRK } else if(this.interrupt===this.INTERRUPT.BRK) { var low_byte = this.mmu.read_byte_long(0xffe6, 0); var high_byte = this.mmu.read_byte_long(0xffe7, 0); this.r.pc = (high_byte<<8)|low_byte; } } this.interrupt = this.INTERRUPT.NO_INTERRUPT; } var b = this.mmu.read_byte_long(this.r.pc, this.r.k); this.r.pc++; // If we reach the end of the code then stop everything. if(b==null) { this.executing = false; return; } var operation = this.opcode_map[b]; var bytes_required = operation.bytes_required(this); if(bytes_required===1) { operation.execute(this); } else { var bytes = []; for(var i = 1; i < bytes_required; i++) { bytes.push(this.mmu.read_byte_long(this.r.pc, this.r.k)); this.r.pc++; } operation.execute(this,bytes); } if(this.waiting||this.stopped) this.executing = false; }; /** * TODO: Add ability for this function to limit number of cpu cycles per * second. */ this.execute = function(start_address) { this.r.pc = start_address; this.executing = true; while(this.executing) { this.step(); } }; this.reset = function() { this.executing = false; this.waiting = false; this.stopped = false; this.interrupt = this.INTERRUPT.NO_INTERRUPT; this.r = { a:0, b:0, x:0, y:0, d:0, s:0xff, pc:0, dbr:0, k:0 }; this.p = { e:1, c:0, z:0, i:0, d:0, x:0, m:0, v:0, n:0 }; this.mmu.reset(); this.cycle_count = 0; }; } function MMU() { this.cpu = {}; this.memory = { 0: {} }; this.memory_mapped_io_devices = {}; this.reset = function() { this.memory ={ 0: {} }; }; this.add_memory_mapped_io_device = function(write_callback, read_callback, bank, location) { if(typeof this.memory_mapped_io_devices[bank] === 'undefined') { this.memory_mapped_io_devices[bank] = {}; } this.memory_mapped_io_devices[bank][location] = { write: write_callback, read: read_callback }; }; this.pull_byte = function() { if(this.cpu.p.e) { if(this.cpu.r.s===0xff) { this.cpu.r.s = 0; return this.read_byte(0x100); } else { return this.read_byte(0x100|(++this.cpu.r.s)); } } else { return this.read_byte(++this.cpu.r.s); } }; this.push_byte = function(b) { if(this.cpu.p.e) { if(this.cpu.r.s===0) { this.store_byte(0x100, b); this.cpu.r.s = 0xff; } else { this.store_byte((0x100|(this.cpu.r.s--)), b); } } else { this.store_byte(this.cpu.r.s--, b); } }; this.read_byte = function(location) { var device_map_at_bank = this.memory_mapped_io_devices[this.cpu.r.dbr]; if(device_map_at_bank!=null) { var device = device_map_at_bank[location]; if(device!=null) return device.read(this.cpu); } return this.memory[this.cpu.r.dbr][location]; }; this.read_byte_long = function(location, bank) { if(typeof this.memory[bank] === 'undefined') { this.memory[bank] = {}; } var device_map_at_bank = this.memory_mapped_io_devices[bank]; if(device_map_at_bank!=null) { var device = device_map_at_bank[location]; if(device!=null) return device.read(this.cpu); } return this.memory[bank][location]; }; this.store_byte = function(location, b) { var device_map_at_bank = this.memory_mapped_io_devices[this.cpu.r.dbr]; if(device_map_at_bank!=null) { var device = device_map_at_bank[location]; if(device!=null) device.write(this.cpu, b); } this.memory[this.cpu.r.dbr][location] = b; }; this.store_byte_long = function(location, bank, b) { if(typeof this.memory[bank] === 'undefined') { this.memory[bank] = {}; } var device_map_at_bank = this.memory_mapped_io_devices[bank]; if(device_map_at_bank!=null) { var device = device_map_at_bank[location]; if(device!=null) device.write(this.cpu, b); } this.memory[bank][location] = b; }; } var STP = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; cpu.stopped = true; } }; var WAI = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; cpu.waiting = true; } }; var WDM = { bytes_required:function() { return 2; }, execute:function() {} }; var TXS = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.r.s = cpu.r.x; if(cpu.p.e|cpu.p.x) { cpu.p.n = cpu.r.s >> 7; } else { cpu.p.n = cpu.r.s >> 15; } if(cpu.r.s===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TSX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.r.s & 0xff; cpu.p.n = cpu.r.x >> 7; } else { cpu.r.x = cpu.r.s; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TRB_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { var data = cpu.mmu.read_byte(location); if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } cpu.mmu.store_byte(location, (~cpu.r.a & data)); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); var data = (high_byte<<8) | low_byte; if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } data &= ~cpu.r.a; high_byte = data >> 8; low_byte = data & 0xff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var TRB_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var data = cpu.mmu.read_byte(location&0xffff); if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } cpu.mmu.store_byte(location&0xffff, (~cpu.r.a & data)); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); var data = (high_byte<<8) | low_byte; if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } data &= ~cpu.r.a; high_byte = data >> 8; low_byte = data & 0xff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var TSB_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { var data = cpu.mmu.read_byte(location); if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } cpu.mmu.store_byte(location, (cpu.r.a | data)); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); var data = (high_byte<<8) | low_byte; if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } data |= cpu.r.a; high_byte = data >> 8; low_byte = data & 0xff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var TSB_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var data = cpu.mmu.read_byte(location&0xffff); if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } cpu.mmu.store_byte(location&0xffff, (cpu.r.a | data)); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); var data = (high_byte<<8) | low_byte; if((data & cpu.r.a) === 0) { cpu.p.z = 1; } else { cpu.p.z = 0; } data |= cpu.r.a; high_byte = data >> 8; low_byte = data & 0xff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var BIT_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) return 2; else return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var and_result; if(cpu.p.e|cpu.p.m) { cpu.p.n = bytes[0] >> 7; cpu.p.v = (bytes[0] >> 6) & 0x1; and_result = cpu.r.a & bytes[0]; } else { cpu.cycle_count++; var argument = (bytes[1]<<8)|bytes[0]; cpu.p.n = bytes[1] >> 7; cpu.p.v = (bytes[1] >> 6) & 0x1; and_result = cpu.r.a & argument; } if(and_result===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var BIT_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { BIT_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); BIT_const.execute(cpu, [low_byte, high_byte]); } } }; var BIT_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { BIT_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); BIT_const.execute(cpu, [low_byte, high_byte]); } } }; var BIT_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_location = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_location, 0); BIT_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var args = [cpu.mmu.read_byte((high_byte_loc<<8)|low_byte_loc)]; BIT_const.execute(cpu, args); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } BIT_const.execute(cpu, [low_byte, high_byte]); } } }; var BIT_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; BIT_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var COP = { bytes_required:function() { return 2; }, execute:function(cpu) { cpu.cycle_count+=7; if(cpu.p.e===0) cpu.cycle_count++; cpu.interrupt = cpu.INTERRUPT.COP; } }; var BRK = { bytes_required:function() { return 2; }, execute:function(cpu) { cpu.cycle_count+=7; if(cpu.p.e===0) cpu.cycle_count++; cpu.interrupt = cpu.INTERRUPT.BRK; if(cpu.p.e) cpu.p.m = 1; } }; var RTI = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=6; if(cpu.p.e===0) cpu.cycle_count++; var p_byte = cpu.mmu.pull_byte(); var pc_low = cpu.mmu.pull_byte(); var pc_high = cpu.mmu.pull_byte(); cpu.r.pc = (pc_high<<8)|pc_low; cpu.p.c = p_byte & 0x01; cpu.p.z = (p_byte & 0x02) >> 1; cpu.p.i = (p_byte & 0x04) >> 2; cpu.p.d = (p_byte & 0x08) >> 3; cpu.p.x = (p_byte & 0x10) >> 4; cpu.p.m = (p_byte & 0x20) >> 5; cpu.p.v = (p_byte & 0x40) >> 6; cpu.p.n = p_byte >> 7; if(!cpu.p.e) { cpu.r.k = cpu.mmu.pull_byte(); } } }; // MVN is a really weird instruction, until the accumulator underflows MVN // will keep decrementing the program counter to have it continue to execute. var MVN = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=7; // TODO: One piece of reference material I've read claims that this // operation should always work with a 16-bit accumulator even if in // emulation mode or the m bit is set to 1, in those cases it claims that // you should concatenate the B "hidden" register with A. I'm going to // need to test this claim out somehow. var b = cpu.mmu.read_byte_long(cpu.r.x,bytes[1]); cpu.r.dbr = bytes[0]; cpu.mmu.store_byte(cpu.r.y, b); cpu.r.x++; cpu.r.y++; if(cpu.p.e|cpu.p.x) { cpu.r.x &= 0x00ff; cpu.r.y &= 0x00ff; } else { cpu.r.x &= 0xffff; cpu.r.y &= 0xffff; } if(cpu.r.a!=0) { cpu.r.a--; cpu.r.pc-=3; } else { if(cpu.p.e|cpu.p.m) cpu.r.a = 0xff; else cpu.r.a = 0xffff; } } }; // MVP is a really weird instruction, until the accumulator reaches $FFFF MVP // will keep decrementing the program counter to have it continue to execute. var MVP = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=7; // TODO: One piece of reference material I've read claims that this // operation should always work with a 16-bit accumulator even if in // emulation mode or the m bit is set to 1, in those cases it claims that // you should concatenate the B "hidden" register with A. I'm going to // need to test this claim out somehow. var b = cpu.mmu.read_byte_long(cpu.r.x,bytes[1]); cpu.r.dbr = bytes[0]; cpu.mmu.store_byte(cpu.r.y,b); var index_register_wrap; if(cpu.p.e|cpu.p.x) { index_register_wrap = 0xff; } else { index_register_wrap = 0xffff; } if(cpu.r.y===index_register_wrap) { cpu.r.y = 0; } else { cpu.r.y--; } if(cpu.r.x===index_register_wrap) { cpu.r.x = 0; } else { cpu.r.x--; } if(cpu.r.a!=0) { cpu.r.pc-=3; cpu.r.a--; } else { if(cpu.p.e|cpu.p.m) cpu.r.a = 0xff; else cpu.r.a = 0xffff; } } }; var JSL = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=8; var location = cpu.r.pc - 1; var low_byte = location & 0x00ff; var high_byte = location >> 8; cpu.mmu.push_byte(cpu.r.k); cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); cpu.r.k = bytes[2]; cpu.r.pc = (bytes[1]<<8)|bytes[0]; } }; var RTL = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=6; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.k = cpu.mmu.pull_byte(); cpu.r.pc = ((high_byte<<8)|low_byte) + 1; } }; var JSR = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = cpu.r.pc - 1; var low_byte = location & 0x00ff; var high_byte = location >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); cpu.r.pc = (bytes[1]<<8)|bytes[0]; } }; var JSR_absolute_indexed_x_indirect = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=8; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var bank = cpu.r.k; if(location&0x10000) { bank++; } location &= 0xffff; var indirect_location_low_byte = cpu.mmu.read_byte_long(location, bank); var indirect_location_high_byte = cpu.mmu.read_byte_long(location+1, bank); var indirect_location = (indirect_location_high_byte<<8) | indirect_location_low_byte; var low_byte = cpu.mmu.read_byte(indirect_location); bank = cpu.r.k; if(indirect_location===0xffff) { indirect_location = 0; bank++; } else { indirect_location++; } var high_byte = cpu.mmu.read_byte_long(indirect_location, bank); JSR.execute(cpu, [low_byte, high_byte]); } }; var RTS = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=6; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.pc = ((high_byte<<8)|low_byte) + 1; } }; var PER = { bytes_required:function() { return 3; }, execute:function(cpu,bytes) { cpu.cycle_count+=6; var address = ((bytes[1]<<8)|bytes[0]) + cpu.r.pc; var low_byte = address & 0x00ff; var high_byte = address >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } }; var PHK = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; cpu.mmu.push_byte(cpu.r.k); } }; var PHD = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; var low_byte = cpu.r.d & 0x00ff; var high_byte = cpu.r.d >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } }; var PLD = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=5; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.d = (high_byte<<8)|low_byte; cpu.p.n = cpu.r.d >> 15; if(cpu.r.d===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var PHB = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; cpu.mmu.push_byte(cpu.r.dbr); } }; var PLB = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; cpu.r.dbr = cpu.mmu.pull_byte(); cpu.p.n = cpu.r.dbr >> 7; if(cpu.r.dbr===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var PEA = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; cpu.mmu.push_byte(bytes[1]); cpu.mmu.push_byte(bytes[0]); } }; var PEI = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } }; var PHP = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; var p_byte = (cpu.p.n<<7)|(cpu.p.v<<6)|(cpu.p.m<<5)|(cpu.p.x<<4)| (cpu.p.d<<3)|(cpu.p.i<<2)|(cpu.p.z<<1)|cpu.p.c; cpu.mmu.push_byte(p_byte); } }; var PLP = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; var p_byte = cpu.mmu.pull_byte(); cpu.p.c = p_byte & 0x01; cpu.p.z = (p_byte & 0x02) >> 1; cpu.p.i = (p_byte & 0x04) >> 2; cpu.p.d = (p_byte & 0x08) >> 3; cpu.p.x = (p_byte & 0x10) >> 4; cpu.p.m = (p_byte & 0x20) >> 5; cpu.p.v = (p_byte & 0x40) >> 6; cpu.p.n = p_byte >> 7; } }; var PHX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; if(cpu.p.e|cpu.p.x) { cpu.mmu.push_byte(cpu.r.x); } else { cpu.cycle_count++; var low_byte = cpu.r.x & 0x00ff; var high_byte = cpu.r.x >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } } }; var PLX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.mmu.pull_byte(); cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.x = (high_byte<<8)|low_byte; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var PHY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; if(cpu.p.e|cpu.p.x) { cpu.mmu.push_byte(cpu.r.y); } else { cpu.cycle_count++; var low_byte = cpu.r.y & 0x00ff; var high_byte = cpu.r.y >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } } }; var PLY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; if(cpu.p.e|cpu.p.x) { cpu.r.y = cpu.mmu.pull_byte(); cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.y = (high_byte<<8)|low_byte; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var PHA = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; if(cpu.p.e|cpu.p.m) { cpu.mmu.push_byte(cpu.r.a); } else { cpu.cycle_count++; var low_byte = cpu.r.a & 0x00ff; var high_byte = cpu.r.a >> 8; cpu.mmu.push_byte(high_byte); cpu.mmu.push_byte(low_byte); } } }; var PLA = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=4; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.pull_byte(); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.pull_byte(); var high_byte = cpu.mmu.pull_byte(); cpu.r.a = (high_byte<<8)|low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROR_accumulator = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { var old_c = cpu.p.c; cpu.p.c = cpu.r.a & 0x01; cpu.r.a = cpu.r.a >> 1; cpu.r.a &= 0x7f; cpu.r.a |= (old_c<<7); cpu.p.n = cpu.r.a >> 7; } else { var old_c = cpu.p.c; cpu.p.c = cpu.r.a & 0x0001; cpu.r.a = cpu.r.a >> 1; cpu.r.a &= 0x7fff; cpu.r.a |= (old_c<<15); cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROR_absolute = { bytes_required:function() { return 3; }, execute:function(cpu,bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); var old_c = cpu.p.c; cpu.p.c = shiftee & 0x01; shiftee = shiftee >> 1; shiftee &= 0x7f; shiftee |= (old_c<<7); cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; var old_c = cpu.p.c; cpu.p.c = shiftee & 0x0001; shiftee = shiftee >> 1; shiftee &= 0x7fff; shiftee |= (old_c<<15); cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROR_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu,bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); var old_c = cpu.p.c; cpu.p.c = shiftee & 0x01; shiftee = shiftee >> 1; shiftee &= 0x7f; shiftee |= (old_c<<7); cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; var old_c = cpu.p.c; cpu.p.c = shiftee & 0x0001; shiftee = shiftee >> 1; shiftee &= 0x7fff; shiftee |= (old_c<<15); cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROR_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count++; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ROR_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ROR_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; ROR_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var ROL_accumulator = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { var old_c = cpu.p.c; cpu.p.c = cpu.r.a >> 7; cpu.r.a = cpu.r.a << 1; cpu.r.a &= 0xfe; cpu.r.a |= old_c; cpu.p.n = cpu.r.a >> 7; } else { var old_c = cpu.p.c; cpu.p.c = cpu.r.a >> 15; cpu.r.a = cpu.r.a << 1; cpu.r.a &= 0xfffe; cpu.r.a |= old_c; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROL_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); var old_c = cpu.p.c; cpu.p.c = shiftee >> 7; shiftee = shiftee << 1; shiftee &= 0xfe; shiftee |= old_c; cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; var old_c = cpu.p.c; cpu.p.c = shiftee >> 15; shiftee = shiftee << 1; shiftee &= 0xfffe; shiftee |= old_c; cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROL_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); var old_c = cpu.p.c; cpu.p.c = shiftee >> 7; shiftee = shiftee << 1; shiftee &= 0xfe; shiftee |= old_c; cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; var old_c = cpu.p.c; cpu.p.c = shiftee >> 15; shiftee = shiftee << 1; shiftee &= 0xfffe; shiftee |= old_c; cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ROL_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count++; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ROL_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ROL_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; ROL_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var ASL_accumulator = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { cpu.p.c = cpu.r.a >> 7; cpu.r.a = cpu.r.a << 1; cpu.r.a &= 0xff; cpu.p.n = cpu.r.a >> 7; } else { cpu.p.c = cpu.r.a >> 15; cpu.r.a = cpu.r.a << 1; cpu.r.a &= 0xffff; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ASL_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); cpu.p.c = shiftee >> 7; shiftee = shiftee << 1; shiftee &= 0xff; cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; cpu.p.c = shiftee >> 15; shiftee = shiftee << 1; shiftee &= 0xffff; cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ASL_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu,bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.read_byte(location); cpu.p.c = shiftee >> 7; shiftee = shiftee << 1; shiftee &= 0xff; cpu.p.n = shiftee >> 7; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; cpu.p.c = shiftee >> 15; shiftee = shiftee << 1; shiftee &= 0xffff; cpu.p.n = shiftee >> 15; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ASL_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count++; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ASL_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ASL_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; ASL_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var LSR_accumulator = { bytes_required:function(cpu) { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.p.c = cpu.r.a & 1; cpu.r.a = cpu.r.a >> 1; cpu.p.n = 0; if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LSR_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.ready_byte(location); cpu.p.c = shiftee & 0x0001; shiftee = shiftee >> 1; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; cpu.p.c = cpu.r.a & 0x01; shiftee = shiftee >> 1; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } cpu.p.n = 0; if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LSR_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var shiftee; if(cpu.p.e|cpu.p.m) { shiftee = cpu.mmu.ready_byte(location); cpu.p.c = shiftee & 0x0001; shiftee = shiftee >> 1; cpu.mmu.store_byte(location, shiftee); } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); shiftee = (high_byte<<8)|low_byte; cpu.p.c = cpu.r.a & 0x01; shiftee = shiftee >> 1; low_byte = shiftee & 0x00ff; high_byte = shiftee >> 8; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } cpu.p.n = 0; if(shiftee===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LSR_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count++; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; LSR_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var LSR_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; LSR_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var EOR_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { cpu.r.a ^= bytes[0]; cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; cpu.r.a ^= (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var EOR_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); EOR_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); EOR_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle-count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); EOR_const.execute(cpu, [low_byte, high_byte]); } } }; var EOR_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; EOR_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var EOR_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; EOR_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var EOR_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; EOR_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var EOR_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); EOR_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { EOR_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); EOR_const.execute(cpu, [low_byte, high_byte]); } } } }; var EOR_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } EOR_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } EOR_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } EOR_const.execute(cpu, [low_byte, high_byte]); } } } }; var ORA_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { cpu.r.a |= bytes[0]; cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; cpu.r.a |= (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ORA_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); ORA_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); ORA_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); ORA_const.execute(cpu, [low_byte, high_byte]); } } }; var ORA_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((location&0xff00)!=(original_location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ORA_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ORA_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ORA_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ORA_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; ORA_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var ORA_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); ORA_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { ORA_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ORA_const.execute(cpu, [low_byte, high_byte]); } } } }; var ORA_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } ORA_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } ORA_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } ORA_const.execute(cpu, [low_byte, high_byte]); } } } }; var AND_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { cpu.r.a &= bytes[0]; cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; cpu.r.a &= (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var AND_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); AND_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); AND_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8)| low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle-count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); AND_const.execute(cpu, [low_byte, high_byte]); } } }; var AND_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((location&0xff00)!=(original_location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; AND_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var AND_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; AND_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var AND_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; AND_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var AND_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); AND_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { AND_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); AND_const.execute(cpu, [low_byte, high_byte]); } } } }; var AND_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } AND_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } AND_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } AND_const.execute(cpu, [low_byte, high_byte]); } } } }; var CPX_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.x) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var result; if(cpu.p.e|cpu.p.x) { result = cpu.r.x - bytes[0]; if(result<0) { cpu.p.c = 0; result = 0x100 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 7; } else { cpu.cycle_count++; result = cpu.r.x - ((bytes[1]<<8)|bytes[0]); if(result<0) { cpu.p.c = 0; result = 0x10000 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 15; } if(result===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var CPX_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { CPX_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CPX_const.execute(cpu, [low_byte, high_byte]); } } }; var CPX_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { CPX_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CPX_const.execute(cpu, [low_byte, high_byte]); } } }; var CPY_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.x) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var result; if(cpu.p.e|cpu.p.x) { result = cpu.r.y - bytes[0]; if(result<0) { cpu.p.c = 0; result = 0x100 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 7; } else { cpu.cycle_count++; result = cpu.r.y - ((bytes[1]<<8)|bytes[0]); if(result<0) { cpu.p.c = 0; result = 0x10000 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 15; } if(result===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var CPY_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { CPY_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CPY_const.execute(cpu, [low_byte, high_byte]); } } }; var CPY_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { CPY_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CPY_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var result; if(cpu.p.e|cpu.p.m) { result = cpu.r.a - bytes[0]; if(result<0) { cpu.p.c = 0; result = 0x100 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 7; } else { cpu.cycle_count++; result = cpu.r.a - ((bytes[1]<<8)|bytes[0]); if(result<0) { cpu.p.c = 0; result = 0x10000 + result; } else { cpu.p.c = 1; } cpu.p.n = result >> 15; } if(result===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var CMP_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; CMP_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var CMP_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); CMP_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); CMP_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8)| low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); CMP_const.execute(cpu, [low_byte, high_byte]); } } }; var CMP_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; CMP_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var CMP_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; CMP_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var CMP_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cyle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); CMP_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { CMP_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); CMP_const.execute(cpu, [low_byte, high_byte]); } } } }; var CMP_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } CMP_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } CMP_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } CMP_const.execute(cpu, [low_byte, high_byte]); } } } }; var SBC_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var old_a = cpu.r.a; var temp = 0; if(cpu.p.c===0) temp = 1; if(cpu.p.e|cpu.p.m) { if(cpu.p.d) { // Form a decimal number out of a. var ones = cpu.r.a & 0x0f; var tens = cpu.r.a >> 4; var dec_a = (tens*10)+ones; // Form a decimal number out of the argument. ones = bytes[0] & 0x0f; tens = bytes[0] >> 4; var dec_arg = (tens*10)+ones; var result = dec_a - dec_arg - temp; // Check for decimal overflow. if(result<0) { result += 100; cpu.p.c = 0; } else { cpu.p.c = 1; } var digits = result.toString(10).split(""); var i = 0; cpu.r.a = 0; for(i=0;i> 7; // Check for signed overflow. // If they started with the same sign and then the resulting sign is // different then we have a signed overflow. if((!((old_a ^ bytes[0]) & 0x80)) && ((cpu.r.a ^ old_a) & 0x80)) { cpu.p.v = 1; } else { cpu.p.v = 0; } } } else { cpu.cycle_count++; var argument = (bytes[1]<<8)|bytes[0]; var temp = 0; if(cpu.p.c===0) temp = 1; if(cpu.p.d) { // Form a decimal number out of a. var ones = cpu.r.a & 0xf; var tens = (cpu.r.a >>4) & 0xf; var hundreds = (cpu.r.a >> 8) & 0xf; var thousands = (cpu.r.a >> 12) & 0xf; var dec_a = (thousands*1000)+(hundreds*100)+(tens*10)+ones; // Form a decimal number out of the argument. ones = argument & 0xf; tens = (argument >> 4) & 0xf; hundreds = (argument >> 8) & 0xf; thousands = (argument >> 12) & 0xf; var dec_arg = (thousands*1000)+(hundreds*100)+(tens*10)+ones; var result = dec_a - dec_arg - temp; // Check for decimal overflow. if(result<0) { result += 10000; cpu.p.c = 0; } else { cpu.p.c = 1; } var digits = result.toString(10).split(""); var i = 0; cpu.r.a = 0; for(i=0;i> 15; // Check for signed overflow. // If they started with the same sign and then the resulting sign is // different then we have a signed overflow. if((!((old_a ^ argument) & 0x8000)) && ((cpu.r.a ^ old_a) & 0x8000)) { cpu.p.v = 1; } else { cpu.p.v = 0; } } } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var SBC_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cyle_count+=3; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); SBC_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); SBC_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; SBC_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var SBC_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; SBC_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var SBC_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; SBC_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var SBC_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); SBC_const.execute(cpu, [low_byte, high_byte]); } } }; var SBC_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); SBC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { SBC_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); SBC_const.execute(cpu, [low_byte, high_byte]); } } } }; var SBC_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } SBC_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } SBC_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } SBC_const.execute(cpu, [low_byte, high_byte]); } } } }; var ADC_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute:function(cpu, bytes) { var old_a = cpu.r.a; if(cpu.p.e|cpu.p.m) { cpu.cycle_count+=2; if(cpu.p.d) { // Form a decimal number out of a. var ones = cpu.r.a & 0x0f; var tens = cpu.r.a >>4; var dec_a = (tens*10)+ones; // Form a decimal number out of the argument. ones = bytes[0] & 0x0f; tens = bytes[0] >>4; var dec_arg = (tens*10)+ones; var result = dec_a + dec_arg + cpu.p.c; // Check for decimal overflow. if(result>99) { result -= 99; cpu.p.c = 1; } else { cpu.p.c = 0; } var digits = result.toString(10).split(""); var i = 0; cpu.r.a = 0; for(i=0;i> 7; // Check for signed overflow. // If they started with the same sign and then the resulting sign is // different then we have a signed overflow. if((!((old_a ^ bytes[0]) & 0x80)) && ((cpu.r.a ^ old_a) & 0x80)) { cpu.p.v = 1; } else { cpu.p.v = 0; } } } else { cpu.cycle_count+=3; var argument = (bytes[1]<<8)|bytes[0]; if(cpu.p.d) { // Form a decimal number out of a. var ones = cpu.r.a & 0xf; var tens = (cpu.r.a >>4) & 0xf; var hundreds = (cpu.r.a >> 8) & 0xf; var thousands = (cpu.r.a >> 12) & 0xf; var dec_a = (thousands*1000)+(hundreds*100)+(tens*10)+ones; // Form a decimal number out of the argument. ones = argument & 0xf; tens = (argument >> 4) & 0xf; hundreds = (argument >> 8) & 0xf; thousands = (argument >> 12) & 0xf; var dec_arg = (thousands*1000)+(hundreds*100)+(tens*10)+ones; var result = dec_a + dec_arg + cpu.p.c; // Check for decimal overflow. if(result>9999) { result -= 9999; cpu.p.c = 1; } else { cpu.p.c = 0; } var digits = result.toString(10).split(""); var i = 0; cpu.r.a = 0; for(i=0;i> 15; // Check for signed overflow. // If they started with the same sign and then the resulting sign is // different then we have a signed overflow. if((!((old_a ^ argument) & 0x8000)) && ((cpu.r.a ^ old_a) & 0x8000)) { cpu.p.v = 1; } else { cpu.p.v = 0; } } } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var ADC_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var location = (bytes[1]<<8)|bytes[0]; cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { var location = (bytes[1]<<8)|bytes[0]; cpu.cycle_count+=3; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte_long(location, bytes[2])]); } else { var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=2; else cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=4; else cpu.cycle_count+=3; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=5; else cpu.cycle_count+=4; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); ADC_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); ADC_const.execute(cpu, [cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc)]); } else { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=5; else cpu.cycle_count+=4; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { absolute_location &= 0xffff; bank_byte++; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=5; else cpu.cycle_count+=4; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte_long(absolute_location, bank_byte)]); } else { var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { if((cpu.r.d&0x00ff)!=0) cpu.cycle_count+=4; else cpu.cycle_count+=3; var location = bytes[0] + cpu.r.d; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var initial_absolute_location = ((high_byte_loc<<8) | low_byte_loc); var absolute_location = initial_absolute_location + cpu.r.y; // Add 1 cycle if page boundary crossed if((initial_absolute_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte(absolute_location)]); } else { var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); ADC_const.execute(cpu, [low_byte, high_byte]); } } }; var ADC_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var initial_location = (bytes[1]<<8)|bytes[0]; var location = initial_location+cpu.r.x; // Add 1 cycle if page boundary crossed if((location&0xff00)!=(initial_location&0xff00)) cpu.cycle_count+=3; else cpu.cycle_count+=2; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ADC_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ADC_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { var initial_location = (bytes[1]<<8)|bytes[0]; var location = initial_location+cpu.r.y; // Add 1 cycle if page boundary crossed if((location&0xff00)!=(initial_location&0xff00)) cpu.cycle_count+=3; else cpu.cycle_count+=2; var location_high_byte = location >> 8; var location_low_byte = location & 0x00ff; ADC_absolute.execute(cpu, [location_low_byte, location_high_byte]); } }; var ADC_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count++; ADC_direct_page.execute(cpu, [bytes[0]+cpu.r.x]); } }; var ADC_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); ADC_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { ADC_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); ADC_const.execute(cpu, [low_byte, high_byte]); } } } }; var ADC_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } ADC_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } ADC_const.execute(cpu, [b]); } else { var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } ADC_const.execute(cpu, [low_byte, high_byte]); } } } }; var BMI = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(cpu.p.n) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BPL = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(!cpu.p.n) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BVC = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(!cpu.p.v) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BVS = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(cpu.p.v) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BCC = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(!cpu.p.c) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BCS = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(cpu.p.c) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BEQ = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(cpu.p.z) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BNE = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e) cpu.cycle_count++; if(!cpu.p.z) { cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } } }; var BRA = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if(cpu.p.e) cpu.cycle_count++; // Handle single byte two's complement numbers as the branch argument. if(bytes[0]<=127) { cpu.r.pc+=bytes[0]; cpu.r.pc&=0xffff; } else { cpu.r.pc-=256-bytes[0]; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } }; var BRL = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; // Handle double byte two's complement numbers as the branch argument. var num = (bytes[1]<<8)|bytes[0]; if(num<=32767) { cpu.r.pc+=num; cpu.r.pc&=0xffff; } else { cpu.r.pc-=65536-num; if(cpu.r.pc<0) cpu.r.pc+=0xffff; } } }; var JMP_absolute_indirect = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; var location = (bytes[1]<<8)|bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.pc = (high_byte<<8) | low_byte; } }; var JMP_absolute_long = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; cpu.r.k = bytes[2]; cpu.r.pc = (bytes[1]<<8)|bytes[0]; } }; var JMP_absolute_indirect_long = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.pc = (high_byte<<8) | low_byte; cpu.r.k = cpu.mmu.read_byte(location+2); } }; var JMP_absolute_indexed_x_indirect = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; var bank = cpu.r.k; if(location&0x10000) { bank++; } location &= 0xffff; var indirect_location_low_byte = cpu.mmu.read_byte_long(location, bank); var indirect_location_high_byte = cpu.mmu.read_byte_long(location+1, bank); var indirect_location = (indirect_location_high_byte<<8) | indirect_location_low_byte; var low_byte = cpu.mmu.read_byte(indirect_location); bank = cpu.r.k; if(indirect_location===0xffff) { indirect_location = 0; bank++; } else { indirect_location++; } var high_byte = cpu.mmu.read_byte_long(indirect_location, bank); cpu.r.pc = (high_byte<<8)|low_byte; } }; var JMP_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; cpu.r.pc = (bytes[1]<<8)|bytes[0]; } }; var TYA = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { if(cpu.p.e|cpu.p.x) { // 8-bit index register to 8-bit accumulator. cpu.r.a = cpu.r.y; } else { // 16-bit index register to 8-bit accumulator. cpu.r.a = cpu.r.y & 0x00ff; } cpu.p.n = cpu.r.a >> 7; } else { // 8-bit index register to 16-bit accumulator. // 16-bit index register to 16-bit accumulator. cpu.r.a = cpu.r.y; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TAY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { if(cpu.p.e|cpu.p.x) { // 8-bit accumulator to 8-bit x index register. cpu.r.y = cpu.r.a; cpu.p.n = cpu.r.y >> 7; } else { // 8-bit accumulator to 16-bit x index register. cpu.r.y = cpu.r.b; // Transfer b as high-byte of x. cpu.r.y |= cpu.r.a; // Use the bitwise or to add a as the low-byte. cpu.p.n = cpu.r.y >> 15; } } else { if(cpu.p.x) { // 16-bit accumulator to 8-bit x index register. cpu.r.y = cpu.r.a & 0x00ff; // Transfer only the low-byte to x. cpu.p.n = cpu.r.y >> 7; } else { // 16-bit accumulator to 16-bit x index register. cpu.r.y = cpu.r.a; cpu.p.n = cpu.r.y >> 15; } } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TXA = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { if(cpu.p.e|cpu.p.x) { // 8-bit index register to 8-bit accumulator. cpu.r.a = cpu.r.x; } else { // 16-bit index register to 8-bit accumulator. cpu.r.a = cpu.r.x & 0x00ff; } cpu.p.n = cpu.r.a >> 7; } else { // 8-bit index register to 16-bit accumulator. // 16-bit index register to 16-bit accumulator. cpu.r.a = cpu.r.x; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TAX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { if(cpu.p.e|cpu.p.x) { // 8-bit accumulator to 8-bit x index register. cpu.r.x = cpu.r.a; cpu.p.n = cpu.r.x >> 7; } else { // 8-bit accumulator to 16-bit x index register. cpu.r.x = cpu.r.b; // Transfer b as high-byte of x. cpu.r.x |= cpu.r.a; // Use the bitwise or to add a as the low-byte. cpu.p.n = cpu.r.x >> 15; } } else { if(cpu.p.x) { // 16-bit accumulator to 8-bit x index register. cpu.r.x = cpu.r.a & 0x00ff; // Transfer only the low-byte to x. cpu.p.n = cpu.r.x >> 7; } else { // 16-bit accumulator to 16-bit x index register. cpu.r.x = cpu.r.a; cpu.p.n = cpu.r.x >> 15; } } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TXY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.r.y = cpu.r.x; if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } if(cpu.p.e|cpu.p.x) { cpu.p.n = cpu.r.y >> 7; } else { cpu.p.n = cpu.r.y >> 15; } } }; var TYX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.r.x = cpu.r.y; if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } if(cpu.p.e|cpu.p.x) { cpu.p.n = cpu.r.y >> 7; } else { cpu.p.n = cpu.r.y >> 15; } } }; var TCD = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; // Transfers 16-bits regardless of setting. if(cpu.p.e|cpu.p.m) { cpu.r.d = (cpu.r.b<<8)|cpu.r.a; } else { cpu.r.d = cpu.r.a; } cpu.p.n = cpu.r.d >> 15; if(cpu.r.d===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TDC = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; // Transfers 16-bits regardless of setting. if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.r.d & 0xff; cpu.r.b = cpu.r.d >> 8; cpu.p.n = cpu.r.b >> 7; } else { cpu.r.a = cpu.r.d; cpu.p.n = cpu.r.a >> 7; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var TCS = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e|!cpu.p.m) { cpu.r.s = cpu.r.a; } else { cpu.r.s = (cpu.r.b<<8)|cpu.r.a; } } }; var TSC = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.p.e) { cpu.r.b = 1; cpu.r.a = cpu.r.s; // TODO: Figure out if in emulation mode the z and n bits should always // be set to zero here as a 1 is transferred to b. cpu.p.n = 0; cpu.p.z = 0; } else { if(cpu.p.m) { cpu.r.a = cpu.r.s & 0xff; cpu.r.b = cpu.r.s >> 8; cpu.p.n = cpu.r.b >> 7; } else { cpu.r.a = cpu.r.s; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.s===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var STZ_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, 0); } else { cpu.cycle_count++; cpu.mmu.store_byte(location, 0); cpu.mmu.store_byte(location+1, 0); } } }; var STZ_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, 0); } else { cpu.cycle_count++; cpu.mmu.store_byte(location, 0); cpu.mmu.store_byte(location+1, 0); } } }; var STZ_absolute_indexed_x = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, 0); } else { cpu.cycle_count++; cpu.mmu.store_byte(location, 0); cpu.mmu.store_byte(location+1, 0); } } }; var STZ_direct_page_indexed_x = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.r.d+cpu.r.x; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, 0); } else { cpu.cycle_count++; // Check for overflow. var overflow_check = location - 0xffff; if(overflow_check > 0) { location = overflow_check-1; } cpu.mmu.store_byte(location, 0); // Check for potential overflow again. if(location===0xffff) { location = 0; } else { location++; } cpu.mmu.store_byte(location, 0); } } }; var STA_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); cpu.mmu.store_byte((high_byte_loc<<8) | low_byte_loc, cpu.r.a); } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.r.a & 0x00ff; var high_byte = cpu.r.a >> 8; cpu.mmu.store_byte(absolute_location, low_byte); cpu.mmu.store_byte(absolute_location+1, high_byte); } } }; var STA_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); cpu.mmu.store_byte_long((high_byte_loc<<8) | low_byte_loc, bank_byte, cpu.r.a); } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.r.a & 0x00ff; var high_byte = cpu.r.a >> 8; cpu.mmu.store_byte(absolute_location, bank_byte, low_byte); cpu.mmu.store_byte((absolute_location+1)&0xffff, bank_byte, high_byte); } } }; var STA_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc << 8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } cpu.mmu.store_byte_long(absolute_location, bank_byte, cpu.r.a); } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } var low_byte = cpu.r.a & 0x00ff; var high_byte = cpu.r.a >> 8; cpu.mmu.store_byte(absolute_location, bank_byte, low_byte); absolute_location++; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } cpu.mmu.store_byte(absolute_location, bank_byte, high_byte); } } }; var STA_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); cpu.mmu.store_byte((high_byte_loc<<8) | low_byte_loc, cpu.r.a); } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; var low_byte = cpu.r.a & 0x00ff; var high_byte = cpu.r.a >> 8; cpu.mmu.store_byte(absolute_location, low_byte); cpu.mmu.store_byte(absolute_location+1, high_byte); } } }; var STA_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); cpu.mmu.store_byte(location, cpu.r.a); } else { if(cpu.p.m) { cpu.mmu.store_byte(cpu.r.s + bytes[0], cpu.r.a); } else { cpu.cycle_count++; var low_byte = cpu.r.a & 0xff; var high_byte = cpu.r.a >> 8; var location = cpu.r.s + bytes[0]; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } } }; var STA_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=7; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } cpu.mmu.store_byte(b, cpu.r.a); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } cpu.mmu.store_byte(b, cpu.r.a); } else { cpu.cycle_count++; var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } var sta_location = (high_byte<<8)|low_byte; cpu.mmu.store_byte(sta_location, cpu.r.a & 0xff); cpu.mmu.store_byte(sta_location+1, cpu.r.a >> 8); } } } }; var LDA_direct_page_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); cpu.r.a = cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); cpu.r.a = cpu.mmu.read_byte((high_byte_loc<<8) | low_byte_loc); cpu.p.n = cpu.r.a >> 7; } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); cpu.r.a = cpu.mmu.read_byte((high_byte_loc<<8)|low_byte_loc); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page_indirect_long = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); cpu.r.a = cpu.mmu.read_byte_long((high_byte_loc<<8) | low_byte_loc, bank_byte); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); var high_byte = cpu.mmu.read_byte_long((absolute_location+1)&0xffff, bank_byte); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page_indirect_long_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc << 8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } cpu.r.a = cpu.mmu.read_byte_long(absolute_location, bank_byte); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location&0xffff); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var bank_byte = cpu.mmu.read_byte((location+2)&0xffff); var absolute_location = ((high_byte_loc<<8) | low_byte_loc) + cpu.r.y; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } var low_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); absolute_location++; if(absolute_location >> 16) { bank_byte++; absolute_location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(absolute_location, bank_byte); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8)|low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; cpu.r.a = cpu.mmu.read_byte(absolute_location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte(location+1); var original_location = (high_byte_loc<<8) | low_byte_loc; var absolute_location = original_location + cpu.r.y; if((original_location&0xff00)!=(absolute_location&0xff00)) cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte = cpu.mmu.read_byte(absolute_location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); cpu.r.a = low_byte | (high_byte<<8); cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_absolute_indexed_y = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_stack_relative = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if(cpu.p.e) { var location = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); LDA_const.execute(cpu, [cpu.mmu.read_byte(location)]); } else { if(cpu.p.m) { LDA_const.execute(cpu, [cpu.mmu.read_byte(cpu.r.s+bytes[0])]); } else { cpu.cycle_count++; var location = cpu.r.s + bytes[0]; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); LDA_const.execute(cpu, [low_byte, high_byte]); } } } }; var LDA_stack_relative_indirect_indexed_y = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=7; if(cpu.p.e) { var location_loc = 0x100 | ((cpu.r.s + bytes[0]) & 0xff); var low_byte = cpu.mmu.read_byte(location_loc); var high_byte; if(location_loc===0x1ff) { high_byte = cpu.mmu.read_byte(0x100); } else { high_byte = cpu.mmu.read_byte(location_loc+1); } var absolute_location = ((high_byte<<8)|low_byte)+cpu.r.y; var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } LDA_const.execute(cpu, [b]); } else { var location_loc = (cpu.r.s + bytes[0]) & 0xffff; var location_low_byte = cpu.mmu.read_byte(location); var location_high_byte = cpu.mmu.read_byte(location+1); var absolute_location = (location_high_byte<<8)|location_low_byte; absolute_location += cpu.r.y; if(cpu.p.m) { var b; if(absolute_location>=0x10000) { b = cpu.mmu.read_byte_long(absolute_location & 0xffff, cpu.r.dbr+1); } else { b = cpu.mmu.read_byte(absolute_location); } LDA_const.execute(cpu, [b]); } else { cpu.cycle_count++; var low_byte; var high_byte; if(absolute_location>=0x10000) { absolute_location &= 0xffff; low_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { low_byte = cpu.mmu.read_byte(absolute_location); if(absolute_location===0xffff) { high_byte = cpu.mmu.read_byte_long(0, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } } LDA_const.execute(cpu, [low_byte, high_byte]); } } } }; var NOP = { bytes_required:function() { return 1; }, execute:function() { cpu.cycle_count+=2; } }; var LDY_const = { bytes_required:function(cpu) { if(cpu.p.e|cpu.p.x) return 2; else return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.x) { cpu.r.y = bytes[0]; cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; cpu.r.y = (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDY_absolute_indexed_x = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location + cpu.r.x; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.x) { cpu.r.y = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.y = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDY_direct_page_indexed_x = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; if(cpu.p.e|cpu.p.x) { cpu.r.y = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); cpu.r.y = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } var LDY_absolute = { bytes_required:function() { return 3; }, execute:function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { cpu.r.y = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.y = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDY_direct_page = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.x) { cpu.r.y = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.y >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.y = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var DEX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.r.x===0) { if(cpu.p.e|cpu.p.x) { cpu.r.x = 0xff; } else { cpu.r.x = 0xffff; } cpu.p.n = 1; cpu.p.z = 0; } else { cpu.r.x--; if(cpu.p.e|cpu.p.x) { cpu.p.n = cpu.r.x >> 7; } else { cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var DEY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; if(cpu.r.y===0) { if(cpu.p.e|cpu.p.x) { cpu.r.y = 0xff; } else { cpu.r.y = 0xffff; } cpu.p.n = 1; cpu.p.z = 0; } else { cpu.r.y--; if(cpu.p.e|cpu.p.x) { cpu.p.n = cpu.r.y >> 7; } else { cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var DEC_accumulator = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; if(cpu.r.a===0) { if(cpu.p.e|cpu.p.m) { cpu.r.a = 0xff; } else { cpu.r.a = 0xffff; } cpu.p.n = 1; cpu.p.z = 0; } else { cpu.r.a--; if(cpu.p.e|cpu.p.m) { cpu.r.a &= 0xff; cpu.p.n = cpu.r.a >> 7; } else { cpu.r.a &= 0xffff; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var DEC_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0]; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location); if(temp===0) { cpu.mmu.store_byte(location, 0xff); cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.mmu.store_byte(location, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); temp = (high_byte<<8) | low_byte; if(temp===0) { temp = 0xffff; cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.p.n = temp >> 15; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var DEC_absolute_indexed_x = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=7; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location&0xffff); if(temp===0) { cpu.mmu.store_byte(location&0xffff, 0xff); cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.mmu.store_byte(location&0xffff, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); temp = (high_byte<<8) | low_byte; if(temp===0) { temp = 0xffff; cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.p.n = temp >> 15; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var DEC_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location); if(temp===0) { cpu.mmu.store_byte(location, 0xff); cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.mmu.store_byte(location, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); temp = (high_byte<<8) | low_byte; if(temp===0) { temp = 0xffff; cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.p.n = temp >> 15; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var DEC_direct_page_indexed_x = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location&0xffff); if(temp===0) { cpu.mmu.store_byte(location&0xffff, 0xff); cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.mmu.store_byte(location&0xffff, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); temp = (high_byte<<8) | low_byte; if(temp===0) { temp = 0xffff; cpu.p.n = 1; cpu.p.z = 0; } else { temp--; cpu.p.n = temp >> 15; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var INX = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.r.x++; if(cpu.p.e|cpu.p.x) { cpu.r.x &= 0xff; cpu.p.n = cpu.r.x >> 7; } else { cpu.r.x &= 0xffff; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var INY = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.r.y++; if(cpu.p.e|cpu.p.x) { cpu.r.y &= 0xff; cpu.p.n = cpu.r.y >> 7; } else { cpu.r.y &= 0xffff; cpu.p.n = cpu.r.y >> 15; } if(cpu.r.y===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var INC_accumulator = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; cpu.r.a++; if(cpu.p.e|cpu.p.m) { cpu.r.a &= 0xff; cpu.p.n = cpu.r.a >> 7; } else { cpu.r.a &= 0xffff; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var INC_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=6; var location = (bytes[1]<<8)|bytes[0] var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location) + 1; temp &= 0xff; cpu.p.n = temp >> 7; cpu.mmu.store_byte(location, temp); if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); temp = (high_byte<<8) | low_byte; temp++; cpu.p.n = temp >> 15; high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); if(((high_byte<<8)|low_byte)===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var INC_absolute_indexed_x = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=7; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location&0xffff) + 1; temp &= 0xff; cpu.p.n = temp >> 7; cpu.mmu.store_byte(location&0xffff, temp); if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); temp = (high_byte<<8) | low_byte; temp++; cpu.p.n = temp >> 15; high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); if(((high_byte<<8)|low_byte)===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var INC_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location) + 1; temp &= 0xff; cpu.mmu.store_byte(location, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); temp = (high_byte<<8) | low_byte; temp++; cpu.p.n = temp >> 15; high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); if(((high_byte<<8)|low_byte)===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var INC_direct_page_indexed_x = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; var temp; if(cpu.p.e|cpu.p.m) { temp = cpu.mmu.read_byte(location&0xffff) + 1; temp &= 0xff; cpu.mmu.store_byte(location&0xffff, temp); cpu.p.n = temp >> 7; if(temp===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } else { cpu.cycle_count+=2; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); temp = (high_byte<<8) | low_byte; temp++; cpu.p.n = temp >> 15; high_byte = temp >> 8; low_byte = temp & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); if(((high_byte<<8)|low_byte)===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } }; var STA_direct_page_indexed_x = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d+cpu.r.x; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var STA_direct_page_indexed_x_indirect = { bytes_required:function() { return 2; }, execute:function(cpu, bytes) { cpu.cycle_count+=6; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; if(cpu.p.e) { var location = (bytes[0] + cpu.r.x) & 0xff; var low_byte_loc = cpu.mmu.read_byte_long((location+cpu.r.d)&0xffff, 0); var high_byte_read_loc = (((location+1)&0xff)+cpu.r.d)&0xffff; var high_byte_loc = cpu.mmu.read_byte_long(high_byte_read_loc, 0); cpu.mmu.store_byte((high_byte_loc<<8) | low_byte_loc, cpu.r.a); } else if(cpu.p.m) { var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); cpu.mmu.store_byte((high_byte_loc<<8)|low_byte_loc, cpu.r.a); } else { cpu.cycle_count++; var location = bytes[0] + cpu.r.d + cpu.r.x; var low_byte_loc = cpu.mmu.read_byte(location); var high_byte_loc = cpu.mmu.read_byte((location+1)&0xffff); var absolute_location = (high_byte_loc<<8) | low_byte_loc; var low_byte = cpu.mmu.read_byte(absolute_location); var high_byte; absolute_location++; if(absolute_location&0x10000) { absolute_location &= 0xffff; high_byte = cpu.mmu.read_byte_long(absolute_location, cpu.r.dbr+1); } else { high_byte = cpu.mmu.read_byte(absolute_location); } var storage_location = (high_byte<<8) | low_byte; cpu.mmu.store_byte(storage_location, cpu.r.a & 0xff); storage_location++; if(storage_location&0x10000) { storage_location &= 0xffff; cpu.mmu.store_byte_long(storage_location, cpu.r.dbr+1, cpu.r.a >> 8); } else { cpu.mmu.store_byte(storage_location, cpu.r.a >> 8); } } } }; var STA_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STA_absolute_indexed_x = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.x; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STA_absolute_indexed_y = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0])+cpu.r.y; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STY_direct_page_indexed_x = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d+cpu.r.x; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.y); } else { cpu.cycle_count++; var high_byte = cpu.r.y >> 8; var low_byte = cpu.r.y & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var STY_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.y); } else { cpu.cycle_count++; var high_byte = cpu.r.y >> 8; var low_byte = cpu.r.y & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STY_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.y); } else { cpu.cycle_count++; var high_byte = cpu.r.y >> 8; var low_byte = cpu.r.y & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STX_direct_page_indexed_y = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d+cpu.r.y; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.x); } else { cpu.cycle_count++; var high_byte = cpu.r.x >> 8; var low_byte = cpu.r.x & 0x00ff; cpu.mmu.store_byte(location&0xffff, low_byte); cpu.mmu.store_byte((location+1)&0xffff, high_byte); } } }; var STX_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0]+cpu.p.d; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.x); } else { cpu.cycle_count++; var high_byte = cpu.r.x >> 8; var low_byte = cpu.r.x & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STX_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { cpu.mmu.store_byte(location, cpu.r.x); } else { cpu.cycle_count++; var high_byte = cpu.r.x >> 8; var low_byte = cpu.r.x & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var STA_absolute_long = { bytes_required: function() { return 4; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte_long(location, bytes[2], cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte_long(location, bytes[2], low_byte); cpu.mmu.store_byte_long(location+1, bytes[2], high_byte); } } }; var STA_absolute_long_indexed_x = { bytes_required: function() { return 4; }, execute: function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { location &= 0xffff; bytes[2]++; } if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte_long(location, bytes[2], cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte_long(location, bytes[2], low_byte); location++; if(location & 0x10000) { location &= 0xffff; bytes[2]++; } cpu.mmu.store_byte_long(location, bytes[2], high_byte); } } }; var STA_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { cpu.mmu.store_byte(location, cpu.r.a); } else { cpu.cycle_count++; var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.mmu.store_byte(location, low_byte); cpu.mmu.store_byte(location+1, high_byte); } } }; var LDX_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = cpu.r.d + bytes[0]; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.x = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDX_direct_page_indexed_y = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = cpu.r.d + bytes[0] + cpu.r.y; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location&0xffff); var high_byte = cpu.mmu.read_byte((location+1)&0xffff); cpu.r.x = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_direct_page = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { cpu.cycle_count+=3; if((cpu.r.d&0xff)!=0) cpu.cycle_count++; var location = bytes[0] + cpu.r.d; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDX_absolute_indexed_y = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var original_location = (bytes[1]<<8)|bytes[0]; var location = original_location+cpu.r.y; if((original_location&0xff00)!=(location&0xff00)) cpu.cycle_count++; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.x = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDX_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.x) { cpu.r.x = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.x = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_absolute_long = { bytes_required: function() { return 4; }, execute: function(cpu, bytes) { cpu.cyclce_count+=5; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte_long(location, bytes[2]); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); var high_byte = cpu.mmu.read_byte_long(location+1, bytes[2]); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_absolute_long_indexed_x = { bytes_required:function() { return 4; }, execute:function(cpu, bytes) { cpu.cycle_count+=5; var location = ((bytes[1]<<8)|bytes[0]) + cpu.r.x; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte_long(location, bytes[2]); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte_long(location, bytes[2]); location++; if(location & 0x10000) { bytes[2]++; location &= 0xffff; } var high_byte = cpu.mmu.read_byte_long(location, bytes[2]); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_absolute = { bytes_required: function() { return 3; }, execute: function(cpu, bytes) { cpu.cycle_count+=4; var location = (bytes[1]<<8)|bytes[0]; if(cpu.p.e|cpu.p.m) { cpu.r.a = cpu.mmu.read_byte(location); cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; var low_byte = cpu.mmu.read_byte(location); var high_byte = cpu.mmu.read_byte(location+1); cpu.r.a = (high_byte<<8) | low_byte; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDA_const = { bytes_required: function(cpu) { if(cpu.p.e|cpu.p.m) { return 2; } else { return 3; } }, execute: function(cpu, bytes) { cpu.cycle_count+=2; if(cpu.p.e|cpu.p.m) { cpu.r.a = bytes[0]; cpu.p.n = cpu.r.a >> 7; } else { cpu.cycle_count++; cpu.r.a = (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.a >> 15; } if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; var LDX_const = { bytes_required: function(cpu) { if(cpu.p.e|cpu.p.x) { return 2; } else { return 3; } }, execute: function(cpu, bytes) { cpu.cycle_count+=2; var constant; if(cpu.p.e|cpu.p.x) { cpu.r.x = bytes[0]; cpu.p.n = cpu.r.x >> 7; } else { cpu.cycle_count++; cpu.r.x = (bytes[1]<<8)|bytes[0]; cpu.p.n = cpu.r.x >> 15; } if(cpu.r.x===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } }; // Set bits in the p status register as specified by 1's in the position // that represents each register. var SEP = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { // TODO: Figure out exactly how behavior differs in emulation mode. cpu.cycle_count+=3; var flags = bytes[0].toString(2); // Sometimes it cuts off zeros before hand, so add those zeros back. while(flags.length<8) { flags = '0' + flags; } var ops = { 0: function() { cpu.p.n = 1; }, 1: function() { cpu.p.v = 1; }, 2: function() { cpu.p.m = 1; }, 3: function() { cpu.p.x = 1; }, 4: function() { cpu.p.d = 1; }, 5: function() { cpu.p.i = 1; }, 6: function() { cpu.p.z = 1; }, 7: function() { cpu.p.c = 1; }}; for(var i = 0; i < 8; i++) { if(flags[i]==='1') { ops[i](); } } } }; // Clear bits in the p status register as specified by 1's in the position // that represents each register. var REP = { bytes_required: function() { return 2; }, execute: function(cpu, bytes) { // TODO: Figure out exactly how behavior differs in emulation mode. cpu.cycle_count+=3; var flags = bytes[0].toString(2); // Sometimes it cuts off zeros before hand, so add those zeros back. while(flags.length<8) { flags = '0' + flags; } var ops = { 0: function() { cpu.p.n = 0; }, 1: function() { cpu.p.v = 0; }, 2: function() { cpu.p.m = 0; }, 3: function() { cpu.p.x = 0; }, 4: function() { cpu.p.d = 0; }, 5: function() { cpu.p.i = 0; }, 6: function() { cpu.p.z = 0; }, 7: function() { cpu.p.c = 0; }}; for(var i = 0; i < 8; i++) { if(flags[i]==='1') { ops[i](); } } } }; var XCE = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; var temp = cpu.p.c; cpu.p.c = cpu.p.e; cpu.p.e = temp; if(cpu.p.e) { // Switching to emulation mode. var high_byte = cpu.r.a >> 8; var low_byte = cpu.r.a & 0x00ff; cpu.r.a = low_byte; cpu.r.b = high_byte; cpu.r.s &= 0xff; } else { // Switching to native mode. cpu.r.a = (cpu.r.b<<8) | cpu.r.a; cpu.p.m = 1; cpu.p.x = 1; cpu.r.s |= 0x100; } } }; var CLC = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; cpu.p.c = 0; } }; var SEI = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; cpu.p.i = 1; } }; var CLI = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; cpu.p.i = 0; } }; var SEC = { bytes_required: function() { return 1; }, execute: function(cpu) { cpu.cycle_count+=2; cpu.p.c = 1; } }; var CLD = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.p.d = 0; } }; var SED = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.p.d = 1; } }; var CLV = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=2; cpu.p.v = 0; } }; var XBA = { bytes_required:function() { return 1; }, execute:function(cpu) { cpu.cycle_count+=3; if(cpu.p.e|cpu.p.m) { cpu.cycle_count+=2; var old_a = cpu.r.a; cpu.r.a = cpu.r.b; cpu.r.b = old_a; cpu.p.n = cpu.r.a >> 7; if(cpu.r.a===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } else { var low_byte = cpu.r.a & 0xff; var high_byte = cpu.r.a >> 8; cpu.r.a = (low_byte<<8)|high_byte; cpu.p.n = high_byte >> 7; if(high_byte===0) { cpu.p.z = 1; } else { cpu.p.z = 0; } } } };