A comprehensive and accurate 6502 microprocessor emulator written in Go. This library provides a cycle-accurate implementation of the MOS Technology 6502 CPU, including all official instructions, addressing modes, and many unofficial/illegal opcodes.
go get github.com/drewwalton19216801/sixty502
package main
import (
"fmt"
"github.com/drewwalton19216801/sixty502"
)
// Simple memory implementation
type SimpleBus struct {
ram [65536]uint8
}
func (b *SimpleBus) Read(addr uint16) uint8 {
return b.ram[addr]
}
func (b *SimpleBus) Write(addr uint16, data uint8) {
b.ram[addr] = data
}
func main() {
// Create bus and CPU
bus := &SimpleBus{}
cpu := cpu6502.NewCPU(bus)
// Load a simple program: LDA #$42, STA $0200, BRK
bus.Write(0x8000, 0xA9) // LDA immediate
bus.Write(0x8001, 0x42) // Value $42
bus.Write(0x8002, 0x8D) // STA absolute
bus.Write(0x8003, 0x00) // Low byte of address
bus.Write(0x8004, 0x02) // High byte of address
bus.Write(0x8005, 0x00) // BRK
// Set reset vector
bus.Write(0xFFFC, 0x00) // Reset vector low
bus.Write(0xFFFD, 0x80) // Reset vector high
// Reset and run
cpu.Reset()
// Execute until BRK
for cpu.Cycles > 0 {
cpu.Clock()
}
fmt.Printf("CPU State: %s\n", cpu.GetState())
fmt.Printf("Value at $0200: $%02X\n", bus.Read(0x0200))
}
The CPU communicates with memory through a simple Bus interface:
type Bus interface {
Read(addr uint16) uint8
Write(addr uint16, data uint8)
}
This design allows for flexible memory implementations, from simple RAM to complex memory-mapped I/O systems.
Instructions are defined using method expressions for efficient dispatch:
type Instruction struct {
Name string // Mnemonic (e.g., "LDA")
Operate func(*CPU) uint8 // Instruction logic
AddrMode func(*CPU) uint8 // Addressing mode calculation
Cycles uint8 // Base cycle count
Length uint8 // Instruction length in bytes
Illegal bool // Unofficial opcode flag
}
All 13 addressing modes are implemented:
The library includes comprehensive tests covering:
Run the test suite:
go test -v
The emulator supports BCD (Binary Coded Decimal) arithmetic:
cpu.setFlag(cpu6502.D, true) // Enable decimal mode
// ADC and SBC will now perform BCD arithmetic
Full interrupt support with proper vector handling:
cpu.InterruptRequest() // Handle IRQ
cpu.NonMaskableInterrupt() // Handle NMI
Built-in disassembler for code analysis:
disassembly := cpu.Disassemble(0x8000, 0x8010)
for addr, line := range disassembly {
fmt.Printf("$%04X: %s\n", addr, line)
}
Comprehensive state inspection methods:
fmt.Println(cpu.GetState()) // Human-readable state
fmt.Printf("Flags: %s\n", cpu6502.FormatFlags(cpu.P))
fmt.Printf("Total cycles: %d\n", cpu.TotalCycles())
The emulator is designed for accuracy over raw speed, but still provides good performance:
This emulator is designed to be compatible with:
Contributions are welcome! Areas for improvement include:
This project is licensed under the MIT License - see the LICENSE file for details.
This emulator is based on extensive research of the 6502 architecture and behavior. Special thanks to the 6502 community for documentation and testing resources.