// ---------------------------------------------------------------------------- // ___ ___ ___ ___ ___ ____ ___ _ _ // /__/ /__/ / / /__ /__/ /__ / /_ / |/ / // / / \ /__/ ___/ ___/ ___/ / /__ / / emulator // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ---------------------------------------------------------------------------- // Sally.cpp // ---------------------------------------------------------------------------- #include "Sally.h" byte sally_a = 0; byte sally_x = 0; byte sally_y = 0; byte sally_p = 0; byte sally_s = 0; pair sally_pc = {0}; static byte sally_opcode; static pair sally_address; static uint sally_cycles; struct Flag { byte C; byte Z; byte I; byte D; byte B; byte R; byte V; byte N; }; static const Flag SALLY_FLAG = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; struct Vector { word H; word L; }; static const Vector SALLY_RES = {65533, 65532}; static const Vector SALLY_NMI = {65531, 65530}; static const Vector SALLY_IRQ = {65535, 65534}; static const byte SALLY_CYCLES[256] = { 7,6,0,0,0,3,5,0,3,2,2,0,0,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 6,6,0,0,3,3,5,0,4,2,2,0,4,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 6,6,0,0,0,3,5,0,3,2,2,0,3,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 6,6,0,0,0,3,5,0,4,2,2,0,5,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 0,6,0,0,3,3,3,0,2,0,2,0,4,4,4,0, 2,6,0,0,4,4,4,0,2,5,2,0,0,5,0,0, 2,6,2,0,3,3,3,0,2,2,2,0,4,4,4,0, 2,5,0,0,4,4,4,0,2,4,2,0,4,4,4,0, 2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, 2,6,0,0,3,3,5,0,2,2,2,0,4,4,6,0, 2,5,0,0,0,4,6,0,2,4,0,0,0,4,7,0, }; // ---------------------------------------------------------------------------- // Push // ---------------------------------------------------------------------------- static void sally_Push(byte data) { memory_Write(sally_s + 256, data); sally_s--; } // ---------------------------------------------------------------------------- // Pop // ---------------------------------------------------------------------------- static byte sally_Pop( ) { sally_s++; return memory_Read(sally_s + 256); } // ---------------------------------------------------------------------------- // Flags // ---------------------------------------------------------------------------- static void sally_Flags(byte data) { if(!data) { sally_p |= SALLY_FLAG.Z; } else { sally_p &= ~SALLY_FLAG.Z; } if(data & 128) { sally_p |= SALLY_FLAG.N; } else { sally_p &= ~SALLY_FLAG.N; } } // ---------------------------------------------------------------------------- // Branch // ---------------------------------------------------------------------------- static void sally_Branch(byte branch) { if(branch) { pair temp = sally_pc; sally_pc.w += (char)sally_address.b.l; if(temp.b.h != sally_pc.b.h) { sally_cycles += 2; } else { sally_cycles++; } } } // ---------------------------------------------------------------------------- // Delay // ---------------------------------------------------------------------------- static void sally_Delay(byte delta) { pair address1 = sally_address; pair address2 = sally_address; address1.w -= delta; if(address1.b.h != address2.b.h) { sally_cycles++; } } // ---------------------------------------------------------------------------- // Absolute // ---------------------------------------------------------------------------- static void sally_Absolute( ) { sally_address.b.l = memory_Read(sally_pc.w++); sally_address.b.h = memory_Read(sally_pc.w++); } // ---------------------------------------------------------------------------- // AbsoluteX // ---------------------------------------------------------------------------- static void sally_AbsoluteX( ) { sally_address.b.l = memory_Read(sally_pc.w++); sally_address.b.h = memory_Read(sally_pc.w++); sally_address.w += sally_x; } // ---------------------------------------------------------------------------- // AbsoluteY // ---------------------------------------------------------------------------- static void sally_AbsoluteY( ) { sally_address.b.l = memory_Read(sally_pc.w++); sally_address.b.h = memory_Read(sally_pc.w++); sally_address.w += sally_y; } // ---------------------------------------------------------------------------- // Immediate // ---------------------------------------------------------------------------- static void sally_Immediate( ) { sally_address.w = sally_pc.w++; } // ---------------------------------------------------------------------------- // Indirect // ---------------------------------------------------------------------------- static void sally_Indirect( ) { pair base; base.b.l = memory_Read(sally_pc.w++); base.b.h = memory_Read(sally_pc.w++); sally_address.b.l = memory_Read(base.w); sally_address.b.h = memory_Read(base.w + 1); } // ---------------------------------------------------------------------------- // IndirectX // ---------------------------------------------------------------------------- static void sally_IndirectX( ) { sally_address.b.l = memory_Read(sally_pc.w++) + sally_x; sally_address.b.h = memory_Read(sally_address.b.l + 1); sally_address.b.l = memory_Read(sally_address.b.l); } // ---------------------------------------------------------------------------- // IndirectY // ---------------------------------------------------------------------------- static void sally_IndirectY( ) { sally_address.b.l = memory_Read(sally_pc.w++); sally_address.b.h = memory_Read(sally_address.b.l + 1); sally_address.b.l = memory_Read(sally_address.b.l); sally_address.w += sally_y; } // ---------------------------------------------------------------------------- // Relative // ---------------------------------------------------------------------------- static void sally_Relative( ) { sally_address.w = memory_Read(sally_pc.w++); } // ---------------------------------------------------------------------------- // Zero Page // ---------------------------------------------------------------------------- static void sally_ZeroPage( ) { sally_address.w = memory_Read(sally_pc.w++); } // ---------------------------------------------------------------------------- // ZeroPageX // ---------------------------------------------------------------------------- static void sally_ZeroPageX( ) { sally_address.w = memory_Read(sally_pc.w++); sally_address.b.l += sally_x; } // ---------------------------------------------------------------------------- // ZeroPageY // ---------------------------------------------------------------------------- static void sally_ZeroPageY( ) { sally_address.w = memory_Read(sally_pc.w++); sally_address.b.l += sally_y; } // ---------------------------------------------------------------------------- // ADC // ---------------------------------------------------------------------------- static void sally_ADC( ) { byte data = memory_Read(sally_address.w); if(sally_p & SALLY_FLAG.D) { word al = (sally_a & 15) + (data & 15) + (sally_p & SALLY_FLAG.C); word ah = (sally_a >> 4) + (data >> 4); if(al > 9) { al += 6; ah++; } if(!(sally_a + data + (sally_p & SALLY_FLAG.C))) { sally_p |= SALLY_FLAG.Z; } else { sally_p &= ~SALLY_FLAG.Z; } if((ah & 8) != 0) { sally_p |= SALLY_FLAG.N; } else { sally_p &= ~SALLY_FLAG.N; } if(~(sally_a ^ data) & ((ah << 4) ^ sally_a) & 128) { sally_p |= SALLY_FLAG.V; } else { sally_p &= ~SALLY_FLAG.V; } if(ah > 9) { ah += 6; } if(ah > 15) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_a = (ah << 4) | (al & 15); } else { pair temp; temp.w = sally_a + data + (sally_p & SALLY_FLAG.C); if(temp.b.h) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } if(~(sally_a ^ data) & (sally_a ^ temp.b.l) & 128) { sally_p |= SALLY_FLAG.V; } else { sally_p &= ~SALLY_FLAG.V; } sally_Flags(temp.b.l); sally_a = temp.b.l; } } // ---------------------------------------------------------------------------- // AND // ---------------------------------------------------------------------------- static void sally_AND( ) { sally_a &= memory_Read(sally_address.w); sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // ASLA // ---------------------------------------------------------------------------- static void sally_ASLA( ) { if(sally_a & 128) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_a <<= 1; sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // ASL // ---------------------------------------------------------------------------- static void sally_ASL( ) { byte data = memory_Read(sally_address.w); if(data & 128) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } data <<= 1; memory_Write(sally_address.w, data); sally_Flags(data); } // ---------------------------------------------------------------------------- // BCC // ---------------------------------------------------------------------------- static void sally_BCC( ) { sally_Branch(!(sally_p & SALLY_FLAG.C)); } // ---------------------------------------------------------------------------- // BCS // ---------------------------------------------------------------------------- static void sally_BCS( ) { sally_Branch(sally_p & SALLY_FLAG.C); } // ---------------------------------------------------------------------------- // BEQ // ---------------------------------------------------------------------------- static void sally_BEQ( ) { sally_Branch(sally_p & SALLY_FLAG.Z); } // ---------------------------------------------------------------------------- // BIT // ---------------------------------------------------------------------------- static void sally_BIT( ) { byte data = memory_Read(sally_address.w); if(!(data & sally_a)) { sally_p |= SALLY_FLAG.Z; } else { sally_p &= ~SALLY_FLAG.Z; } sally_p &= ~SALLY_FLAG.V; sally_p &= ~SALLY_FLAG.N; sally_p |= data & 64; sally_p |= data & 128; } // ---------------------------------------------------------------------------- // BMI // ---------------------------------------------------------------------------- static void sally_BMI( ) { sally_Branch(sally_p & SALLY_FLAG.N); } // ---------------------------------------------------------------------------- // BNE // ---------------------------------------------------------------------------- static void sally_BNE( ) { sally_Branch(!(sally_p & SALLY_FLAG.Z)); } // ---------------------------------------------------------------------------- // BPL // ---------------------------------------------------------------------------- static void sally_BPL( ) { sally_Branch(!(sally_p & SALLY_FLAG.N)); } // ---------------------------------------------------------------------------- // BRK // ---------------------------------------------------------------------------- static void sally_BRK( ) { sally_pc.w++; sally_p |= SALLY_FLAG.B; sally_Push(sally_pc.b.h); sally_Push(sally_pc.b.l); sally_Push(sally_p); sally_p |= SALLY_FLAG.I; sally_pc.b.l = memory_ram[SALLY_IRQ.L]; sally_pc.b.h = memory_ram[SALLY_IRQ.H]; } // ---------------------------------------------------------------------------- // BVC // ---------------------------------------------------------------------------- static void sally_BVC( ) { sally_Branch(!(sally_p & SALLY_FLAG.V)); } // ---------------------------------------------------------------------------- // BVS // ---------------------------------------------------------------------------- static void sally_BVS( ) { sally_Branch(sally_p & SALLY_FLAG.V); } // ---------------------------------------------------------------------------- // CLC // ---------------------------------------------------------------------------- static void sally_CLC( ) { sally_p &= ~SALLY_FLAG.C; } // ---------------------------------------------------------------------------- // CLD // ---------------------------------------------------------------------------- static void sally_CLD( ) { sally_p &= ~SALLY_FLAG.D; } // ---------------------------------------------------------------------------- // CLI // ---------------------------------------------------------------------------- static void sally_CLI( ) { sally_p &= ~SALLY_FLAG.I; } // ---------------------------------------------------------------------------- // CLV // ---------------------------------------------------------------------------- static void sally_CLV( ) { sally_p &= ~SALLY_FLAG.V; } // ---------------------------------------------------------------------------- // CMP // ---------------------------------------------------------------------------- static void sally_CMP( ) { byte data = memory_Read(sally_address.w); if(sally_a >= data) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_Flags(sally_a - data); } // ---------------------------------------------------------------------------- // CPX // ---------------------------------------------------------------------------- static void sally_CPX( ) { byte data = memory_Read(sally_address.w); if(sally_x >= data) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_Flags(sally_x - data); } // ---------------------------------------------------------------------------- // CPY // ---------------------------------------------------------------------------- static void sally_CPY( ) { byte data = memory_Read(sally_address.w); if(sally_y >= data) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_Flags(sally_y - data); } // ---------------------------------------------------------------------------- // DEC // ---------------------------------------------------------------------------- static void sally_DEC( ) { byte data = memory_Read(sally_address.w); memory_Write(sally_address.w, --data); sally_Flags(data); } // ---------------------------------------------------------------------------- // DEX // ---------------------------------------------------------------------------- static void sally_DEX( ) { sally_Flags(--sally_x); } // ---------------------------------------------------------------------------- // DEY // ---------------------------------------------------------------------------- static void sally_DEY( ) { sally_Flags(--sally_y); } // ---------------------------------------------------------------------------- // EOR // ---------------------------------------------------------------------------- static void sally_EOR( ) { sally_a ^= memory_Read(sally_address.w); sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // INC // ---------------------------------------------------------------------------- static void sally_INC( ) { byte data = memory_Read(sally_address.w); memory_Write(sally_address.w, ++data); sally_Flags(data); } // ---------------------------------------------------------------------------- // INX // ---------------------------------------------------------------------------- static void sally_INX( ) { sally_Flags(++sally_x); } // ---------------------------------------------------------------------------- // INY // ---------------------------------------------------------------------------- static void sally_INY( ) { sally_Flags(++sally_y); } // ---------------------------------------------------------------------------- // JMP // ---------------------------------------------------------------------------- static void sally_JMP( ) { sally_pc = sally_address; } // ---------------------------------------------------------------------------- // JSR // ---------------------------------------------------------------------------- static void sally_JSR( ) { sally_pc.w--; sally_Push(sally_pc.b.h); sally_Push(sally_pc.b.l); sally_pc = sally_address; } // ---------------------------------------------------------------------------- // LDA // ---------------------------------------------------------------------------- static void sally_LDA( ) { sally_a = memory_Read(sally_address.w); sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // LDX // ---------------------------------------------------------------------------- static void sally_LDX( ) { sally_x = memory_Read(sally_address.w); sally_Flags(sally_x); } // ---------------------------------------------------------------------------- // LDY // ---------------------------------------------------------------------------- static void sally_LDY( ) { sally_y = memory_Read(sally_address.w); sally_Flags(sally_y); } // ---------------------------------------------------------------------------- // LSRA // ---------------------------------------------------------------------------- static void sally_LSRA( ) { sally_p &= ~SALLY_FLAG.C; sally_p |= sally_a & 1; sally_a >>= 1; sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // LSR // ---------------------------------------------------------------------------- static void sally_LSR( ) { byte data = memory_Read(sally_address.w); sally_p &= ~SALLY_FLAG.C; sally_p |= data & 1; data >>= 1; memory_Write(sally_address.w, data); sally_Flags(data); } // ---------------------------------------------------------------------------- // NOP // ---------------------------------------------------------------------------- static void sally_NOP( ) { } // ---------------------------------------------------------------------------- // ORA // ---------------------------------------------------------------------------- static void sally_ORA( ) { sally_a |= memory_Read(sally_address.w); sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // PHA // ---------------------------------------------------------------------------- static void sally_PHA( ) { sally_Push(sally_a); } // ---------------------------------------------------------------------------- // PHP // ---------------------------------------------------------------------------- static void sally_PHP( ) { sally_Push(sally_p); } // ---------------------------------------------------------------------------- // PLA // ---------------------------------------------------------------------------- static void sally_PLA( ) { sally_a = sally_Pop( ); sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // PLP // ---------------------------------------------------------------------------- static void sally_PLP( ) { sally_p = sally_Pop( ); } // ---------------------------------------------------------------------------- // ROLA // ---------------------------------------------------------------------------- static void sally_ROLA( ) { byte temp = sally_p; if(sally_a & 128) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } sally_a <<= 1; sally_a |= temp & SALLY_FLAG.C; sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // ROL // ---------------------------------------------------------------------------- static void sally_ROL( ) { byte data = memory_Read(sally_address.w); byte temp = sally_p; if(data & 128) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } data <<= 1; data |= temp & 1; memory_Write(sally_address.w, data); sally_Flags(data); } // ---------------------------------------------------------------------------- // RORA // ---------------------------------------------------------------------------- static void sally_RORA( ) { byte temp = sally_p; sally_p &= ~SALLY_FLAG.C; sally_p |= sally_a & 1; sally_a >>= 1; if(temp & SALLY_FLAG.C) { sally_a |= 128; } sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // ROR // ---------------------------------------------------------------------------- static void sally_ROR( ) { byte data = memory_Read(sally_address.w); byte temp = sally_p; sally_p &= ~SALLY_FLAG.C; sally_p |= data & 1; data >>= 1; if(temp & 1) { data |= 128; } memory_Write(sally_address.w, data); sally_Flags(data); } // ---------------------------------------------------------------------------- // RTI // ---------------------------------------------------------------------------- static void sally_RTI( ) { sally_p = sally_Pop( ); sally_pc.b.l = sally_Pop( ); sally_pc.b.h = sally_Pop( ); } // ---------------------------------------------------------------------------- // RTS // ---------------------------------------------------------------------------- static void sally_RTS( ) { sally_pc.b.l = sally_Pop( ); sally_pc.b.h = sally_Pop( ); sally_pc.w++; } // ---------------------------------------------------------------------------- // SBC // ---------------------------------------------------------------------------- static void sally_SBC( ) { byte data = memory_Read(sally_address.w); if(sally_p & SALLY_FLAG.D) { word al = (sally_a & 15) - (data & 15) - !(sally_p & SALLY_FLAG.C); word ah = (sally_a >> 4) - (data >> 4); if(al > 9) { al -= 6; ah--; } if(ah > 9) { ah -= 6; } pair temp; temp.w = sally_a - data - !(sally_p & SALLY_FLAG.C); if(!temp.b.h) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } if((sally_a ^ data) & (sally_a ^ temp.b.l) & 128) { sally_p |= SALLY_FLAG.V; } else { sally_p &= ~SALLY_FLAG.V; } sally_Flags(temp.b.l); sally_a = (ah << 4) | (al & 15); } else { pair temp; temp.w = sally_a - data - !(sally_p & SALLY_FLAG.C); if(!temp.b.h) { sally_p |= SALLY_FLAG.C; } else { sally_p &= ~SALLY_FLAG.C; } if((sally_a ^ data) & (sally_a ^ temp.b.l) & 128) { sally_p |= SALLY_FLAG.V; } else { sally_p &= ~SALLY_FLAG.V; } sally_Flags(temp.b.l); sally_a = temp.b.l; } } // ---------------------------------------------------------------------------- // SEC // ---------------------------------------------------------------------------- static void sally_SEC( ) { sally_p |= SALLY_FLAG.C; } // ---------------------------------------------------------------------------- // SED // ---------------------------------------------------------------------------- static void sally_SED( ) { sally_p |= SALLY_FLAG.D; } // ---------------------------------------------------------------------------- // SEI // ---------------------------------------------------------------------------- static void sally_SEI( ) { sally_p |= SALLY_FLAG.I; } // ---------------------------------------------------------------------------- // STA // ---------------------------------------------------------------------------- static void sally_STA( ) { memory_Write(sally_address.w, sally_a); } // ---------------------------------------------------------------------------- // STX // ---------------------------------------------------------------------------- static void sally_stx( ) { memory_Write(sally_address.w, sally_x); } // ---------------------------------------------------------------------------- // STY // ---------------------------------------------------------------------------- static void sally_STY( ) { memory_Write(sally_address.w, sally_y); } // ---------------------------------------------------------------------------- // TAX // ---------------------------------------------------------------------------- static void sally_TAX( ) { sally_x = sally_a; sally_Flags(sally_x); } // ---------------------------------------------------------------------------- // TAY // ---------------------------------------------------------------------------- static void sally_TAY( ) { sally_y = sally_a; sally_Flags(sally_y); } // ---------------------------------------------------------------------------- // TSX // ---------------------------------------------------------------------------- static void sally_TSX( ) { sally_x = sally_s; sally_Flags(sally_x); } // ---------------------------------------------------------------------------- // TXA // ---------------------------------------------------------------------------- static void sally_TXA( ) { sally_a = sally_x; sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // TXS // ---------------------------------------------------------------------------- static void sally_TXS( ) { sally_s = sally_x; } // ---------------------------------------------------------------------------- // TYA // ---------------------------------------------------------------------------- static void sally_TYA( ) { sally_a = sally_y; sally_Flags(sally_a); } // ---------------------------------------------------------------------------- // Reset // ---------------------------------------------------------------------------- void sally_Reset( ) { sally_a = 0; sally_x = 0; sally_y = 0; sally_p = SALLY_FLAG.R; sally_s = 0; sally_pc.w = 0; } // ---------------------------------------------------------------------------- // ExecuteInstruction // ---------------------------------------------------------------------------- uint sally_ExecuteInstruction( ) { sally_opcode = memory_Read(sally_pc.w++); sally_cycles = SALLY_CYCLES[sally_opcode]; switch(sally_opcode) { case 0x00: sally_BRK( ); break; case 0x01: sally_IndirectX( ); sally_ORA( ); break; case 0x05: sally_ZeroPage( ); sally_ORA( ); break; case 0x06: sally_ZeroPage( ); sally_ASL( ); break; case 0x08: sally_PHP( ); break; case 0x09: sally_Immediate( ); sally_ORA( ); break; case 0x0a: sally_ASLA( ); break; case 0x0d: sally_Absolute( ); sally_ORA( ); break; case 0x0e: sally_Absolute( ); sally_ASL( ); break; case 0x10: sally_Relative( ); sally_BPL( ); break; case 0x11: sally_IndirectY( ); sally_ORA( ); sally_Delay(sally_y); break; case 0x15: sally_ZeroPageX( ); sally_ORA( ); break; case 0x16: sally_ZeroPageX( ); sally_ASL( ); break; case 0x18: sally_CLC( ); break; case 0x19: sally_AbsoluteY( ); sally_ORA( ); sally_Delay(sally_y); break; case 0x1d: sally_AbsoluteX( ); sally_ORA( ); sally_Delay(sally_x); break; case 0x1e: sally_AbsoluteX( ); sally_ASL( ); break; case 0x20: sally_Absolute( ); sally_JSR( ); break; case 0x21: sally_IndirectX( ); sally_AND( ); break; case 0x24: sally_ZeroPage( ); sally_BIT( ); break; case 0x25: sally_ZeroPage( ); sally_AND( ); break; case 0x26: sally_ZeroPage( ); sally_ROL( ); break; case 0x28: sally_PLP( ); break; case 0x29: sally_Immediate( ); sally_AND( ); break; case 0x2a: sally_ROLA( ); break; case 0x2c: sally_Absolute( ); sally_BIT( ); break; case 0x2d: sally_Absolute( ); sally_AND( ); break; case 0x2e: sally_Absolute( ); sally_ROL( ); break; case 0x30: sally_Relative( ); sally_BMI( ); break; case 0x31: sally_IndirectY( ); sally_AND( ); sally_Delay(sally_y); break; case 0x35: sally_ZeroPageX( ); sally_AND( ); break; case 0x36: sally_ZeroPageX( ); sally_ROL( ); break; case 0x38: sally_SEC( ); break; case 0x39: sally_AbsoluteY( ); sally_AND( ); sally_Delay(sally_y); break; case 0x3d: sally_AbsoluteX( ); sally_AND( ); sally_Delay(sally_x); break; case 0x3e: sally_AbsoluteX( ); sally_ROL( ); break; case 0x40: sally_RTI( ); break; case 0x41: sally_IndirectX( ); sally_EOR( ); break; case 0x45: sally_ZeroPage( ); sally_EOR( ); break; case 0x46: sally_ZeroPage( ); sally_LSR( ); break; case 0x48: sally_PHA( ); break; case 0x49: sally_Immediate( ); sally_EOR( ); break; case 0x4a: sally_LSRA( ); break; case 0x4c: sally_Absolute( ); sally_JMP( ); break; case 0x4d: sally_Absolute( ); sally_EOR( ); break; case 0x4e: sally_Absolute( ); sally_LSR( ); break; case 0x50: sally_Relative( ); sally_BVC( ); break; case 0x51: sally_IndirectY( ); sally_EOR( ); sally_Delay(sally_y); break; case 0x55: sally_ZeroPageX( ); sally_EOR( ); break; case 0x56: sally_ZeroPageX( ); sally_LSR( ); break; case 0x58: sally_CLI( ); break; case 0x59: sally_AbsoluteY( ); sally_EOR( ); sally_Delay(sally_y); break; case 0x5d: sally_AbsoluteX( ); sally_EOR( ); sally_Delay(sally_x); break; case 0x5e: sally_AbsoluteX( ); sally_LSR( ); break; case 0x60: sally_RTS( ); break; case 0x61: sally_IndirectX( ); sally_ADC( ); break; case 0x65: sally_ZeroPage( ); sally_ADC( ); break; case 0x66: sally_ZeroPage( ); sally_ROR( ); break; case 0x68: sally_PLA( ); break; case 0x69: sally_Immediate( ); sally_ADC( ); break; case 0x6a: sally_RORA( ); break; case 0x6c: sally_Indirect( ); sally_JMP( ); break; case 0x6d: sally_Absolute( ); sally_ADC( ); break; case 0x6e: sally_Absolute( ); sally_ROR( ); break; case 0x70: sally_Relative( ); sally_BVS( ); break; case 0x71: sally_IndirectY( ); sally_ADC( ); sally_Delay(sally_y); break; case 0x75: sally_ZeroPageX( ); sally_ADC( ); break; case 0x76: sally_ZeroPageX( ); sally_ROR( ); break; case 0x78: sally_SEI( ); break; case 0x79: sally_AbsoluteY( ); sally_ADC( ); sally_Delay(sally_y); break; case 0x7d: sally_AbsoluteX( ); sally_ADC( ); sally_Delay(sally_x); break; case 0x7e: sally_AbsoluteX( ); sally_ROR( ); break; case 0x81: sally_IndirectX( ); sally_STA( ); break; case 0x84: sally_ZeroPage( ); sally_STY( ); break; case 0x85: sally_ZeroPage( ); sally_STA( ); break; case 0x86: sally_ZeroPage( ); sally_stx( ); break; case 0x88: sally_DEY( ); break; case 0x8a: sally_TXA( ); break; case 0x8c: sally_Absolute( ); sally_STY( ); break; case 0x8d: sally_Absolute( ); sally_STA( ); break; case 0x8e: sally_Absolute( ); sally_stx( ); break; case 0x90: sally_Relative( ); sally_BCC( ); break; case 0x91: sally_IndirectY( ); sally_STA( ); break; case 0x94: sally_ZeroPageX( ); sally_STY( ); break; case 0x95: sally_ZeroPageX( ); sally_STA( ); break; case 0x96: sally_ZeroPageY( ); sally_stx( ); break; case 0x98: sally_TYA( ); break; case 0x99: sally_AbsoluteY( ); sally_STA( ); break; case 0x9a: sally_TXS( ); break; case 0x9d: sally_AbsoluteX( ); sally_STA( ); break; case 0xa0: sally_Immediate( ); sally_LDY( ); break; case 0xa1: sally_IndirectX( ); sally_LDA( ); break; case 0xa2: sally_Immediate( ); sally_LDX( ); break; case 0xa4: sally_ZeroPage( ); sally_LDY( ); break; case 0xa5: sally_ZeroPage( ); sally_LDA( ); break; case 0xa6: sally_ZeroPage( ); sally_LDX( ); break; case 0xa8: sally_TAY( ); break; case 0xa9: sally_Immediate( ); sally_LDA( ); break; case 0xaa: sally_TAX( ); break; case 0xac: sally_Absolute( ); sally_LDY( ); break; case 0xad: sally_Absolute( ); sally_LDA( ); break; case 0xae: sally_Absolute( ); sally_LDX( ); break; case 0xb0: sally_Relative( ); sally_BCS( ); break; case 0xb1: sally_IndirectY( ); sally_LDA( ); sally_Delay(sally_y); break; case 0xb4: sally_ZeroPageX( ); sally_LDY( ); break; case 0xb5: sally_ZeroPageX( ); sally_LDA( ); break; case 0xb6: sally_ZeroPageY( ); sally_LDX( ); break; case 0xb8: sally_CLV( ); break; case 0xb9: sally_AbsoluteY( ); sally_LDA( ); sally_Delay(sally_y); break; case 0xba: sally_TSX( ); break; case 0xbc: sally_AbsoluteX( ); sally_LDY( ); sally_Delay(sally_x); break; case 0xbd: sally_AbsoluteX( ); sally_LDA( ); sally_Delay(sally_x); break; case 0xbe: sally_AbsoluteY( ); sally_LDX( ); sally_Delay(sally_y); break; case 0xc0: sally_Immediate( ); sally_CPY( ); break; case 0xc1: sally_IndirectX( ); sally_CMP( ); break; case 0xc4: sally_ZeroPage( ); sally_CPY( ); break; case 0xc5: sally_ZeroPage( ); sally_CMP( ); break; case 0xc6: sally_ZeroPage( ); sally_DEC( ); break; case 0xc8: sally_INY( ); break; case 0xc9: sally_Immediate( ); sally_CMP( ); break; case 0xca: sally_DEX( ); break; case 0xcc: sally_Absolute( ); sally_CPY( ); break; case 0xcd: sally_Absolute( ); sally_CMP( ); break; case 0xce: sally_Absolute( ); sally_DEC( ); break; case 0xd0: sally_Relative( ); sally_BNE( ); break; case 0xd1: sally_IndirectY( ); sally_CMP( ); sally_Delay(sally_y); break; case 0xd5: sally_ZeroPageX( ); sally_CMP( ); break; case 0xd6: sally_ZeroPageX( ); sally_DEC( ); break; case 0xd8: sally_CLD( ); break; case 0xd9: sally_AbsoluteY( ); sally_CMP( ); sally_Delay(sally_y); break; case 0xdd: sally_AbsoluteX( ); sally_CMP( ); sally_Delay(sally_x); break; case 0xde: sally_AbsoluteX( ); sally_DEC( ); break; case 0xe0: sally_Immediate( ); sally_CPX( ); break; case 0xe1: sally_IndirectX( ); sally_SBC( ); break; case 0xe4: sally_ZeroPage( ); sally_CPX( ); break; case 0xe5: sally_ZeroPage( ); sally_SBC( ); break; case 0xe6: sally_ZeroPage( ); sally_INC( ); break; case 0xe8: sally_INX( ); break; case 0xe9: sally_Immediate( ); sally_SBC( ); break; case 0xea: sally_NOP( ); break; case 0xec: sally_Absolute( ); sally_CPX( ); break; case 0xed: sally_Absolute( ); sally_SBC( ); break; case 0xee: sally_Absolute( ); sally_INC( ); break; case 0xf0: sally_Relative( ); sally_BEQ( ); break; case 0xf1: sally_IndirectY( ); sally_SBC( ); sally_Delay(sally_y); break; case 0xf5: sally_ZeroPageX( ); sally_SBC( ); break; case 0xf6: sally_ZeroPageX( ); sally_INC( ); break; case 0xf8: sally_SED( ); break; case 0xf9: sally_AbsoluteY( ); sally_SBC( ); sally_Delay(sally_y); break; case 0xfd: sally_AbsoluteX( ); sally_SBC( ); sally_Delay(sally_x); break; case 0xfe: sally_AbsoluteX( ); sally_INC( ); break; default: break; } return sally_cycles; } // ---------------------------------------------------------------------------- // ExecuteRES // ---------------------------------------------------------------------------- uint sally_ExecuteRES( ) { sally_p = SALLY_FLAG.I | SALLY_FLAG.R | SALLY_FLAG.Z; sally_pc.b.l = memory_ram[SALLY_RES.L]; sally_pc.b.h = memory_ram[SALLY_RES.H]; return 6; } // ---------------------------------------------------------------------------- // ExecuteNMI // ---------------------------------------------------------------------------- uint sally_ExecuteNMI( ) { sally_Push(sally_pc.b.h); sally_Push(sally_pc.b.l); sally_p &= ~SALLY_FLAG.B; sally_Push(sally_p); sally_p |= SALLY_FLAG.I; sally_pc.b.l = memory_ram[SALLY_NMI.L]; sally_pc.b.h = memory_ram[SALLY_NMI.H]; return 7; } // ---------------------------------------------------------------------------- // Execute IRQ // ---------------------------------------------------------------------------- uint sally_ExecuteIRQ( ) { if(!(sally_p & SALLY_FLAG.I)) { sally_Push(sally_pc.b.h); sally_Push(sally_pc.b.l); sally_p &= ~SALLY_FLAG.B; sally_Push(sally_p); sally_p |= SALLY_FLAG.I; sally_pc.b.l = memory_ram[SALLY_IRQ.L]; sally_pc.b.h = memory_ram[SALLY_IRQ.H]; } return 7; }