diff --git a/src/cpu/archive/6502_all_opcodes.json b/src/cpu/archive/6502_all_opcodes.json new file mode 100644 index 0000000..bd3a81e --- /dev/null +++ b/src/cpu/archive/6502_all_opcodes.json @@ -0,0 +1,2062 @@ +[ + { + "opcode": "$00", + "name": "BRK", + "bytes": 1, + "cycles": 7, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$01", + "name": "ORA", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$02", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$03", + "name": "SLO", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$04", + "name": "NOP", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$05", + "name": "ORA", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$06", + "name": "ASL", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$07", + "name": "SLO", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$08", + "name": "PHP", + "bytes": 1, + "cycles": 3, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$09", + "name": "ORA", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$0A", + "name": "ASL", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$0B", + "name": "ANC", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$0C", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$0D", + "name": "ORA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$0E", + "name": "ASL", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$0F", + "name": "SLO", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$10", + "name": "BPL", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$11", + "name": "ORA", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$12", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$13", + "name": "SLO", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$14", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$15", + "name": "ORA", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$16", + "name": "ASL", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$17", + "name": "SLO", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$18", + "name": "CLC", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$19", + "name": "ORA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$1A", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$1B", + "name": "SLO", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$1C", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$1D", + "name": "ORA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$1E", + "name": "ASL", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$1F", + "name": "SLO", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$20", + "name": "JSR", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$21", + "name": "AND", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$22", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$23", + "name": "RLA", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$24", + "name": "BIT", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$25", + "name": "AND", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$26", + "name": "ROL", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$27", + "name": "RLA", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$28", + "name": "PLP", + "bytes": 1, + "cycles": 4, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$29", + "name": "AND", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$2A", + "name": "ROL", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$2B", + "name": "ANC", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$2C", + "name": "BIT", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$2D", + "name": "AND", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$2E", + "name": "ROL", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$2F", + "name": "RLA", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$30", + "name": "BMI", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$31", + "name": "AND", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$32", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$33", + "name": "RLA", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$34", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$35", + "name": "AND", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$36", + "name": "ROL", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$37", + "name": "RLA", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$38", + "name": "SEC", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$39", + "name": "AND", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$3A", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$3B", + "name": "RLA", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$3C", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$3D", + "name": "AND", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$3E", + "name": "ROL", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$3F", + "name": "RLA", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$40", + "name": "RTI", + "bytes": 1, + "cycles": 6, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$41", + "name": "EOR", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$42", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$43", + "name": "SRE", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$44", + "name": "NOP", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$45", + "name": "EOR", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$46", + "name": "LSR", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$47", + "name": "SRE", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$48", + "name": "PHA", + "bytes": 1, + "cycles": 3, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$49", + "name": "EOR", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$4A", + "name": "LSR", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$4B", + "name": "ALR", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$4C", + "name": "JMP", + "bytes": 3, + "cycles": 3, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$4D", + "name": "EOR", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$4E", + "name": "LSR", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$4F", + "name": "SRE", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$50", + "name": "BVC", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$51", + "name": "EOR", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$52", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$53", + "name": "SRE", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$54", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$55", + "name": "EOR", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$56", + "name": "LSR", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$57", + "name": "SRE", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$58", + "name": "CLI", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$59", + "name": "EOR", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$5A", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$5B", + "name": "SRE", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$5C", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$5D", + "name": "EOR", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$5E", + "name": "LSR", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$5F", + "name": "SRE", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$60", + "name": "RTS", + "bytes": 1, + "cycles": 6, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$61", + "name": "ADC", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$62", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$63", + "name": "RRA", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$64", + "name": "NOP", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$65", + "name": "ADC", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$66", + "name": "ROR", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$67", + "name": "RRA", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$68", + "name": "PLA", + "bytes": 1, + "cycles": 4, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$69", + "name": "ADC", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$6A", + "name": "ROR", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$6B", + "name": "ARR", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$6C", + "name": "JMP", + "bytes": 3, + "cycles": 5, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$6D", + "name": "ADC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$6E", + "name": "ROR", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$6F", + "name": "RRA", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$70", + "name": "BVS", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$71", + "name": "ADC", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$72", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$73", + "name": "RRA", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$74", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$75", + "name": "ADC", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$76", + "name": "ROR", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$77", + "name": "RRA", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$78", + "name": "SEI", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$79", + "name": "ADC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$7A", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$7B", + "name": "RRA", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$7C", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$7D", + "name": "ADC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$7E", + "name": "ROR", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$7F", + "name": "RRA", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$80", + "name": "NOP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$81", + "name": "STA", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$82", + "name": "NOP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$83", + "name": "SAX", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$84", + "name": "STY", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$85", + "name": "STA", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$86", + "name": "STX", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$87", + "name": "SAX", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$88", + "name": "DEY", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$89", + "name": "NOP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$8A", + "name": "TXA", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$8B", + "name": "XAA", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$8C", + "name": "STY", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$8D", + "name": "STA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$8E", + "name": "STX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$8F", + "name": "SAX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$90", + "name": "BCC", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$91", + "name": "STA", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$92", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$93", + "name": "AHX", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$94", + "name": "STY", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$95", + "name": "STA", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$96", + "name": "STX", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,Y", + "unofficial": false + }, + { + "opcode": "$97", + "name": "SAX", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,Y", + "unofficial": true + }, + { + "opcode": "$98", + "name": "TYA", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$99", + "name": "STA", + "bytes": 3, + "cycles": 5, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$9A", + "name": "TXS", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$9B", + "name": "TAS", + "bytes": 3, + "cycles": 5, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$9C", + "name": "SHY", + "bytes": 3, + "cycles": 5, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$9D", + "name": "STA", + "bytes": 3, + "cycles": 5, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$9E", + "name": "SHX", + "bytes": 3, + "cycles": 5, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$9F", + "name": "AHX", + "bytes": 3, + "cycles": 5, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$A0", + "name": "LDY", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$A1", + "name": "LDA", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$A2", + "name": "LDX", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$A3", + "name": "LAX", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$A4", + "name": "LDY", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$A5", + "name": "LDA", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$A6", + "name": "LDX", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$A7", + "name": "LAX", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$A8", + "name": "TAY", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$A9", + "name": "LDA", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$AA", + "name": "TAX", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$AB", + "name": "LAX", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$AC", + "name": "LDY", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$AD", + "name": "LDA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$AE", + "name": "LDX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$AF", + "name": "LAX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$B0", + "name": "BCS", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$B1", + "name": "LDA", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$B2", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$B3", + "name": "LAX", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$B4", + "name": "LDY", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$B5", + "name": "LDA", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$B6", + "name": "LDX", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,Y", + "unofficial": false + }, + { + "opcode": "$B7", + "name": "LAX", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,Y", + "unofficial": true + }, + { + "opcode": "$B8", + "name": "CLV", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$B9", + "name": "LDA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$BA", + "name": "TSX", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$BB", + "name": "LAS", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$BC", + "name": "LDY", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$BD", + "name": "LDA", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$BE", + "name": "LDX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$BF", + "name": "LAX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$C0", + "name": "CPY", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$C1", + "name": "CMP", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$C2", + "name": "NOP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$C3", + "name": "DCP", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$C4", + "name": "CPY", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$C5", + "name": "CMP", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$C6", + "name": "DEC", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$C7", + "name": "DCP", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$C8", + "name": "INY", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$C9", + "name": "CMP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$CA", + "name": "DEX", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$CB", + "name": "AXS", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$CC", + "name": "CPY", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$CD", + "name": "CMP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$CE", + "name": "DEC", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$CF", + "name": "DCP", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$D0", + "name": "BNE", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$D1", + "name": "CMP", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$D2", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$D3", + "name": "DCP", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$D4", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$D5", + "name": "CMP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$D6", + "name": "DEC", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$D7", + "name": "DCP", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$D8", + "name": "CLD", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$D9", + "name": "CMP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$DA", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$DB", + "name": "DCP", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$DC", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$DD", + "name": "CMP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$DE", + "name": "DEC", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$DF", + "name": "DCP", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$E0", + "name": "CPX", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$E1", + "name": "SBC", + "bytes": 2, + "cycles": 6, + "mode": "Indirect,X", + "unofficial": false + }, + { + "opcode": "$E2", + "name": "NOP", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$E3", + "name": "ISC", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,X", + "unofficial": true + }, + { + "opcode": "$E4", + "name": "CPX", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$E5", + "name": "SBC", + "bytes": 2, + "cycles": 3, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$E6", + "name": "INC", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": false + }, + { + "opcode": "$E7", + "name": "ISC", + "bytes": 2, + "cycles": 5, + "mode": "ZeroPage", + "unofficial": true + }, + { + "opcode": "$E8", + "name": "INX", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$E9", + "name": "SBC", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": false + }, + { + "opcode": "$EA", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$EB", + "name": "SBC", + "bytes": 2, + "cycles": 2, + "mode": "Immediate", + "unofficial": true + }, + { + "opcode": "$EC", + "name": "CPX", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$ED", + "name": "SBC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$EE", + "name": "INC", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": false + }, + { + "opcode": "$EF", + "name": "ISC", + "bytes": 3, + "cycles": 6, + "mode": "Absolute", + "unofficial": true + }, + { + "opcode": "$F0", + "name": "BEQ", + "bytes": 2, + "cycles": 2, + "mode": "Relative", + "unofficial": false + }, + { + "opcode": "$F1", + "name": "SBC", + "bytes": 2, + "cycles": 5, + "mode": "Indirect,Y", + "unofficial": false + }, + { + "opcode": "$F2", + "name": "KIL", + "bytes": 1, + "cycles": 0, + "mode": "Implied", + "unofficial": true, + "unstable": true + }, + { + "opcode": "$F3", + "name": "ISC", + "bytes": 2, + "cycles": 8, + "mode": "Indirect,Y", + "unofficial": true + }, + { + "opcode": "$F4", + "name": "NOP", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$F5", + "name": "SBC", + "bytes": 2, + "cycles": 4, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$F6", + "name": "INC", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": false + }, + { + "opcode": "$F7", + "name": "ISC", + "bytes": 2, + "cycles": 6, + "mode": "ZeroPage,X", + "unofficial": true + }, + { + "opcode": "$F8", + "name": "SED", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": false + }, + { + "opcode": "$F9", + "name": "SBC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,Y", + "unofficial": false + }, + { + "opcode": "$FA", + "name": "NOP", + "bytes": 1, + "cycles": 2, + "mode": "Implied", + "unofficial": true + }, + { + "opcode": "$FB", + "name": "ISC", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,Y", + "unofficial": true + }, + { + "opcode": "$FC", + "name": "NOP", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": true + }, + { + "opcode": "$FD", + "name": "SBC", + "bytes": 3, + "cycles": 4, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$FE", + "name": "INC", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": false + }, + { + "opcode": "$FF", + "name": "ISC", + "bytes": 3, + "cycles": 7, + "mode": "Absolute,X", + "unofficial": true + } +] \ No newline at end of file diff --git a/src/cpu/archive/unofficial_instr_to_opcodes.json b/src/cpu/archive/unofficial_instr_to_opcodes.json new file mode 100644 index 0000000..3d888f7 --- /dev/null +++ b/src/cpu/archive/unofficial_instr_to_opcodes.json @@ -0,0 +1,1432 @@ +{ + "BRK": { + "0x00": { + "notation": null, + "name": "IMPL", + "examples": ["BRK"] + } + }, + "ORA": { + "0x01": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["ORA ($BB,X)"] + }, + "0x05": { + "notation": "d", + "name": "ZP", + "examples": ["ORA $BB"] + }, + "0x09": { + "notation": "#i", + "name": "IMM", + "examples": ["ORA #$BB"] + }, + "0x0D": { + "notation": "a", + "name": "ABS", + "examples": ["ORA $LLHH"] + }, + "0x11": { + "notation": "(d),y", + "name": "INDY", + "examples": ["ORA ($BB),Y"] + }, + "0x15": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ORA $BB,X"] + }, + "0x19": { + "notation": "a,y", + "name": "ABSY", + "examples": ["ORA $LLHH,Y"] + }, + "0x1D": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ORA $LLHH,X"] + } + }, + "STP": { + "0x02": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x12": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x22": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x32": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x42": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x52": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x62": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x72": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0x92": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0xB2": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0xD2": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + }, + "0xF2": { + "notation": null, + "name": "IMPL", + "examples": ["STP"] + } + }, + "SLO": { + "0x03": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["SLO ($BB,X)"] + }, + "0x07": { + "notation": "d", + "name": "ZP", + "examples": ["SLO $BB"] + }, + "0x0F": { + "notation": "a", + "name": "ABS", + "examples": ["SLO $LLHH"] + }, + "0x13": { + "notation": "(d),y", + "name": "INDY", + "examples": ["SLO ($BB),Y"] + }, + "0x17": { + "notation": "d,x", + "name": "ZPX", + "examples": ["SLO $BB,X"] + }, + "0x1B": { + "notation": "a,y", + "name": "ABSY", + "examples": ["SLO $LLHH,Y"] + }, + "0x1F": { + "notation": "a,x", + "name": "ABSX", + "examples": ["SLO $LLHH,X"] + } + }, + "NOP": { + "0x04": { + "notation": "d", + "name": "ZP", + "examples": ["NOP $BB"] + }, + "0x0C": { + "notation": "a", + "name": "ABS", + "examples": ["NOP $LLHH"] + }, + "0x14": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0x1A": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0x1C": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + }, + "0x34": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0x3A": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0x3C": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + }, + "0x44": { + "notation": "d", + "name": "ZP", + "examples": ["NOP $BB"] + }, + "0x54": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0x5A": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0x5C": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + }, + "0x64": { + "notation": "d", + "name": "ZP", + "examples": ["NOP $BB"] + }, + "0x74": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0x7A": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0x7C": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + }, + "0x80": { + "notation": "#i", + "name": "IMM", + "examples": ["NOP #$BB"] + }, + "0x82": { + "notation": "#i", + "name": "IMM", + "examples": ["NOP #$BB"] + }, + "0x89": { + "notation": "#i", + "name": "IMM", + "examples": ["NOP #$BB"] + }, + "0xC2": { + "notation": "#i", + "name": "IMM", + "examples": ["NOP #$BB"] + }, + "0xD4": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0xDA": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0xDC": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + }, + "0xE2": { + "notation": "#i", + "name": "IMM", + "examples": ["NOP #$BB"] + }, + "0xEA": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0xF4": { + "notation": "d,x", + "name": "ZPX", + "examples": ["NOP $BB,X"] + }, + "0xFA": { + "notation": null, + "name": "IMPL", + "examples": ["NOP"] + }, + "0xFC": { + "notation": "a,x", + "name": "ABSX", + "examples": ["NOP $LLHH,X"] + } + }, + "ASL": { + "0x06": { + "notation": "d", + "name": "ZP", + "examples": ["ASL $BB"] + }, + "0x0A": { + "notation": null, + "name": "IMPL", + "examples": ["ASL"] + }, + "0x0E": { + "notation": "a", + "name": "ABS", + "examples": ["ASL $LLHH"] + }, + "0x16": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ASL $BB,X"] + }, + "0x1E": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ASL $LLHH,X"] + } + }, + "PHP": { + "0x08": { + "notation": null, + "name": "IMPL", + "examples": ["PHP"] + } + }, + "ANC": { + "0x0B": { + "notation": "#i", + "name": "IMM", + "examples": ["ANC #$BB"] + }, + "0x2B": { + "notation": "#i", + "name": "IMM", + "examples": ["ANC #$BB"] + } + }, + "BPL": { + "0x10": { + "notation": "*+d", + "name": "REL", + "examples": ["BPL $BB", "BPL label"] + } + }, + "CLC": { + "0x18": { + "notation": null, + "name": "IMPL", + "examples": ["CLC"] + } + }, + "JSR": { + "0x20": { + "notation": "a", + "name": "ABS", + "examples": ["JSR $LLHH"] + } + }, + "AND": { + "0x21": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["AND ($BB,X)"] + }, + "0x25": { + "notation": "d", + "name": "ZP", + "examples": ["AND $BB"] + }, + "0x29": { + "notation": "#i", + "name": "IMM", + "examples": ["AND #$BB"] + }, + "0x2D": { + "notation": "a", + "name": "ABS", + "examples": ["AND $LLHH"] + }, + "0x31": { + "notation": "(d),y", + "name": "INDY", + "examples": ["AND ($BB),Y"] + }, + "0x35": { + "notation": "d,x", + "name": "ZPX", + "examples": ["AND $BB,X"] + }, + "0x39": { + "notation": "a,y", + "name": "ABSY", + "examples": ["AND $LLHH,Y"] + }, + "0x3D": { + "notation": "a,x", + "name": "ABSX", + "examples": ["AND $LLHH,X"] + } + }, + "RLA": { + "0x23": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["RLA ($BB,X)"] + }, + "0x27": { + "notation": "d", + "name": "ZP", + "examples": ["RLA $BB"] + }, + "0x2F": { + "notation": "a", + "name": "ABS", + "examples": ["RLA $LLHH"] + }, + "0x33": { + "notation": "(d),y", + "name": "INDY", + "examples": ["RLA ($BB),Y"] + }, + "0x37": { + "notation": "d,x", + "name": "ZPX", + "examples": ["RLA $BB,X"] + }, + "0x3B": { + "notation": "a,y", + "name": "ABSY", + "examples": ["RLA $LLHH,Y"] + }, + "0x3F": { + "notation": "a,x", + "name": "ABSX", + "examples": ["RLA $LLHH,X"] + } + }, + "BIT": { + "0x24": { + "notation": "d", + "name": "ZP", + "examples": ["BIT $BB"] + }, + "0x2C": { + "notation": "a", + "name": "ABS", + "examples": ["BIT $LLHH"] + } + }, + "ROL": { + "0x26": { + "notation": "d", + "name": "ZP", + "examples": ["ROL $BB"] + }, + "0x2A": { + "notation": null, + "name": "IMPL", + "examples": ["ROL"] + }, + "0x2E": { + "notation": "a", + "name": "ABS", + "examples": ["ROL $LLHH"] + }, + "0x36": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ROL $BB,X"] + }, + "0x3E": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ROL $LLHH,X"] + } + }, + "PLP": { + "0x28": { + "notation": null, + "name": "IMPL", + "examples": ["PLP"] + } + }, + "BMI": { + "0x30": { + "notation": "*+d", + "name": "REL", + "examples": ["BMI $BB", "BMI label"] + } + }, + "SEC": { + "0x38": { + "notation": null, + "name": "IMPL", + "examples": ["SEC"] + } + }, + "RTI": { + "0x40": { + "notation": null, + "name": "IMPL", + "examples": ["RTI"] + } + }, + "EOR": { + "0x41": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["EOR ($BB,X)"] + }, + "0x45": { + "notation": "d", + "name": "ZP", + "examples": ["EOR $BB"] + }, + "0x49": { + "notation": "#i", + "name": "IMM", + "examples": ["EOR #$BB"] + }, + "0x4D": { + "notation": "a", + "name": "ABS", + "examples": ["EOR $LLHH"] + }, + "0x51": { + "notation": "(d),y", + "name": "INDY", + "examples": ["EOR ($BB),Y"] + }, + "0x55": { + "notation": "d,x", + "name": "ZPX", + "examples": ["EOR $BB,X"] + }, + "0x59": { + "notation": "a,y", + "name": "ABSY", + "examples": ["EOR $LLHH,Y"] + }, + "0x5D": { + "notation": "a,x", + "name": "ABSX", + "examples": ["EOR $LLHH,X"] + } + }, + "SRE": { + "0x43": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["SRE ($BB,X)"] + }, + "0x47": { + "notation": "d", + "name": "ZP", + "examples": ["SRE $BB"] + }, + "0x4F": { + "notation": "a", + "name": "ABS", + "examples": ["SRE $LLHH"] + }, + "0x53": { + "notation": "(d),y", + "name": "INDY", + "examples": ["SRE ($BB),Y"] + }, + "0x57": { + "notation": "d,x", + "name": "ZPX", + "examples": ["SRE $BB,X"] + }, + "0x5B": { + "notation": "a,y", + "name": "ABSY", + "examples": ["SRE $LLHH,Y"] + }, + "0x5F": { + "notation": "a,x", + "name": "ABSX", + "examples": ["SRE $LLHH,X"] + } + }, + "LSR": { + "0x46": { + "notation": "d", + "name": "ZP", + "examples": ["LSR $BB"] + }, + "0x4A": { + "notation": null, + "name": "IMPL", + "examples": ["LSR"] + }, + "0x4E": { + "notation": "a", + "name": "ABS", + "examples": ["LSR $LLHH"] + }, + "0x56": { + "notation": "d,x", + "name": "ZPX", + "examples": ["LSR $BB,X"] + }, + "0x5E": { + "notation": "a,x", + "name": "ABSX", + "examples": ["LSR $LLHH,X"] + } + }, + "PHA": { + "0x48": { + "notation": null, + "name": "IMPL", + "examples": ["PHA"] + } + }, + "ALR": { + "0x4B": { + "notation": "#i", + "name": "IMM", + "examples": ["ALR #$BB"] + } + }, + "JMP": { + "0x4C": { + "notation": "a", + "name": "ABS", + "examples": ["JMP $LLHH"] + }, + "0x6C": { + "notation": "(a)", + "name": "IND", + "examples": ["JMP ($LLHH)"] + } + }, + "BVC": { + "0x50": { + "notation": "*+d", + "name": "REL", + "examples": ["BVC $BB", "BVC label"] + } + }, + "CLI": { + "0x58": { + "notation": null, + "name": "IMPL", + "examples": ["CLI"] + } + }, + "RTS": { + "0x60": { + "notation": null, + "name": "IMPL", + "examples": ["RTS"] + } + }, + "ADC": { + "0x61": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["ADC ($BB,X)"] + }, + "0x65": { + "notation": "d", + "name": "ZP", + "examples": ["ADC $BB"] + }, + "0x69": { + "notation": "#i", + "name": "IMM", + "examples": ["ADC #$BB"] + }, + "0x6D": { + "notation": "a", + "name": "ABS", + "examples": ["ADC $LLHH"] + }, + "0x71": { + "notation": "(d),y", + "name": "INDY", + "examples": ["ADC ($BB),Y"] + }, + "0x75": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ADC $BB,X"] + }, + "0x79": { + "notation": "a,y", + "name": "ABSY", + "examples": ["ADC $LLHH,Y"] + }, + "0x7D": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ADC $LLHH,X"] + } + }, + "RRA": { + "0x63": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["RRA ($BB,X)"] + }, + "0x67": { + "notation": "d", + "name": "ZP", + "examples": ["RRA $BB"] + }, + "0x6F": { + "notation": "a", + "name": "ABS", + "examples": ["RRA $LLHH"] + }, + "0x73": { + "notation": "(d),y", + "name": "INDY", + "examples": ["RRA ($BB),Y"] + }, + "0x77": { + "notation": "d,x", + "name": "ZPX", + "examples": ["RRA $BB,X"] + }, + "0x7B": { + "notation": "a,y", + "name": "ABSY", + "examples": ["RRA $LLHH,Y"] + }, + "0x7F": { + "notation": "a,x", + "name": "ABSX", + "examples": ["RRA $LLHH,X"] + } + }, + "ROR": { + "0x66": { + "notation": "d", + "name": "ZP", + "examples": ["ROR $BB"] + }, + "0x6A": { + "notation": null, + "name": "IMPL", + "examples": ["ROR"] + }, + "0x6E": { + "notation": "a", + "name": "ABS", + "examples": ["ROR $LLHH"] + }, + "0x76": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ROR $BB,X"] + }, + "0x7E": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ROR $LLHH,X"] + } + }, + "PLA": { + "0x68": { + "notation": null, + "name": "IMPL", + "examples": ["PLA"] + } + }, + "ARR": { + "0x6B": { + "notation": "#i", + "name": "IMM", + "examples": ["ARR #$BB"] + } + }, + "BVS": { + "0x70": { + "notation": "*+d", + "name": "REL", + "examples": ["BVS $BB", "BVS label"] + } + }, + "SEI": { + "0x78": { + "notation": null, + "name": "IMPL", + "examples": ["SEI"] + } + }, + "STA": { + "0x81": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["STA ($BB,X)"] + }, + "0x85": { + "notation": "d", + "name": "ZP", + "examples": ["STA $BB"] + }, + "0x8D": { + "notation": "a", + "name": "ABS", + "examples": ["STA $LLHH"] + }, + "0x91": { + "notation": "(d),y", + "name": "INDY", + "examples": ["STA ($BB),Y"] + }, + "0x95": { + "notation": "d,x", + "name": "ZPX", + "examples": ["STA $BB,X"] + }, + "0x99": { + "notation": "a,y", + "name": "ABSY", + "examples": ["STA $LLHH,Y"] + }, + "0x9D": { + "notation": "a,x", + "name": "ABSX", + "examples": ["STA $LLHH,X"] + } + }, + "SAX": { + "0x83": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["SAX ($BB,X)"] + }, + "0x87": { + "notation": "d", + "name": "ZP", + "examples": ["SAX $BB"] + }, + "0x8F": { + "notation": "a", + "name": "ABS", + "examples": ["SAX $LLHH"] + }, + "0x97": { + "notation": "d,y", + "name": "ZPY", + "examples": ["SAX $BB,Y"] + } + }, + "STY": { + "0x84": { + "notation": "d", + "name": "ZP", + "examples": ["STY $BB"] + }, + "0x8C": { + "notation": "a", + "name": "ABS", + "examples": ["STY $LLHH"] + }, + "0x94": { + "notation": "d,x", + "name": "ZPX", + "examples": ["STY $BB,X"] + } + }, + "STX": { + "0x86": { + "notation": "d", + "name": "ZP", + "examples": ["STX $BB"] + }, + "0x8E": { + "notation": "a", + "name": "ABS", + "examples": ["STX $LLHH"] + }, + "0x96": { + "notation": "d,y", + "name": "ZPY", + "examples": ["STX $BB,Y"] + } + }, + "DEY": { + "0x88": { + "notation": null, + "name": "IMPL", + "examples": ["DEY"] + } + }, + "TXA": { + "0x8A": { + "notation": null, + "name": "IMPL", + "examples": ["TXA"] + } + }, + "XAA": { + "0x8B": { + "notation": "#i", + "name": "IMM", + "examples": ["XAA #$BB"] + } + }, + "BCC": { + "0x90": { + "notation": "*+d", + "name": "REL", + "examples": ["BCC $BB", "BCC label"] + } + }, + "AHX": { + "0x93": { + "notation": "(d),y", + "name": "INDY", + "examples": ["AHX ($BB),Y"] + }, + "0x9F": { + "notation": "a,y", + "name": "ABSY", + "examples": ["AHX $LLHH,Y"] + } + }, + "TYA": { + "0x98": { + "notation": null, + "name": "IMPL", + "examples": ["TYA"] + } + }, + "TXS": { + "0x9A": { + "notation": null, + "name": "IMPL", + "examples": ["TXS"] + } + }, + "TAS": { + "0x9B": { + "notation": "a,y", + "name": "ABSY", + "examples": ["TAS $LLHH,Y"] + } + }, + "SHY": { + "0x9C": { + "notation": "a,x", + "name": "ABSX", + "examples": ["SHY $LLHH,X"] + } + }, + "SHX": { + "0x9E": { + "notation": "a,y", + "name": "ABSY", + "examples": ["SHX $LLHH,Y"] + } + }, + "LDY": { + "0xA0": { + "notation": "#i", + "name": "IMM", + "examples": ["LDY #$BB"] + }, + "0xA4": { + "notation": "d", + "name": "ZP", + "examples": ["LDY $BB"] + }, + "0xAC": { + "notation": "a", + "name": "ABS", + "examples": ["LDY $LLHH"] + }, + "0xB4": { + "notation": "d,x", + "name": "ZPX", + "examples": ["LDY $BB,X"] + }, + "0xBC": { + "notation": "a,x", + "name": "ABSX", + "examples": ["LDY $LLHH,X"] + } + }, + "LDA": { + "0xA1": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["LDA ($BB,X)"] + }, + "0xA5": { + "notation": "d", + "name": "ZP", + "examples": ["LDA $BB"] + }, + "0xA9": { + "notation": "#i", + "name": "IMM", + "examples": ["LDA #$BB"] + }, + "0xAD": { + "notation": "a", + "name": "ABS", + "examples": ["LDA $LLHH"] + }, + "0xB1": { + "notation": "(d),y", + "name": "INDY", + "examples": ["LDA ($BB),Y"] + }, + "0xB5": { + "notation": "d,x", + "name": "ZPX", + "examples": ["LDA $BB,X"] + }, + "0xB9": { + "notation": "a,y", + "name": "ABSY", + "examples": ["LDA $LLHH,Y"] + }, + "0xBD": { + "notation": "a,x", + "name": "ABSX", + "examples": ["LDA $LLHH,X"] + } + }, + "LDX": { + "0xA2": { + "notation": "#i", + "name": "IMM", + "examples": ["LDX #$BB"] + }, + "0xA6": { + "notation": "d", + "name": "ZP", + "examples": ["LDX $BB"] + }, + "0xAE": { + "notation": "a", + "name": "ABS", + "examples": ["LDX $LLHH"] + }, + "0xB6": { + "notation": "d,y", + "name": "ZPY", + "examples": ["LDX $BB,Y"] + }, + "0xBE": { + "notation": "a,y", + "name": "ABSY", + "examples": ["LDX $LLHH,Y"] + } + }, + "LAX": { + "0xA3": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["LAX ($BB,X)"] + }, + "0xA7": { + "notation": "d", + "name": "ZP", + "examples": ["LAX $BB"] + }, + "0xAB": { + "notation": "#i", + "name": "IMM", + "examples": ["LAX #$BB"] + }, + "0xAF": { + "notation": "a", + "name": "ABS", + "examples": ["LAX $LLHH"] + }, + "0xB3": { + "notation": "(d),y", + "name": "INDY", + "examples": ["LAX ($BB),Y"] + }, + "0xB7": { + "notation": "d,y", + "name": "ZPY", + "examples": ["LAX $BB,Y"] + }, + "0xBF": { + "notation": "a,y", + "name": "ABSY", + "examples": ["LAX $LLHH,Y"] + } + }, + "TAY": { + "0xA8": { + "notation": null, + "name": "IMPL", + "examples": ["TAY"] + } + }, + "TAX": { + "0xAA": { + "notation": null, + "name": "IMPL", + "examples": ["TAX"] + } + }, + "BCS": { + "0xB0": { + "notation": "*+d", + "name": "REL", + "examples": ["BCS $BB", "BCS label"] + } + }, + "CLV": { + "0xB8": { + "notation": null, + "name": "IMPL", + "examples": ["CLV"] + } + }, + "TSX": { + "0xBA": { + "notation": null, + "name": "IMPL", + "examples": ["TSX"] + } + }, + "LAS": { + "0xBB": { + "notation": "a,y", + "name": "ABSY", + "examples": ["LAS $LLHH,Y"] + } + }, + "CPY": { + "0xC0": { + "notation": "#i", + "name": "IMM", + "examples": ["CPY #$BB"] + }, + "0xC4": { + "notation": "d", + "name": "ZP", + "examples": ["CPY $BB"] + }, + "0xCC": { + "notation": "a", + "name": "ABS", + "examples": ["CPY $LLHH"] + } + }, + "CMP": { + "0xC1": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["CMP ($BB,X)"] + }, + "0xC5": { + "notation": "d", + "name": "ZP", + "examples": ["CMP $BB"] + }, + "0xC9": { + "notation": "#i", + "name": "IMM", + "examples": ["CMP #$BB"] + }, + "0xCD": { + "notation": "a", + "name": "ABS", + "examples": ["CMP $LLHH"] + }, + "0xD1": { + "notation": "(d),y", + "name": "INDY", + "examples": ["CMP ($BB),Y"] + }, + "0xD5": { + "notation": "d,x", + "name": "ZPX", + "examples": ["CMP $BB,X"] + }, + "0xD9": { + "notation": "a,y", + "name": "ABSY", + "examples": ["CMP $LLHH,Y"] + }, + "0xDD": { + "notation": "a,x", + "name": "ABSX", + "examples": ["CMP $LLHH,X"] + } + }, + "DCP": { + "0xC3": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["DCP ($BB,X)"] + }, + "0xC7": { + "notation": "d", + "name": "ZP", + "examples": ["DCP $BB"] + }, + "0xCF": { + "notation": "a", + "name": "ABS", + "examples": ["DCP $LLHH"] + }, + "0xD3": { + "notation": "(d),y", + "name": "INDY", + "examples": ["DCP ($BB),Y"] + }, + "0xD7": { + "notation": "d,x", + "name": "ZPX", + "examples": ["DCP $BB,X"] + }, + "0xDB": { + "notation": "a,y", + "name": "ABSY", + "examples": ["DCP $LLHH,Y"] + }, + "0xDF": { + "notation": "a,x", + "name": "ABSX", + "examples": ["DCP $LLHH,X"] + } + }, + "DEC": { + "0xC6": { + "notation": "d", + "name": "ZP", + "examples": ["DEC $BB"] + }, + "0xCE": { + "notation": "a", + "name": "ABS", + "examples": ["DEC $LLHH"] + }, + "0xD6": { + "notation": "d,x", + "name": "ZPX", + "examples": ["DEC $BB,X"] + }, + "0xDE": { + "notation": "a,x", + "name": "ABSX", + "examples": ["DEC $LLHH,X"] + } + }, + "INY": { + "0xC8": { + "notation": null, + "name": "IMPL", + "examples": ["INY"] + } + }, + "DEX": { + "0xCA": { + "notation": null, + "name": "IMPL", + "examples": ["DEX"] + } + }, + "AXS": { + "0xCB": { + "notation": "#i", + "name": "IMM", + "examples": ["AXS #$BB"] + } + }, + "BNE": { + "0xD0": { + "notation": "*+d", + "name": "REL", + "examples": ["BNE $BB", "BNE label"] + } + }, + "CLD": { + "0xD8": { + "notation": null, + "name": "IMPL", + "examples": ["CLD"] + } + }, + "CPX": { + "0xE0": { + "notation": "#i", + "name": "IMM", + "examples": ["CPX #$BB"] + }, + "0xE4": { + "notation": "d", + "name": "ZP", + "examples": ["CPX $BB"] + }, + "0xEC": { + "notation": "a", + "name": "ABS", + "examples": ["CPX $LLHH"] + } + }, + "SBC": { + "0xE1": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["SBC ($BB,X)"] + }, + "0xE5": { + "notation": "d", + "name": "ZP", + "examples": ["SBC $BB"] + }, + "0xE9": { + "notation": "#i", + "name": "IMM", + "examples": ["SBC #$BB"] + }, + "0xEB": { + "notation": "#i", + "name": "IMM", + "examples": ["SBC #$BB"] + }, + "0xED": { + "notation": "a", + "name": "ABS", + "examples": ["SBC $LLHH"] + }, + "0xF1": { + "notation": "(d),y", + "name": "INDY", + "examples": ["SBC ($BB),Y"] + }, + "0xF5": { + "notation": "d,x", + "name": "ZPX", + "examples": ["SBC $BB,X"] + }, + "0xF9": { + "notation": "a,y", + "name": "ABSY", + "examples": ["SBC $LLHH,Y"] + }, + "0xFD": { + "notation": "a,x", + "name": "ABSX", + "examples": ["SBC $LLHH,X"] + } + }, + "ISC": { + "0xE3": { + "notation": "(d,x)", + "name": "INDX", + "examples": ["ISC ($BB,X)"] + }, + "0xE7": { + "notation": "d", + "name": "ZP", + "examples": ["ISC $BB"] + }, + "0xEF": { + "notation": "a", + "name": "ABS", + "examples": ["ISC $LLHH"] + }, + "0xF3": { + "notation": "(d),y", + "name": "INDY", + "examples": ["ISC ($BB),Y"] + }, + "0xF7": { + "notation": "d,x", + "name": "ZPX", + "examples": ["ISC $BB,X"] + }, + "0xFB": { + "notation": "a,y", + "name": "ABSY", + "examples": ["ISC $LLHH,Y"] + }, + "0xFF": { + "notation": "a,x", + "name": "ABSX", + "examples": ["ISC $LLHH,X"] + } + }, + "INC": { + "0xE6": { + "notation": "d", + "name": "ZP", + "examples": ["INC $BB"] + }, + "0xEE": { + "notation": "a", + "name": "ABS", + "examples": ["INC $LLHH"] + }, + "0xF6": { + "notation": "d,x", + "name": "ZPX", + "examples": ["INC $BB,X"] + }, + "0xFE": { + "notation": "a,x", + "name": "ABSX", + "examples": ["INC $LLHH,X"] + } + }, + "INX": { + "0xE8": { + "notation": null, + "name": "IMPL", + "examples": ["INX"] + } + }, + "BEQ": { + "0xF0": { + "notation": "*+d", + "name": "REL", + "examples": ["BEQ $BB", "BEQ label"] + } + }, + "SED": { + "0xF8": { + "notation": null, + "name": "IMPL", + "examples": ["SED"] + } + } +} diff --git a/src/cpu/cpu.rs b/src/cpu/cpu.rs index 461d7f6..afd202b 100644 --- a/src/cpu/cpu.rs +++ b/src/cpu/cpu.rs @@ -1,6 +1,8 @@ // The main (and, as far as I know, only) difference between the Ricoh 2A03 used in the NES and the MOS 6502 is that the 20A4 has integrated audio. // Since I haven't implemented audio, this effectively becomes a general-purpose 6502 microchip emulator. (except by the BUS, and NMI) +use serde::Deserialize; + use crate::cpu::opcodes::{self, opcodes_map}; use crate::engine::console::{LogType, print_logs}; use crate::memory::bus::BUS; @@ -67,9 +69,10 @@ pub struct CPU { pub vblank: bool, pub last_opcode: u8, - is_halted: bool + is_halted: bool, + nmi_prev: bool, } -#[derive(Debug)] +#[derive(Debug, Deserialize)] #[allow(non_camel_case_types)] pub enum AddressingMode { Immediate, @@ -102,6 +105,7 @@ impl CPU { cycles: 0, last_opcode : 0, is_halted: false, + nmi_prev: false, } } @@ -176,7 +180,10 @@ impl CPU { self.program_counter = self.bus.mem_read_u16(0xFFFA); - self.vblank = false; // Limpa a flag vblank + self.cycles += 7; + self.bus.tick(7); + + self.vblank = false; } @@ -201,6 +208,7 @@ impl CPU { //usually 7 on real hardware self.cycles += 7; + self.bus.tick(7); } /////writes the program counter to @@ -698,14 +706,14 @@ impl CPU { let (addr, page_crossed) = self.get_oprand_adress(mode); let val = self.bus.mem_read(addr); - let sum = self.register_a as u16 + val as u16 //+ (((self.status & 0b0000_0001) != 0) as u16); //adiciona 1 se for True e 0 se for False (Rust converte True para 1 e False para 0) + let sum = self.register_a as u16 + val as u16 + (if self.status.contains(CpuFlags::CARRY) { 1 } else { 0 }); - if sum > 0xff { //seta a carry flag + if sum > 0xff { self.status.insert(CpuFlags::CARRY); } else { self.status.remove(CpuFlags::CARRY); @@ -713,10 +721,7 @@ impl CPU { let result = sum as u8; - if (result ^ val) & (result ^ self.register_a) & 0b1000_0000 != 0 { //seta a overflow flag - //usa os operadores logicos de XOR para verificar quais bits sao diferentes e dps verifica com 0b100... - //já q é o bit que quer ser verificado(o unico bit q importa)... se for diferente dos outros significa que - //ocorreu um overflow, + if (result ^ val) & (result ^ self.register_a) & 0b1000_0000 != 0 { self.status.insert(CpuFlags::OVERFLOW); } else { self.status.remove(CpuFlags::OVERFLOW); @@ -810,6 +815,127 @@ impl CPU { self.program_counter = self.bus.mem_read_u16(0xFFFE); } + // -------------- undocumented / unofficial -------------- + + ///(page crosses) + fn lax(&mut self, mode: &AddressingMode) -> u8 { + let (addr, page_crossed) = self.get_oprand_adress(mode); + let value = self.bus.mem_read(addr); + + self.register_a = value; + self.register_x = value; + + self.update_zero_and_negative_flags(value); + + if page_crossed { + 1 + } else { + 0 + } + } + + fn axs(&mut self) { + let and_result = self.register_x & self.register_a; + let immediate = self.bus.mem_read(self.program_counter); + + self.program_counter = self.program_counter.wrapping_add(1); + + if and_result >= immediate { + self.status.insert(CpuFlags::CARRY); + } else { + self.status.remove(CpuFlags::CARRY); + } + + let final_result = and_result.wrapping_sub(immediate); + self.register_x = final_result; + + self.update_zero_and_negative_flags(self.register_x); + } + + fn slo(&mut self, mode: &AddressingMode) -> u8 { + //ASL + let (addr, page_crossed) = self.get_oprand_adress(mode); + let mut data = self.bus.mem_read(addr); + if data >> 7 == 1 { + self.status.insert(CpuFlags::CARRY); + } + else { + self.status.remove(CpuFlags::CARRY); + } + data = data << 1; + self.bus.mem_write(addr, data); + self.update_zero_and_negative_flags(data); + + //ORA + self.register_a = self.register_a | data; + self.update_zero_and_negative_flags(self.register_a); + + if page_crossed { 1 } else { 0 } + } + + fn rra(&mut self, mode: &AddressingMode) -> u8 { + let (addr, _) = self.get_oprand_adress(mode); + let mut val = self.bus.mem_read(addr); + + let carry_in = if self.status.contains(CpuFlags::CARRY) { 1 } else { 0 }; + let carry_out = val & 1; + + val = (val >> 1) | (carry_in << 7); + + if carry_out == 1 { + self.status.insert(CpuFlags::CARRY); + } else { + self.status.remove(CpuFlags::CARRY); + } + + self.bus.mem_write(addr, val); + + let sum = self.register_a as u16 + val as u16 + carry_out as u16; + let result = sum as u8; + + if (self.register_a ^ result) & (val ^ result) & 0b1000_0000 != 0 { + self.status.insert(CpuFlags::OVERFLOW); + } else { + self.status.remove(CpuFlags::OVERFLOW); + } + + if sum > 0xFF { + self.status.insert(CpuFlags::CARRY); + } else { + self.status.remove(CpuFlags::CARRY); + } + + self.register_a = result; + self.update_zero_and_negative_flags(self.register_a); + + 0 + } + + fn rla(&mut self, mode: &AddressingMode) -> u8 { + let (addr, page_crossed) = self.get_oprand_adress(mode); + + let mut data = self.bus.mem_read(addr); + let previous_carry = self.status.contains(CpuFlags::CARRY); + + if data & 0b1000_0000 != 0 { + self.status.insert(CpuFlags::CARRY); + } else { + self.status.remove(CpuFlags::CARRY); + } + + data = data << 1; + if previous_carry { + data = data | 0b0000_0001 + } + + self.bus.mem_write(addr, data); + + self.register_a = self.register_a & data; + self.update_zero_and_negative_flags(self.register_a); + + if page_crossed { 1 } else { 0 } + } + pub fn step(&mut self) -> (bool, u8) { self.step_with_callback(None::) } @@ -822,12 +948,16 @@ impl CPU { c(self) } - if self.vblank { + let nmi_current = self.bus.nmi_active(); + + if nmi_current && !self.nmi_prev { print_logs(LogType::Debug, format!("Vblank Triggered [PC:{} | A:{} | X:{} | Y:{} CYC: {}]", self.bus.peek(self.program_counter), self.register_a, self.register_x, self.register_y, self.cycles )); self.trigger_cpu_nmi(); } + + self.nmi_prev = nmi_current; if self.bus.mapper.borrow_mut().irq_pending() && !self.status.contains(CpuFlags::INTERRUPT_DISABLE) { self.trigger_cpu_irq(); @@ -851,6 +981,21 @@ impl CPU { let mut opcycles = opcode.cycles; + let mut is_2002_read = false; + if opcode.len == 3 && (self.last_opcode == 0x2C || self.last_opcode == 0xAD) { + let lo = self.bus.mem_read(self.program_counter); + let hi = self.bus.mem_read(self.program_counter.wrapping_add(1)); + let addr = ((hi as u16) << 8) | (lo as u16); + + if addr == 0x2002 { + is_2002_read = true; + } + } + + if is_2002_read { + self.bus.tick(opcycles); + } + match self.last_opcode { //LDA 0xa9 | 0xa5 | 0xb5 | 0xad | 0xbd | 0xb9 | 0xa1 | 0xb1 => { @@ -1037,24 +1182,57 @@ impl CPU { 0x98 => self.transfer_to_accumulator(self.register_y), //NOP - No Operation - 0xEA => { + 0xEA | 0x04 | 0x0C | 0x14 | 0x1A | 0x1C | 0x34 | 0x3A | + 0x3C | 0x44 | 0x54 | 0x5A | 0x5C | 0x64 | 0x74 | 0x7A | + 0x7C | 0x80 | 0x82 | 0x89 | 0xC2 | 0xD4 | 0xDA | 0xDC | + 0xE2 | 0xF4 | 0xFA | 0xFC => { } + + //LAX + 0xA3 | 0xA7 | 0xAB | 0xAF | 0xB3 | 0xB7 | 0xBF => { + opcycles += self.lax(&opcode.mode) + } + //AXS + 0xCB => self.axs(), + + //SLO + 0x03 | 0x07 | 0x0F | 0x13 | 0x17 | 0x1B | 0x1F => { + opcycles += self.slo(&opcode.mode) + } + + 0x63 | 0x67 | 0x6F | 0x73 | 0x77 | 0x7B | 0x7F => { + opcycles += self.rra(&opcode.mode) + } + + 0x3B | 0x23 | 0x27 | 0x2F | 0x33 | 0x37 | 0x3F => { + opcycles += self.rla(&opcode.mode) } //BRK 0x00 => self.brk(), - _ => print_logs(LogType::Warning, format!("code: {}", self.last_opcode)) + _ => { + print_logs(LogType::Warning, format!( + "CPU INSTRUCTION NOT IMPLEMENTED! ( CODE:{:02X}, at PC:{:04X} ), + CPU is halted to prevent undefined behavior", + self.last_opcode, self.program_counter - 1 + )); + self.is_halted = true; + return (true, 0); + } } - self.cycles += opcycles as u64; - - let tick_result = self.bus.tick(opcycles); - - if tick_result.nmi { - self.vblank = true; + if !is_2002_read { + self.bus.tick(opcycles); + } else { + let extra_cycles = opcycles - opcode.cycles; + if extra_cycles > 0 { + self.bus.tick(extra_cycles); + } } + self.cycles += opcycles as u64; + //increments the program counter accordingly to how many cicles the opcode is specified at the hashmap if program_counter_state == self.program_counter { self.program_counter += (opcode.len -1) as u16; diff --git a/src/cpu/opcodes.rs b/src/cpu/opcodes.rs index 38a1ea1..a67b7b4 100644 --- a/src/cpu/opcodes.rs +++ b/src/cpu/opcodes.rs @@ -1,16 +1,22 @@ +// json file and archive based on: https://www.nesdev.org/wiki/Visual6502wiki/6502_all_256_Opcodes +// also credits to: +//https://gist.github.com/kirbyUK/1a0797e19f54c1e35e67ce7b385b323e +//https://github.com/michael-0acf4/opcodes-json-6502 + +use serde::Deserialize; + use crate::cpu::cpu::AddressingMode; use std::{collections::HashMap, sync::{Arc, OnceLock}}; -#[allow(dead_code)] pub struct OpCode { pub code: u8, - pub mnemonic: &'static str, + pub mnemonic: String, pub len:u8, pub cycles: u8, pub mode: AddressingMode, } impl OpCode { - fn new(code: u8, mnemonic: &'static str, len: u8, cycles: u8, mode: AddressingMode) -> Self{ + fn new(code: u8, mnemonic: String, len: u8, cycles: u8, mode: AddressingMode) -> Self{ OpCode { code: code, mnemonic: mnemonic, @@ -20,6 +26,14 @@ impl OpCode { } } } +#[derive(Deserialize)] +struct RawOpCode { + opcode: String, + name: String, + bytes: u8, + cycles: u8, + mode: String, +} pub static CPU_OPS_CODES: OnceLock> = OnceLock::new(); pub static OPCODES_MAP: OnceLock> = OnceLock::new(); @@ -28,235 +42,32 @@ pub static OPCODES_MAP: OnceLock> = OnceLock::new() //such as a vector of "opcode::new()" pub fn cpu_ops_codes() -> &'static Arc<[OpCode]> { CPU_OPS_CODES.get_or_init(|| { - let opcodes = vec![ - OpCode::new(0x00, "BRK", 1, 7, AddressingMode::NoneAddressing), - OpCode::new(0xaa, "TAX", 1, 2, AddressingMode::NoneAddressing), - OpCode::new(0xe8, "INX", 1, 2, AddressingMode::NoneAddressing), - - OpCode::new(0xa9, "LDA", 2, 2, AddressingMode::Immediate), - OpCode::new(0xa5, "LDA", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xb5, "LDA", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0xad, "LDA", 3, 4, AddressingMode::Absolute), - OpCode::new(0xbd, "LDA", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0xb9, "LDA", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0xa1, "LDA", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0xb1, "LDA", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - OpCode::new(0x85, "STA", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x95, "STA", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x8d, "STA", 3, 4, AddressingMode::Absolute), - OpCode::new(0x9d, "STA", 3, 5, AddressingMode::Absolute_X), - OpCode::new(0x99, "STA", 3, 5, AddressingMode::Absolute_Y), - OpCode::new(0x81, "STA", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0x91, "STA", 2, 6, AddressingMode::Indirect_Y), - - OpCode::new(0x69, "ADC", 2, 2, AddressingMode::Immediate), - OpCode::new(0x65, "ADC", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x75, "ADC", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x6D, "ADC", 3, 4, AddressingMode::Absolute), - OpCode::new(0x7D, "ADC", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0x79, "ADC", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0x61, "ADC", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0x71, "ADC", 2, 5, AddressingMode::Indirect_Y), - - OpCode::new(0xB0, "BCS", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0x90, "BCC", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0xF0, "BEQ", 2, 2, AddressingMode::NoneAddressing), - OpCode::new(0x30, "BMI", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0xD0, "BNE", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0x10, "BPL", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0x50, "BVC", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - OpCode::new(0x70, "BVS", 2, 2, AddressingMode::NoneAddressing), // +1 if page crossed - - OpCode::new(0x24, "BIT",2 , 3, AddressingMode::ZeroPage), - OpCode::new(0x2c, "BIT",3 , 4, AddressingMode::Absolute), - - // AND - Logical AND - OpCode::new(0x29, "AND", 2, 2, AddressingMode::Immediate), - OpCode::new(0x25, "AND", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x35, "AND", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x2D, "AND", 3, 4, AddressingMode::Absolute), - OpCode::new(0x3D, "AND", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0x39, "AND", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0x21, "AND", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0x31, "AND", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - // ASL - Arithmetic Shift Left - OpCode::new(0x0A, "ASL", 1, 2, AddressingMode::NoneAddressing), // Accumulator - OpCode::new(0x06, "ASL", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0x16, "ASL", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0x0E, "ASL", 3, 6, AddressingMode::Absolute), - OpCode::new(0x1E, "ASL", 3, 7, AddressingMode::Absolute_X), - - // CLC - Clear Carry Flag - OpCode::new(0x18, "CLC", 1, 2, AddressingMode::NoneAddressing), - // CLD - Clear Decimal Mode - OpCode::new(0xD8, "CLD", 1, 2, AddressingMode::NoneAddressing), - // CLI - Clear Interrupt Disable - OpCode::new(0x58, "CLI", 1, 2, AddressingMode::NoneAddressing), - // CLV - Clear Overflow Flag - OpCode::new(0xB8, "CLV", 1, 2, AddressingMode::NoneAddressing), - - // CMP - Compare Accumulator - OpCode::new(0xC9, "CMP", 2, 2, AddressingMode::Immediate), - OpCode::new(0xC5, "CMP", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xD5, "CMP", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0xCD, "CMP", 3, 4, AddressingMode::Absolute), - OpCode::new(0xDD, "CMP", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0xD9, "CMP", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0xC1, "CMP", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0xD1, "CMP", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - // CPX - Compare X Register - OpCode::new(0xE0, "CPX", 2, 2, AddressingMode::Immediate), - OpCode::new(0xE4, "CPX", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xEC, "CPX", 3, 4, AddressingMode::Absolute), - - // CPY - Compare Y Register - OpCode::new(0xC0, "CPY", 2, 2, AddressingMode::Immediate), - OpCode::new(0xC4, "CPY", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xCC, "CPY", 3, 4, AddressingMode::Absolute), - - // DEC - Decrement Memory - OpCode::new(0xC6, "DEC", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0xD6, "DEC", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0xCE, "DEC", 3, 6, AddressingMode::Absolute), - OpCode::new(0xDE, "DEC", 3, 7, AddressingMode::Absolute_X), - - // DEX - Decrement X Register - OpCode::new(0xCA, "DEX", 1, 2, AddressingMode::NoneAddressing), - // DEY - Decrement Y Register - OpCode::new(0x88, "DEY", 1, 2, AddressingMode::NoneAddressing), - - // EOR - Exclusive OR - OpCode::new(0x49, "EOR", 2, 2, AddressingMode::Immediate), - OpCode::new(0x45, "EOR", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x55, "EOR", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x4D, "EOR", 3, 4, AddressingMode::Absolute), - OpCode::new(0x5D, "EOR", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0x59, "EOR", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0x41, "EOR", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0x51, "EOR", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - // INC - Increment Memory - OpCode::new(0xE6, "INC", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0xF6, "INC", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0xEE, "INC", 3, 6, AddressingMode::Absolute), - OpCode::new(0xFE, "INC", 3, 7, AddressingMode::Absolute_X), - - // INY - Increment Y Register - OpCode::new(0xC8, "INY", 1, 2, AddressingMode::NoneAddressing), - - // JMP - Jump - OpCode::new(0x4C, "JMP", 3, 3, AddressingMode::Absolute), - OpCode::new(0x6C, "JMP", 3, 5, AddressingMode::NoneAddressing), //AddressingMode:Indirect with 6502 bug - - // JSR - Jump to Subroutine - OpCode::new(0x20, "JSR", 3, 6, AddressingMode::Absolute), - - // LDX - Load X Register - OpCode::new(0xA2, "LDX", 2, 2, AddressingMode::Immediate), - OpCode::new(0xA6, "LDX", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xB6, "LDX", 2, 4, AddressingMode::ZeroPage_Y), - OpCode::new(0xAE, "LDX", 3, 4, AddressingMode::Absolute), - OpCode::new(0xBE, "LDX", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - - // LDY - Load Y Register - OpCode::new(0xA0, "LDY", 2, 2, AddressingMode::Immediate), - OpCode::new(0xA4, "LDY", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xB4, "LDY", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0xAC, "LDY", 3, 4, AddressingMode::Absolute), - OpCode::new(0xBC, "LDY", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - - // LSR - Logical Shift Right - OpCode::new(0x4A, "LSR", 1, 2, AddressingMode::NoneAddressing), // Accumulator - OpCode::new(0x46, "LSR", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0x56, "LSR", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0x4E, "LSR", 3, 6, AddressingMode::Absolute), - OpCode::new(0x5E, "LSR", 3, 7, AddressingMode::Absolute_X), - - // NOP - No Operation - OpCode::new(0xEA, "NOP", 1, 2, AddressingMode::NoneAddressing), - - // ORA - Logical Inclusive OR - OpCode::new(0x09, "ORA", 2, 2, AddressingMode::Immediate), - OpCode::new(0x05, "ORA", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x15, "ORA", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x0D, "ORA", 3, 4, AddressingMode::Absolute), - OpCode::new(0x1D, "ORA", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0x19, "ORA", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0x01, "ORA", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0x11, "ORA", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - // PHA - Push Accumulator - OpCode::new(0x48, "PHA", 1, 3, AddressingMode::NoneAddressing), - // PHP - Push Processor Status - OpCode::new(0x08, "PHP", 1, 3, AddressingMode::NoneAddressing), - - // PLA - Pull Accumulator - OpCode::new(0x68, "PLA", 1, 4, AddressingMode::NoneAddressing), - // PLP - Pull Processor Status - OpCode::new(0x28, "PLP", 1, 4, AddressingMode::NoneAddressing), - - // ROL - Rotate Left - OpCode::new(0x2A, "ROL", 1, 2, AddressingMode::NoneAddressing), // Accumulator - OpCode::new(0x26, "ROL", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0x36, "ROL", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0x2E, "ROL", 3, 6, AddressingMode::Absolute), - OpCode::new(0x3E, "ROL", 3, 7, AddressingMode::Absolute_X), - - // ROR - Rotate Right - OpCode::new(0x6A, "ROR", 1, 2, AddressingMode::NoneAddressing), // Accumulator - OpCode::new(0x66, "ROR", 2, 5, AddressingMode::ZeroPage), - OpCode::new(0x76, "ROR", 2, 6, AddressingMode::ZeroPage_X), - OpCode::new(0x6E, "ROR", 3, 6, AddressingMode::Absolute), - OpCode::new(0x7E, "ROR", 3, 7, AddressingMode::Absolute_X), - - // RTI - Return from Interrupt - OpCode::new(0x40, "RTI", 1, 6, AddressingMode::NoneAddressing), - // RTS - Return from Subroutine - OpCode::new(0x60, "RTS", 1, 6, AddressingMode::NoneAddressing), - - // SBC - Subtract with Carry - OpCode::new(0xE9, "SBC", 2, 2, AddressingMode::Immediate), - OpCode::new(0xE5, "SBC", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0xF5, "SBC", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0xED, "SBC", 3, 4, AddressingMode::Absolute), - OpCode::new(0xFD, "SBC", 3, 4, AddressingMode::Absolute_X), // +1 if page crossed - OpCode::new(0xF9, "SBC", 3, 4, AddressingMode::Absolute_Y), // +1 if page crossed - OpCode::new(0xE1, "SBC", 2, 6, AddressingMode::Indirect_X), - OpCode::new(0xF1, "SBC", 2, 5, AddressingMode::Indirect_Y), // +1 if page crossed - - // SEC - Set Carry Flag - OpCode::new(0x38, "SEC", 1, 2, AddressingMode::NoneAddressing), - // SED - Set Decimal Flag - OpCode::new(0xF8, "SED", 1, 2, AddressingMode::NoneAddressing), - // SEI - Set Interrupt Disable - OpCode::new(0x78, "SEI", 1, 2, AddressingMode::NoneAddressing), - - // STX - Store X Register - OpCode::new(0x86, "STX", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x96, "STX", 2, 4, AddressingMode::ZeroPage_Y), - OpCode::new(0x8E, "STX", 3, 4, AddressingMode::Absolute), - - // STY - Store Y Register - OpCode::new(0x84, "STY", 2, 3, AddressingMode::ZeroPage), - OpCode::new(0x94, "STY", 2, 4, AddressingMode::ZeroPage_X), - OpCode::new(0x8C, "STY", 3, 4, AddressingMode::Absolute), - - // TXA - Transfer X to Accumulator (já tinha TAX) - OpCode::new(0x8A, "TXA", 1, 2, AddressingMode::NoneAddressing), - // TSX - Transfer Stack Pointer to X - OpCode::new(0xBA, "TSX", 1, 2, AddressingMode::NoneAddressing), - // TXS - Transfer X to Stack Pointer - OpCode::new(0x9A, "TXS", 1, 2, AddressingMode::NoneAddressing), - // TYA - Transfer Y to Accumulator - OpCode::new(0x98, "TYA", 1, 2, AddressingMode::NoneAddressing), - // TAY - Transfer Accumulator to Y - OpCode::new(0xA8, "TAY", 1, 2, AddressingMode::NoneAddressing), - - ]; - opcodes.into_boxed_slice().into() + let json_data = include_str!("archive/6502_all_opcodes.json"); + let raw_opcodes: Vec = serde_json::from_str(json_data).expect("poorly formatted opcodes json"); + + let opcodes: Vec = raw_opcodes + .into_iter() + .map(|raw| { + let code = u8::from_str_radix(raw.opcode.trim_start_matches("$"), 16).unwrap(); + + let mode = match raw.mode.as_str() { + "Immediate" => AddressingMode::Immediate, + "ZeroPage" => AddressingMode::ZeroPage, + "ZeroPage,X" | "ZeroPage_X" => AddressingMode::ZeroPage_X, + "ZeroPage,Y" | "ZeroPage_Y" => AddressingMode::ZeroPage_Y, + "Absolute" => AddressingMode::Absolute, + "Absolute,X" | "Absolute_X" => AddressingMode::Absolute_X, + "Absolute,Y" | "Absolute_Y" => AddressingMode::Absolute_Y, + "Indirect,X" | "Indirect_X" => AddressingMode::Indirect_X, + "Indirect,Y" | "Indirect_Y" => AddressingMode::Indirect_Y, + + "Implied" | "Accumulator" | "Relative" | _ => AddressingMode::NoneAddressing, + }; + + OpCode::new(code, raw.name, raw.bytes, raw.cycles, mode) + }) + .collect(); + Arc::from(opcodes) }) } diff --git a/src/memory/bus.rs b/src/memory/bus.rs index a3fc101..40419ba 100644 --- a/src/memory/bus.rs +++ b/src/memory/bus.rs @@ -189,6 +189,10 @@ impl BUS { self.mem_write(pos + 1, hi); } + pub fn nmi_active(&self) -> bool { + self.ppu.nmi_active() + } + pub fn tick(&mut self, cycles: u8) -> TickResult { self.ppu.tick(cycles as u16 * 3); for _ in 0..cycles { diff --git a/src/ppu/ppu.rs b/src/ppu/ppu.rs index 4fbb193..d9a920b 100644 --- a/src/ppu/ppu.rs +++ b/src/ppu/ppu.rs @@ -172,7 +172,12 @@ impl PPU { match addr & 0x07 { 0x02 => { - let status = (self.status.bits() & 0xE0) | (self.data_buffer & 0x1F); + let mut status = (self.status.bits() & 0xE0) | (self.data_buffer & 0x1F); + + if self.scanline == 240 && self.cycle >= 300 { + status |= 0x80; + } + self.status.remove(PpuStatusFlags::VblankFlag); self.w = false; status @@ -206,7 +211,7 @@ impl PPU { result } - _ => panic!("Program tried to read register ${:?}", (addr & 0x07)), + _ => self.data_buffer } } @@ -266,7 +271,6 @@ impl PPU { } } 0x07 => { - self.ppubus.write_ppubus(self.v.addr, val); if self.ctrl.contains(PpuCtrlFlags::IncrementVRAM) { self.v.addr = self.v.addr.wrapping_add(32) @@ -280,6 +284,10 @@ impl PPU { false } + pub fn nmi_active(&self) -> bool { + self.status.contains(PpuStatusFlags::VblankFlag) && self.ctrl.generate_vblank_nmi() + } + pub fn tick(&mut self, cycles: u16) -> bool { for _ in 0..cycles { self.clock();