use crate::address_mode::AddressMode;
use crate::constants::constants_isa_op::{
    ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX,
    ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY,
    ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A,
    ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS,
    ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK,
    ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS,
    ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY,
    ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS,
    ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX,
    ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I,
    ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS,
    ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS,
    ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I,
    ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY,
    ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I,
    ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP,
    ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I,
    ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP,
    ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP,
    ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX,
    ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I,
    ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED,
    ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY,
    ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS,
    ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS,
    ISA_OP_TYA,
};
use crate::op_info::OpInfo;
use crate::operation::Operation;
use crate::operation::Operation::*;

pub fn instruction_cycles(instruction: u8) -> u8 {
    INSTRUCTION_TABLE[instruction as usize].clone().unwrap().cycles
}

pub fn instruction_length(instruction: u8) -> u8 {
    INSTRUCTION_TABLE[instruction as usize].clone().unwrap().length
}


pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
    let mut table: [Option<OpInfo>; 256] = [const { None }; 256];
    table[ISA_OP_ADC_I as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "ADC #$",
        format_postfix: "",
    });
    table[ISA_OP_ADC_Z as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "ADC $",
        format_postfix: "",
    });
    table[ISA_OP_ADC_ZX as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "ADC $",
        format_postfix: ",X",
    });
    table[ISA_OP_ADC_ABS as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "ADC $",
        format_postfix: "",
    });
    table[ISA_OP_ADC_ABSX as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "ADC $",
        format_postfix: ",X",
    });
    table[ISA_OP_ADC_ABSY as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "ADC $",
        format_postfix: ",Y",
    });
    table[ISA_OP_ADC_INDX as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "ADC ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_ADC_INDY as usize] = Some(OpInfo {
        operation: ADC,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "ADC ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_AND_I as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "AND #$",
        format_postfix: "",
    });
    table[ISA_OP_AND_Z as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "AND $",
        format_postfix: "",
    });
    table[ISA_OP_AND_ZX as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "AND $",
        format_postfix: ",X",
    });
    table[ISA_OP_AND_ABS as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "AND $",
        format_postfix: "",
    });
    table[ISA_OP_AND_ABSX as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "AND $",
        format_postfix: ",X",
    });
    table[ISA_OP_AND_ABSY as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "AND $",
        format_postfix: ",Y",
    });
    table[ISA_OP_AND_INDX as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "AND ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_AND_INDY as usize] = Some(OpInfo {
        operation: AND,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "AND ($",
        format_postfix: "),Y",
    });
    table[ISA_OP_ASL_A as usize] = Some(OpInfo {
        operation: ASL,
        mode: AddressMode::Accumulator,
        length: 1,
        cycles: 2,
        format_prefix: "ASL",
        format_postfix: "",
    });
    table[ISA_OP_ASL_Z as usize] = Some(OpInfo {
        operation: ASL,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "ASL $",
        format_postfix: "",
    });
    table[ISA_OP_ASL_ZX as usize] = Some(OpInfo {
        operation: ASL,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "ASL $",
        format_postfix: ",X",
    });
    table[ISA_OP_ASL_ABS as usize] = Some(OpInfo {
        operation: ASL,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "ASL $",
        format_postfix: "",
    });
    table[ISA_OP_ASL_ABSX as usize] = Some(OpInfo {
        operation: ASL,
        mode: AddressMode::AbsoluteX,
        length: 3,

        cycles: 7,
        format_prefix: "ASL $",
        format_postfix: ",X",
    });

    table[ISA_OP_BCC as usize] = Some(OpInfo {
        operation: BCC,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BCC $",
        format_postfix: "",

    });
    table[ISA_OP_BCS as usize] = Some(OpInfo {
        operation: BCS,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BCS $",
        format_postfix: "",
    });
    table[ISA_OP_BEQ as usize] = Some(OpInfo {
        operation: BEQ,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BEQ $",
        format_postfix: "",

    });

    table[ISA_OP_BIT_ZP as usize] = Some(OpInfo {
        operation: BIT,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "BIT $",
        format_postfix: "",

    });
    table[ISA_OP_BIT_ABS as usize] = Some(OpInfo {
        operation: BIT,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "BIT $",
        format_postfix: "",

    });

    table[ISA_OP_BMI as usize] = Some(OpInfo {
        operation: BMI,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BMI #$",
        format_postfix: "",
    });

    table[ISA_OP_BNE as usize] = Some(OpInfo {
        operation: BNE,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BNE #$",
        format_postfix: "",

    });
    table[ISA_OP_BPL as usize] = Some(OpInfo {
        operation: Operation::BPL,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BPL #$",
        format_postfix: "",

    });
    table[ISA_OP_BRK as usize] = Some(OpInfo {
        operation: BRK,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 7,
        format_prefix: "BRK",
        format_postfix: "",

    });
    table[ISA_OP_BVC as usize] = Some(OpInfo {
        operation: BVC,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BVC #$",
        format_postfix: "",

    });
    table[ISA_OP_BVS as usize] = Some(OpInfo {
        operation: BVS,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "BVS #$",
        format_postfix: "",

    });
    table[ISA_OP_CLC as usize] = Some(OpInfo {
        operation: CLC,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "CLC",
        format_postfix: "",

    });
    table[ISA_OP_CLD as usize] = Some(OpInfo {
        operation: CLD,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "CLD",
        format_postfix: "",

    });
    table[ISA_OP_CLI as usize] = Some(OpInfo {
        operation: CLI,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "CLI",
        format_postfix: "",

    });
    table[ISA_OP_CLV as usize] = Some(OpInfo {
        operation: CLV,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "CLV",
        format_postfix: "",

    });

    table[ISA_OP_CMP_I as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "CMP #$",
        format_postfix: "",

    });
    table[ISA_OP_CMP_ZP as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "CMP $",
        format_postfix: "",

    });
    table[ISA_OP_CMP_ZPX as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "CMP $",
        format_postfix: ",X",

    });
    table[ISA_OP_CMP_ABS as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "CMP $",
        format_postfix: "",

    });
    table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "CMP $",
        format_postfix: ",X",

    });
    table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "CMP $",
        format_postfix: ",Y",

    });
    table[ISA_OP_CMP_INDX as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "CMP ($",
        format_postfix: " ,X)",

    });
    table[ISA_OP_CMP_INDY as usize] = Some(OpInfo {
        operation: CMP,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "CMP ($",
        format_postfix: "),Y",

    });

    table[ISA_OP_CPX_I as usize] = Some(OpInfo {
        operation: CPX,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "CPX #$",
        format_postfix: "",

    });
    table[ISA_OP_CPX_ZP as usize] = Some(OpInfo {
        operation: CPX,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "CPX $",
        format_postfix: "",

    });
    table[ISA_OP_CPX_ABS as usize] = Some(OpInfo {
        operation: CPX,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "CPX $",
        format_postfix: "",

    });
    table[ISA_OP_CPY_I as usize] = Some(OpInfo {
        operation: CPY,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "CPY #$",
        format_postfix: "",

    });
    table[ISA_OP_CPY_ZP as usize] = Some(OpInfo {
        operation: CPY,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "CPY $",
        format_postfix: "",
    });
    table[ISA_OP_CPY_ABS as usize] = Some(OpInfo {
        operation: CPY,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "CPY $",
        format_postfix: "",
    });

    table[ISA_OP_DEC_ZP as usize] = Some(OpInfo {
        operation: DEC,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "DEC $",
        format_postfix: "",

    });
    table[ISA_OP_DEC_ZPX as usize] = Some(OpInfo {
        operation: DEC,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "DEC $",
        format_postfix: ",X",

    });
    table[ISA_OP_DEC_ABS as usize] = Some(OpInfo {
        operation: DEC,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "DEC $",
        format_postfix: "",
    });
    table[ISA_OP_DEC_ABSX as usize] = Some(OpInfo {
        operation: DEC,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 7,
        format_prefix: "DEC $",
        format_postfix: ",X",
    });
    table[ISA_OP_DEX as usize] = Some(OpInfo {
        operation: DEX,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "DEX",
        format_postfix: "",
    });
    table[ISA_OP_DEY as usize] = Some(OpInfo {
        operation: DEY,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "DEY",
        format_postfix: "",
    });
    table[ISA_OP_EOR_I as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "EOR #$",
        format_postfix: "",
    });
    table[ISA_OP_EOR_ZP as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "EOR $",
        format_postfix: "",
    });
    table[ISA_OP_EOR_ZPX as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "EOR $",
        format_postfix: ",X",
    });
    table[ISA_OP_EOR_ABS as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "EOR $",
        format_postfix: "",
    });
    table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "EOR $",
        format_postfix: ",X",
    });
    table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "EOR $",
        format_postfix: ",Y",
    });
    table[ISA_OP_EOR_INDX as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "EOR ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_EOR_INDY as usize] = Some(OpInfo {
        operation: EOR,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "EOR ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_INC_ZP as usize] = Some(OpInfo {
        operation: INC,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "INC $",
        format_postfix: "",
    });
    table[ISA_OP_INC_ZPX as usize] = Some(OpInfo {
        operation: INC,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "INC $",
        format_postfix: ",X",
    });
    table[ISA_OP_INC_ABS as usize] = Some(OpInfo {
        operation: INC,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "INC $",
        format_postfix: "",
    });
    table[ISA_OP_INC_ABSX as usize] = Some(OpInfo {
        operation: INC,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 7,
        format_prefix: "INC $",
        format_postfix: ",X",
    });
    table[ISA_OP_INX as usize] = Some(OpInfo {
        operation: INX,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "INX",
        format_postfix: "",
    });
    table[ISA_OP_INY as usize] = Some(OpInfo {
        operation: INY,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "INY",
        format_postfix: "",
    });
    table[ISA_OP_JMP_ABS as usize] = Some(OpInfo {
        operation: JMP,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 3,
        format_prefix: "JMP $",
        format_postfix: "",
    });
    table[ISA_OP_JMP_IND as usize] = Some(OpInfo {
        operation: JMP,
        mode: AddressMode::Indirect,
        length: 3,
        cycles: 5,
        format_prefix: "JMP ($",
        format_postfix: ")",
    });
    table[ISA_OP_JSR as usize] = Some(OpInfo {
        operation: JSR,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "JSR $",
        format_postfix: "",
    });

    table[ISA_OP_LDA_I as usize] = Some(OpInfo {
        operation: Operation::LDA,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "LDA #$",
        format_postfix: "",
    });
    table[ISA_OP_LDA_Z as usize] = Some(OpInfo {
        operation: LDA,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "LDA $",
        format_postfix: "",
    });
    table[ISA_OP_LDA_ZX as usize] = Some(OpInfo {
        operation: LDA,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "LDA $",
        format_postfix: ",X",
    });
    table[ISA_OP_LDA_ABS as usize] = Some(OpInfo {
        operation: Operation::LDA,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "LDA $",
        format_postfix: "",
    });
    table[ISA_OP_LDA_ABSX as usize] = Some(OpInfo {
        operation: LDA,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "LDA $",
        format_postfix: ",X",
    });
    table[ISA_OP_LDA_ABSY as usize] = Some(OpInfo {
        operation: LDA,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "LDA $",
        format_postfix: ",Y",
    });
    table[ISA_OP_LDA_INDX as usize] = Some(OpInfo {
        operation: Operation::LDA,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "LDA ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_LDA_INDY as usize] = Some(OpInfo {
        operation: LDA,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "LDA ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_LDX_I as usize] = Some(OpInfo {
        operation: Operation::LDX,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "LDX #$",
        format_postfix: "",
    });
    table[ISA_OP_LDX_ZP as usize] = Some(OpInfo {
        operation: Operation::LDX,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "LDX $",
        format_postfix: "",
    });
    table[ISA_OP_LDX_ZPY as usize] = Some(OpInfo {
        operation: LDX,
        mode: AddressMode::ZeroPageY,
        length: 2,
        cycles: 4,
        format_prefix: "LDX $",
        format_postfix: ",Y",
    });
    table[ISA_OP_LDX_ABS as usize] = Some(OpInfo {
        operation: Operation::LDX,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "LDX $",
        format_postfix: "",
    });
    table[ISA_OP_LDX_ABSY as usize] = Some(OpInfo {
        operation: Operation::LDX,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "LDX $",
        format_postfix: ",Y",
    });

    table[ISA_OP_LDY_I as usize] = Some(OpInfo {
        operation: LDY,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "LDY #$",
        format_postfix: "",
    });
    table[ISA_OP_LDY_ZP as usize] = Some(OpInfo {
        operation: LDY,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "LDY $",
        format_postfix: "",
    });
    table[ISA_OP_LDY_ZPX as usize] = Some(OpInfo {
        operation: Operation::LDY,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "LDY $",
        format_postfix: ",X",
    });
    table[ISA_OP_LDY_ABS as usize] = Some(OpInfo {
        operation: LDY,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "LDY $",
        format_postfix: "",
    });
    table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo {
        operation: LDY,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "LDY $",
        format_postfix: ",X",
    });

    table[ISA_OP_LSR_A as usize] = Some(OpInfo {
        operation: Operation::LSR,
        mode: AddressMode::Accumulator,
        length: 1,
        cycles: 2,
        format_prefix: "LSR",
        format_postfix: "",
    });
    table[ISA_OP_LSR_ZP as usize] = Some(OpInfo {
        operation: LSR,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "LSR $",
        format_postfix: "",
    });
    table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo {
        operation: LSR,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "LSR $",
        format_postfix: ",X",
    });
    table[ISA_OP_LSR_ABS as usize] = Some(OpInfo {
        operation: Operation::LSR,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "LSR $",
        format_postfix: "",
    });
    table[ISA_OP_LSR_ABSX as usize] = Some(OpInfo {
        operation: Operation::LSR,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 7,
        format_prefix: "LSR $",
        format_postfix: ",X",
    });

    table[ISA_OP_NOP as usize] = Some(OpInfo {
        operation: Operation::NOP,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "NOP",
        format_postfix: "",
    });

    table[ISA_OP_ORA_I as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "ORA #$",
        format_postfix: "",
    });
    table[ISA_OP_ORA_ZP as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "ORA $",
        format_postfix: "",
    });
    table[ISA_OP_ORA_ZPX as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "ORA $",
        format_postfix: ",X",
    });
    table[ISA_OP_ORA_ABS as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "ORA $",
        format_postfix: "",
    });

    table[ISA_OP_ORA_ABSX as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "ORA $",
        format_postfix: ",X",
    });
    table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "ORA $",
        format_postfix: ",Y",
    });
    table[ISA_OP_ORA_INDX as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "ORA ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_ORA_INDY as usize] = Some(OpInfo {
        operation: Operation::ORA,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "ORA ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_PHA as usize] = Some(OpInfo {
        operation: PHA,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 3,
        format_prefix: "PHA",
        format_postfix: "",
    });
    table[ISA_OP_PHP as usize] = Some(OpInfo {
        operation: Operation::PHP,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 3,
        format_prefix: "PHP",
        format_postfix: "",
    });
    table[ISA_OP_PLA as usize] = Some(OpInfo {
        operation: Operation::PLA,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 4,
        format_prefix: "PLA",
        format_postfix: "",
    });
    table[ISA_OP_PLP as usize] = Some(OpInfo {
        operation: Operation::PLP,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 4,
        format_prefix: "PLP",
        format_postfix: "",
    });

    table[ISA_OP_ROL_A as usize] = Some(OpInfo {
        operation: Operation::ROL,
        mode: AddressMode::Accumulator,
        length: 1,
        cycles: 2,
        format_prefix: "ROL",
        format_postfix: "",
    });
    table[ISA_OP_ROL_ZP as usize] = Some(OpInfo {
        operation: Operation::ROL,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "ROL $",
        format_postfix: "",
    });
    table[ISA_OP_ROL_ZPX as usize] = Some(OpInfo {
        operation: Operation::ROL,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "ROL $",
        format_postfix: ",X",
    });
    table[ISA_OP_ROL_ABS as usize] = Some(OpInfo {
        operation: Operation::ROL,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "ROL $",
        format_postfix: "",
    });
    table[ISA_OP_ROL_ABSX as usize] = Some(OpInfo {
        operation: Operation::ROL,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 7,
        format_prefix: "ROL $",
        format_postfix: ",X",
    });

    table[ISA_OP_ROR_A as usize] = Some(OpInfo {
        operation: Operation::ROR,
        mode: AddressMode::Accumulator,
        length: 1,
        cycles: 2,
        format_prefix: "ROR",
        format_postfix: "",
    });
    table[ISA_OP_ROR_ZP as usize] = Some(OpInfo {
        operation: Operation::ROR,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 5,
        format_prefix: "ROR $",
        format_postfix: "",
    });
    table[ISA_OP_ROR_ZPX as usize] = Some(OpInfo {
        operation: Operation::ROR,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 6,
        format_prefix: "ROR $",
        format_postfix: ",X",
    });
    table[ISA_OP_ROR_ABS as usize] = Some(OpInfo {
        operation: Operation::ROR,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 6,
        format_prefix: "ROR $",
        format_postfix: "",
    });
    table[ISA_OP_ROR_ABSX as usize] = Some(OpInfo {
        operation: Operation::ROR,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 7,
        format_prefix: "ROR $",
        format_postfix: ",X",
    });

    table[ISA_OP_RTI as usize] = Some(OpInfo {
        operation: Operation::RTI,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "RTI",
        format_postfix: "",
    });
    table[ISA_OP_RTS as usize] = Some(OpInfo {
        operation: Operation::RTS,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "RTS",
        format_postfix: "",
    });

    table[ISA_OP_SBC_I as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::Immediate,
        length: 2,
        cycles: 2,
        format_prefix: "SBC #$",
        format_postfix: "",
    });
    table[ISA_OP_SBC_ZP as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "SBC $",
        format_postfix: "",
    });
    table[ISA_OP_SBC_ZPX as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "SBC $",
        format_postfix: ",X",
    });
    table[ISA_OP_SBC_ABS as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "SBC $",
        format_postfix: "",
    });
    table[ISA_OP_SBC_ABSX as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 4,
        format_prefix: "SBC $",
        format_postfix: ",X",
    });
    table[ISA_OP_SBC_ABSY as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 4,
        format_prefix: "SBC $",
        format_postfix: ",Y",
    });
    table[ISA_OP_SBC_INDX as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "SBC ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_SBC_INDY as usize] = Some(OpInfo {
        operation: Operation::SBC,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 5,
        format_prefix: "SBC ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_SEC as usize] = Some(OpInfo {
        operation: SEC,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "SEC",
        format_postfix: "",
    });
    table[ISA_OP_SED as usize] = Some(OpInfo {
        operation: Operation::SED,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "SED",
        format_postfix: "",
    });
    table[ISA_OP_SEI as usize] = Some(OpInfo {
        operation: Operation::SEI,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "SEI",
        format_postfix: "",
    });

    table[ISA_OP_STA_ZP as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "STA $",
        format_postfix: "",
    });
    table[ISA_OP_STA_ZPX as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "STA $",
        format_postfix: ",X",
    });
    table[ISA_OP_STA_ABS as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "STA $",
        format_postfix: "",
    });
    table[ISA_OP_STA_ABSX as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::AbsoluteX,
        length: 3,
        cycles: 5,
        format_prefix: "STA $",
        format_postfix: ",X",
    });
    table[ISA_OP_STA_ABSY as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::AbsoluteY,
        length: 3,
        cycles: 5,
        format_prefix: "STA $",
        format_postfix: ",Y",
    });
    table[ISA_OP_STA_INDX as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::IndirectX,
        length: 2,
        cycles: 6,
        format_prefix: "STA ($",
        format_postfix: ",X)",
    });
    table[ISA_OP_STA_INDY as usize] = Some(OpInfo {
        operation: Operation::STA,
        mode: AddressMode::IndirectY,
        length: 2,
        cycles: 6,
        format_prefix: "STA ($",
        format_postfix: "),Y",
    });

    table[ISA_OP_STX_ZP as usize] = Some(OpInfo {
        operation: Operation::STX,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "STX $",
        format_postfix: "",
    });
    table[ISA_OP_STX_ZPY as usize] = Some(OpInfo {
        operation: Operation::STX,
        mode: AddressMode::ZeroPageY,
        length: 2,
        cycles: 4,
        format_prefix: "STX $",
        format_postfix: ",Y",
    });
    table[ISA_OP_STX_ABS as usize] = Some(OpInfo {
        operation: Operation::STX,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "STX $",
        format_postfix: "",
    });

    table[ISA_OP_STY_ZP as usize] = Some(OpInfo {
        operation: Operation::STY,
        mode: AddressMode::ZeroPage,
        length: 2,
        cycles: 3,
        format_prefix: "STY $",
        format_postfix: "",
    });
    table[ISA_OP_STY_ZPX as usize] = Some(OpInfo {
        operation: Operation::STY,
        mode: AddressMode::ZeroPageX,
        length: 2,
        cycles: 4,
        format_prefix: "STY $",
        format_postfix: ",X",
    });
    table[ISA_OP_STY_ABS as usize] = Some(OpInfo {
        operation: Operation::STY,
        mode: AddressMode::Absolute,
        length: 3,
        cycles: 4,
        format_prefix: "STY $",
        format_postfix: "",
    });

    table[ISA_OP_TAX as usize] = Some(OpInfo {
        operation: Operation::TAX,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TAX",
        format_postfix: "",
    });
    table[ISA_OP_TAY as usize] = Some(OpInfo {
        operation: TAY,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TAY",
        format_postfix: "",
    });
    table[ISA_OP_TSX as usize] = Some(OpInfo {
        operation: TSX,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TSX",
        format_postfix: "",
    });
    table[ISA_OP_TXA as usize] = Some(OpInfo {
        operation: Operation::TXA,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TXA",
        format_postfix: "",
    });
    table[ISA_OP_TXS as usize] = Some(OpInfo {
        operation: Operation::TXS,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TXS",
        format_postfix: "",
    });
    table[ISA_OP_TYA as usize] = Some(OpInfo {
        operation: TYA,
        mode: AddressMode::Implied,
        length: 1,
        cycles: 2,
        format_prefix: "TYA",
        format_postfix: "",
    });

    table
};

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_instruction_table_completeness() {
        use INSTRUCTION_TABLE; // Adjust to your actual path

        let mut defined_count = 0;
        let mut defined_opcodes = vec![];

        for (i, entry) in INSTRUCTION_TABLE.iter().enumerate() {
            if let Some(info) = entry {
                defined_count += 1;
                defined_opcodes.push(i);
                // Optional: sanity check
                assert!(
                    info.length > 0 && info.cycles > 0,
                    "Invalid OpInfo at opcode {:#04x?}",
                    i
                );
            }
        }

        println!("Defined opcodes: {}", defined_count);
        for i in 0..256 {
            if defined_opcodes.contains(&i) {
                print!("{:02x} ", i);
            }
        }
        println!("\nMissing opcodes:");
        for i in 0..256 {
            if !defined_opcodes.contains(&i) {
                print!("{:02X} ", i);
            }
        }
        println!();

        // The standard 6502 has 151 documented opcodes
        assert_eq!(
            defined_count, 151,
            "Expected 151 opcodes, found {}",
            defined_count
        );
    }
}
