sixty502

Sixty502 - 6502 CPU Emulator

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.

Features

Core CPU Implementation

Architecture

Debugging & Development Tools

Installation

go get github.com/drewwalton19216801/sixty502

Quick Start

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))
}

Architecture Overview

Bus Interface

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.

Instruction System

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
}

Addressing Modes

All 13 addressing modes are implemented:

Testing

The library includes comprehensive tests covering:

Run the test suite:

go test -v

Advanced Features

Decimal Mode

The emulator supports BCD (Binary Coded Decimal) arithmetic:

cpu.setFlag(cpu6502.D, true) // Enable decimal mode
// ADC and SBC will now perform BCD arithmetic

Interrupt Handling

Full interrupt support with proper vector handling:

cpu.InterruptRequest()     // Handle IRQ
cpu.NonMaskableInterrupt() // Handle NMI

Disassembly

Built-in disassembler for code analysis:

disassembly := cpu.Disassemble(0x8000, 0x8010)
for addr, line := range disassembly {
    fmt.Printf("$%04X: %s\n", addr, line)
}

State Inspection

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())

Performance

The emulator is designed for accuracy over raw speed, but still provides good performance:

Compatibility

This emulator is designed to be compatible with:

Contributing

Contributions are welcome! Areas for improvement include:

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

This emulator is based on extensive research of the 6502 architecture and behavior. Special thanks to the 6502 community for documentation and testing resources.