### Go: Example of creating CPU with custom config Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Illustrates creating a CPU with a custom configuration. It starts with default settings, modifies the variant to Ricoh2A03, enables strict mode, and then builds the CPU. ```go config := cpu6502.DefaultConfig() config.Variant = cpu6502.VariantRicoh2A03 config.StrictMode = true cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Run Basic and Memory-Mapped I/O Examples (Bash) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/README.md These commands demonstrate how to run pre-built examples for the 6502 emulator. The 'basic' example shows simple CPU usage, while 'memory-mapped' illustrates I/O port interactions. Navigate to the example directory and run `go run main.go`. ```bash # Basic example - simple program execution cd examples/basic go run main.go # Memory-mapped I/O example cd examples/memory-mapped go run main.go ``` -------------------------------- ### Go 6502 CPU Emulation Quick Start Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md This Go code snippet demonstrates how to set up and run a simple 6502 CPU emulation using the sixty502 library. It includes defining a basic memory bus, initializing the CPU, loading a minimal program, and executing it for a set number of cycles. This example requires the sixty502 library to be imported. ```go package main import ( "log" "github.com/yourusername/sixty502" ) 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 program bus.Write(0x8000, 0xA9) // LDA #$42 bus.Write(0x8001, 0x42) bus.Write(0x8002, 0x00) // BRK // Set reset vector bus.Write(0xFFFC, 0x00) bus.Write(0xFFFD, 0x80) // Reset and run cpu.Reset() for i := 0; i < 100; i++ { if err := cpu.Clock(); err != nil { log.Printf("Error: %v", err) break } } } ``` -------------------------------- ### Choosing 6502 CPU Error Handlers for Development and Production Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/error-handling.md This example shows how to select appropriate error handlers for different environments. It contrasts a strict mode for development with a lenient mode for production, and demonstrates using a custom handler for testing. ```go // Development: Strict mode devCPU := cpu6502.NewBuilder(bus). WithStrictMode(). Build() // Production: Lenient mode prodCPU := cpu6502.NewBuilder(bus). WithErrorHandler(&cpu6502.LoggingErrorHandler{}). Build() // Testing: Custom handler testCPU := cpu6502.NewBuilder(bus). WithErrorHandler(&TestErrorHandler{t: t}). Build() ``` -------------------------------- ### CPU Profiling with Go pprof Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md Demonstrates how to use Go's built-in pprof tool to profile the CPU usage of the sixty502 emulator. This involves starting the CPU profiler before running emulation and stopping it afterward, then analyzing the generated profile file. ```go import ( "os" "runtime/pprof" ) func main() { // Start CPU profiling f, _ := os.Create("cpu.prof") pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() // Run your emulation runEmulation() } ``` ```bash go tool pprof cpu.prof ``` -------------------------------- ### Configure CPU Variant in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Example of setting a specific CPU variant (CMOS 65C02) for the sixty502 emulator and creating a new CPU instance with this configuration. This affects instruction behavior and bug emulation. ```go config := cpu6502.DefaultConfig() config.Variant = cpu6502.VariantCMOS65C02 cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Configure 6502 CPU with Custom Error Handler and Variant (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md An example of configuring the 6502 CPU for NES emulation, specifying the Ricoh 2A03 variant and a custom error handler. This configuration prioritizes lenient error handling for potential illegal opcodes used in some games, while ensuring the correct CPU variant is used. It also includes comments documenting the setup. ```go // NES CPU configuration // - Ricoh 2A03 variant (no decimal mode) // - Lenient error handling (some games use illegal opcodes) // - Instruction cache enabled (tight loops in games) cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantRicoh2A03). WithErrorHandler(&NESErrorHandler{}). Build() ``` -------------------------------- ### Documenting 6502 Emulator Error Behavior Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/error-handling.md This example shows how to document the error handling strategy of an emulator. Clear documentation helps users understand how the emulator behaves with different types of errors, such as allowing illegal opcodes but halting on invalid CPU states. ```go // MyEmulator uses lenient error handling for illegal opcodes // commonly found in commercial games, but halts on invalid // CPU state to prevent corruption. type MyEmulator struct { cpu *cpu6502.CPU } func NewMyEmulator() *MyEmulator { handler := &SelectiveErrorHandler{ allowIllegalOpcodes: true, } return &MyEmulator{ cpu: cpu6502.NewCPUWithErrorHandler(bus, handler), } } ``` -------------------------------- ### Manage 6502 CPU Instruction Cache at Runtime (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Provides examples of runtime management for the 6502 CPU's instruction cache. Includes disabling, enabling, invalidating the cache, and retrieving performance statistics like cache hits, misses, and hit rate. Essential for fine-tuning performance and handling self-modifying code. ```go // Disable cache cpu.DisableInstructionCache() // Enable cache cpu.EnableInstructionCache() // Invalidate cache after loading new code cpu.InvalidateInstructionCache() // Check cache performance hits, misses, rate := cpu.InstructionCacheStats() ``` -------------------------------- ### Get Default CPU Configuration in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Retrieves the default configuration for the sixty502 emulator. This function returns a CPUConfig struct with sensible default values for all options. ```go func DefaultConfig() CPUConfig ``` -------------------------------- ### Initialize and Run 6502 CPU (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Demonstrates the basic initialization of a 6502 CPU with a bus and running it in a loop until an error occurs. This is the fundamental way to start and operate the emulator. ```go cpu := cpu6502.NewCPU(bus) cpu.Reset() for { if err := cpu.Clock(); err != nil { break } } ``` -------------------------------- ### Minimize State Inspection Overhead Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md Provides examples of minimizing the overhead associated with inspecting the CPU state in the sixty502 emulator. Frequent calls to state inspection methods can be inefficient due to memory allocation. ```go // Less efficient - frequent state checks for i := 0; i < 1000000; i++ { cpu.Clock() state := cpu.GetStateSnapshot() // Allocates memory logState(state) } ``` ```go // More efficient - periodic checks for i := 0; i < 1000000; i++ { cpu.Clock() if i%1000 == 0 { state := cpu.GetStateSnapshot() logState(state) } } ``` -------------------------------- ### Go: Example of calculating elapsed CPU cycles Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Shows how to measure the number of CPU cycles elapsed between two points in execution. It records the starting cycle count, performs some operations, and then calculates the difference. ```go start := cpu.TotalCycles() // ... execute code ... elapsed := cpu.TotalCycles() - start fmt.Printf("Executed %d cycles\n", elapsed) ``` -------------------------------- ### Implement Custom Error Handler in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Shows how to create and use a custom error handler for the sixty502 emulator. This example logs illegal opcodes but continues execution, returning the error for other types. ```go type MyErrorHandler struct{} func (h *MyErrorHandler) HandleError(err *cpu6502.CPUError) error { if err.Type == cpu6502.ErrorIllegalOpcode { log.Printf("Illegal opcode $%02X at $%04X", err.Opcode, err.PC) return nil // Continue execution } return err // Halt on other errors } config.ErrorHandler = &MyErrorHandler{} ``` -------------------------------- ### Create CPU with Default Configuration in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Creates a new sixty502 CPU instance using the default configuration settings. This is the simplest way to initialize the emulator. ```go cpu := cpu6502.NewCPU(bus) ``` -------------------------------- ### Complete 6502 CPU Example in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md A full Go example demonstrating the usage of the sixty502 CPU. It includes setting up a SimpleBus, initializing the CPU, loading a simple program (LDA, STA, BRK), setting the reset vector, and running the CPU in a loop. The output shows the CPU state and the value stored in memory. ```go package main import ( "fmt" "log" "github.com/yourusername/sixty502" ) 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 program: LDA #$42, STA $0200, BRK bus.Write(0x8000, 0xA9) // LDA #$42 bus.Write(0x8001, 0x42) bus.Write(0x8002, 0x8D) // STA $0200 bus.Write(0x8003, 0x00) bus.Write(0x8004, 0x02) bus.Write(0x8005, 0x00) // BRK // Set reset vector bus.Write(0xFFFC, 0x00) bus.Write(0xFFFD, 0x80) // Reset and run cpu.Reset() for i := 0; i < 100; i++ { if err := cpu.Clock(); err != nil { log.Printf("Error: %v", err) break } if cpu.RemainingCycles() == 0 { fmt.Println(cpu.GetState()) } } fmt.Printf("Value at $0200: $%02X\n", bus.Read(0x0200)) } ``` -------------------------------- ### Enable Strict Mode for CPU in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Example of enabling StrictMode for the sixty502 emulator, which forces execution to halt on illegal opcodes, overriding the configured error handler. A new CPU instance is created with this setting. ```go config := cpu6502.DefaultConfig() config.StrictMode = true cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Benchmark 6502 CPU Clock Cycles in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md This Go code snippet demonstrates how to benchmark the CPU's clock cycle performance using Go's built-in testing framework. It sets up a simple 6502 CPU and bus, loads a basic program, and then runs the `cpu.Clock()` function within the benchmark loop. The `b.ResetTimer()` call ensures accurate timing by excluding setup costs. ```go func BenchmarkCPUClock(b *testing.B) { bus := &SimpleBus{} cpu := cpu6502.NewCPU(bus) // Load a simple program bus.Write(0x8000, 0xEA) // NOP bus.Write(0x8001, 0x4C) // JMP $8000 bus.Write(0x8002, 0x00) bus.Write(0x8003, 0x80) bus.Write(0xFFFC, 0x00) bus.Write(0xFFFD, 0x80) cpu.Reset() b.ResetTimer() for i := 0; i < b.N; i++ { cpu.Clock() } } ``` -------------------------------- ### Install Sixty502 6502 CPU Emulator Source: https://github.com/drewwalton19216801/sixty502/blob/dev/README.md Command to install the Sixty502 library using Go modules. This command fetches the latest version of the library and adds it to your project's dependencies. ```bash go get github.com/drewwalton19216801/sixty502 ``` -------------------------------- ### Configure 6502 CPU with Strict Mode for Development (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md A concise example of configuring the 6502 CPU with strict mode enabled using the builder pattern. This is a best practice during development to catch illegal opcodes and other instruction set violations early. It helps ensure code correctness. ```go cpu := cpu6502.NewBuilder(bus). WithStrictMode(). Build() ``` -------------------------------- ### Handle CPU Errors in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/error-handling.md Provides an example of how to check for and handle a CPUError returned from a CPU operation. It demonstrates type assertion to specifically identify and process CPU-specific errors, extracting details like PC and Opcode. ```Go if err := cpu.Clock(); err != nil { if cpuErr, ok := err.(*cpu6502.CPUError); ok { fmt.Printf("Error at $%04X: %s (opcode $%02X)\n", cpuErr.PC, cpuErr.Message, cpuErr.Opcode) } } ``` -------------------------------- ### Go: Example of creating and resetting CPU Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Demonstrates creating a new CPU with a SimpleBus and then resetting it to its initial power-on state. The reset vector is often set before calling Reset. ```go bus := &SimpleBus{} cpu := cpu6502.NewCPU(bus) cpu.Reset() ``` -------------------------------- ### Configure 6502 CPU for Maximum Performance (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Optimizes the 6502 CPU configuration for maximum performance, leveraging the Ricoh 2A03 variant. This variant inherently disables decimal mode, reducing overhead. This setup is ideal for performance-critical applications where speed is paramount. ```go cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantRicoh2A03). // No decimal mode overhead Build() ``` -------------------------------- ### Emulate Apple II System (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Example of initializing the 6502 CPU emulator for an Apple II system, specifying the NMOS6502 variant and noting its typical clock speed. ```go cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantNMOS6502) // Apple II runs at ~1.023 MHz ``` -------------------------------- ### Go: Example of using CPU Builder Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Demonstrates the fluent usage of the `CPUBuilder` to configure a CPU with specific settings. It chains methods like `WithVariant`, `WithStrictMode`, and `DisableDecimalMode` before building the final CPU object. ```go cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantCMOS65C02). WithStrictMode(). DisableDecimalMode(). Build() ``` -------------------------------- ### Configure 6502 CPU for Apple II Emulation (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Example of configuring a 6502 CPU specifically for Apple II emulation using the builder pattern. It sets the CPU variant to NMOS 6502, which is common for the Apple II. This snippet showcases a basic builder configuration. ```go cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantNMOS6502). Build() ``` -------------------------------- ### Go: CPU Builder pattern Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Provides a fluent interface for configuring a CPU using the builder pattern. This allows chaining configuration methods for a more readable CPU setup. ```go func NewBuilder(bus Bus) *CPUBuilder ``` -------------------------------- ### Go: Example of setting reset vector and resetting CPU Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Shows how to manually write the reset vector addresses ($FFFC/$FFFD) and then call `cpu.Reset()`. After reset, the program counter (PC) will be initialized from this vector. ```go bus.Write(0xFFFC, 0x00) // Reset vector low byte bus.Write(0xFFFD, 0x80) // Reset vector high byte cpu.Reset() // PC now = $8000 ``` -------------------------------- ### Illegal NOPs (Immediate) Examples Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example lists various immediate illegal NOP opcodes supported by the emulator. ```assembly *NOP #$80 ; Immediate NOPs: $80, $82, $89, $C2, $E2 ``` -------------------------------- ### JSR - Jump to Subroutine Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the JSR instruction, which pushes the return address onto the stack and then jumps to a subroutine. ```assembly JSR subroutine_label ; Call subroutine at subroutine_label ; Code continues here after RTS ``` -------------------------------- ### Memory Profiling with Go pprof Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md Shows how to profile memory allocations of the sixty502 emulator using Go's pprof tool. This involves running the emulation and then writing the heap profile to a file for analysis. ```go import ( "os" "runtime/pprof" ) func main() { runEmulation() // Write memory profile f, _ := os.Create("mem.prof") pprof.WriteHeapProfile(f) f.Close() } ``` ```bash go tool pprof mem.prof ``` -------------------------------- ### Emulate Nintendo Entertainment System (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Example of setting up the 6502 CPU emulator for a Nintendo Entertainment System (NES), using the specific Ricoh2A03 variant and its standard NTSC clock speed. ```go cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantRicoh2A03) // NES runs at ~1.789773 MHz (NTSC) ``` -------------------------------- ### Directly Configure CPU Options in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Shows how to modify specific fields of a CPUConfig struct after obtaining the default configuration. This allows for fine-grained control over emulator settings before creating a new CPU instance. ```go config := cpu6502.DefaultConfig() config.Variant = cpu6502.VariantCMOS65C02 config.StrictMode = true cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Configure Strict Error Handling in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Demonstrates how to set the StrictErrorHandler for the sixty502 emulator, which halts execution on any error. A new CPU instance is created with this handler. ```go config := cpu6502.DefaultConfig() config.ErrorHandler = &cpu6502.StrictErrorHandler{} cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Go: Example of continuously clocking the CPU Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Provides an example of a loop that repeatedly calls `cpu.Clock()` to execute instructions until an error occurs or the program terminates. Errors are logged, and the loop breaks. ```go for { if err := cpu.Clock(); err != nil { log.Printf("CPU error: %v", err) break } } ``` -------------------------------- ### Illegal NOPs (Zero Page,X) Examples Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example lists various zero page,X illegal NOP opcodes supported by the emulator. ```assembly *NOP $14,X ; Zero Page,X NOPs: $14, $34, $54, $74, $D4, $F4 ``` -------------------------------- ### Go: Example of executing a full instruction Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Demonstrates how to ensure a complete instruction is executed by repeatedly calling `cpu.Clock()` until `RemainingCycles()` returns 0. This is useful for precise instruction timing. ```go // Execute one complete instruction for cpu.RemainingCycles() > 0 { cpu.Clock() } ``` -------------------------------- ### Use Default CPU Configuration Values in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Illustrates the default configuration values returned by the DefaultConfig() function for the sixty502 emulator. This includes the NMOS 6502 variant and logging error handler. ```go CPUConfig{ Variant: VariantNMOS6502, ErrorHandler: &LoggingErrorHandler{Logger: log.Default()}, StrictMode: false, EnableDecimalMode: true, EnableInstructionCache: true, InstructionCacheSize: 256, } ``` -------------------------------- ### Go: SimpleBus implementation for Bus interface Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md A basic implementation of the Bus interface using a fixed-size array for RAM. This serves as a straightforward example for memory management. ```go 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 } ``` -------------------------------- ### Disable Instruction Cache for CPU in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Example of disabling the instruction cache in the sixty502 emulator for performance optimization. This is recommended when dealing with self-modifying code. A new CPU instance is created. ```go config := cpu6502.DefaultConfig() config.EnableInstructionCache = false cpu := cpu6502.NewCPUWithConfig(bus, config) ``` -------------------------------- ### Create CPU with Custom Error Handler in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Constructs a new sixty502 CPU instance, specifying a custom error handler while keeping other configuration options at their defaults. This allows for tailored error management during emulation. ```go handler := &MyErrorHandler{} cpu := cpu6502.NewCPUWithErrorHandler(bus, handler) ``` -------------------------------- ### Quick Start: Run a 6502 Program with Sixty502 in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/README.md A Go program demonstrating how to use the Sixty502 emulator. It includes a simple memory bus implementation, CPU initialization, loading a small program into memory, executing it, and inspecting the results. ```go 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 (defaults to NMOS 6502) 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 instruction completes for cpu.RemainingCycles() > 0 { cpu.Clock() } // Inspect CPU state state := cpu.GetStateSnapshot() fmt.Printf("CPU State: %s\n", state) fmt.Printf("Value at $0200: $%02X\n", bus.Read(0x0200)) } ``` -------------------------------- ### Define CPUConfig Structure in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Defines the structure for configuring the 6502 CPU emulator, including variant, error handling, strict mode, decimal mode, and instruction caching. ```go type CPUConfig struct { Variant CPUVariant ErrorHandler ErrorHandler StrictMode bool EnableDecimalMode bool EnableInstructionCache bool InstructionCacheSize int } ``` -------------------------------- ### Go Code Demonstrating Page Boundary Crossing Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md This Go code illustrates the concept of page boundary crossing in memory access, which can affect performance. The first example shows a write operation that does not cross a page boundary, resulting in faster execution. The second example demonstrates a write operation that crosses a page boundary, incurring additional overhead and taking longer. ```go // No page cross - faster bus.Write(0x1000, 0xBD) // LDA $1020,X bus.Write(0x1001, 0x20) bus.Write(0x1002, 0x10) cpu.X = 0x10 // Result: $1030 (same page) // Page cross - slower cpu.X = 0xF0 // Result: $1110 (different page) ``` -------------------------------- ### Running and Comparing Go Benchmarks Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md This section outlines how to execute and analyze performance benchmarks for Go programs. It includes commands to run all benchmarks, specific benchmarks, and to compare benchmark results before and after code changes using the `benchstat` tool. ```bash # Run all benchmarks go test -bench=. -benchmem # Run specific benchmark go test -bench=BenchmarkCPUClock -benchtime=10s # Compare before/after go test -bench=. > before.txt # Make changes go test -bench=. > after.txt benchstat before.txt after.txt ``` -------------------------------- ### PHP - Push Processor Status Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This code snippet shows the PHP instruction, which pushes the current state of the Processor Status Register (P) onto the stack. ```assembly PHP ; Push the Processor Status Register onto the stack ``` -------------------------------- ### Run Go Tests and Benchmarks Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Provides command-line instructions for running tests, measuring code coverage, executing benchmarks, and running specific test cases within the Sixty502 project using Go's built-in testing tools. ```bash # Run all tests go test -v # Run with coverage go test -cover # Run benchmarks go test -bench=. # Run specific test go test -run TestCPUBasic ``` -------------------------------- ### Configure 6502 CPU Instances (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/README.md This Go code demonstrates various ways to create and configure a 6502 CPU instance, including simple creation with defaults, specifying CPU variants, using a full configuration struct, and employing a builder pattern for fluent setup. ```go // Simple creation with defaults (NMOS 6502) cpu := cpu6502.NewCPU(bus) // Specify variant cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantRicoh2A03) // Full configuration config := cpu6502.DefaultConfig() config.Variant = cpu6502.VariantCMOS65C02 config.StrictMode = true // Halt on illegal opcodes config.EnableDecimalMode = false cpu := cpu6502.NewCPUWithConfig(bus, config) // Builder pattern for fluent configuration cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantCMOS65C02). WithStrictMode(). DisableDecimalMode(). Build() ``` -------------------------------- ### Enable Instruction Cache in sixty502 Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/performance.md Demonstrates how to enable and monitor the instruction cache in the sixty502 emulator. The cache is enabled by default but can be explicitly configured. It offers a 5-15% performance improvement for code with loops. ```go // Cache is enabled by default cpu := cpu6502.NewCPU(bus) // Or explicitly enable via configuration config := cpu6502.DefaultConfig() config.EnableInstructionCache = true cpu := cpu6502.NewCPUWithConfig(bus, config) // Monitor cache performance hits, misses, hitRate := cpu.InstructionCacheStats() fmt.Printf("Cache hit rate: %.2f%%\n", hitRate*100) ``` -------------------------------- ### Initialize 6502 CPU with Variant Selection (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Shows how to create a 6502 CPU instance specifying a particular variant, such as the CMOS65C02. This allows for emulating different versions of the 6502 processor. ```go cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantCMOS65C02) cpu.Reset() ``` -------------------------------- ### Initialize and Execute 6502 CPU with Basic Program (Go) Source: https://context7.com/drewwalton19216801/sixty502/llms.txt Initializes a 6502 CPU and executes a simple program loaded into memory. The program loads a value, stores it, and then halts with a BRK instruction. It demonstrates setting up the bus, loading the program, configuring the reset vector, and stepping through CPU cycles. ```go package main import ( "fmt" "log" cpu6502 "github.com/drewwalton19216801/sixty502" ) 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() { bus := &SimpleBus{} cpu := cpu6502.NewCPU(bus) // Load a simple program: LDA #$42, STA $0200, BRK program := []uint8{ 0xA9, 0x42, // LDA #$42 (Load 0x42 into accumulator) 0x8D, 0x00, 0x02, // STA $0200 (Store accumulator at $0200) 0x00, // BRK (Break/halt) } // Load program at $8000 for i, b := range program { bus.Write(0x8000+uint16(i), b) } // Set reset vector to point to program start bus.Write(0xFFFC, 0x00) // Low byte bus.Write(0xFFFD, 0x80) // High byte -> PC = $8000 // Set BRK/IRQ vector bus.Write(0xFFFE, 0x00) bus.Write(0xFFFF, 0xFF) // Reset CPU (loads PC from reset vector) cpu.Reset() fmt.Printf("After reset: %s\n", cpu.GetState()) // Execute reset cycles for cpu.RemainingCycles() > 0 { cpu.Clock() } // Execute program until BRK maxCycles := 1000 for i := 0; i < maxCycles; i++ { if err := cpu.Clock(); err != nil { log.Printf("Error: %v\n", err) break } // Check for BRK instruction if cpu.RemainingCycles() == 0 && cpu.CurrentOpcode() == 0x00 { fmt.Println("BRK instruction reached") break } } // Inspect results state := cpu.GetStateSnapshot() fmt.Printf("Final state: %s\n", state) fmt.Printf("Value at $0200: $%02X\n", bus.Read(0x0200)) fmt.Printf("Total cycles: %d\n", cpu.TotalCycles()) } ``` -------------------------------- ### Manage Interrupts for 6502 CPU (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Provides examples of how to trigger Non-Maskable Interrupts (NMI) and Maskable Interrupts (IRQ) on the 6502 CPU, as well as how to check for pending interrupts. This is crucial for simulating system behavior. ```go // Trigger NMI cpu.SetNMI(true) cpu.SetNMI(false) // Falling edge // Assert IRQ cpu.SetIRQ(true) // Check for pending interrupts if cpu.HasPendingInterrupt() { fmt.Println("Interrupt pending") } ``` -------------------------------- ### Initialize 6502 CPU with Builder Pattern (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Demonstrates creating a 6502 CPU instance using the builder pattern for fluent configuration. This method allows setting various CPU properties like variant, strict mode, and cache settings before building the final CPU object. It requires a bus instance as input. ```go cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantCMOS65C02). WithStrictMode(). DisableDecimalMode(). DisableInstructionCache(). Build() ``` -------------------------------- ### Initialize 6502 CPU with Specific Variant (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Provides methods for initializing the 6502 CPU with a specific variant using `NewCPUWithVariant`. This is useful for ensuring accurate emulation of target hardware like the Apple IIc (CMOS65C02) or NES (Ricoh2A03). It requires the bus and the desired variant. ```go // For Apple IIc cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantCMOS65C02) // For NES cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantRicoh2A03) ``` -------------------------------- ### Modify 6502 CPU Flags at Runtime (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Shows how to directly access and modify the 6502 CPU's status register flags at runtime using bitwise operations. Examples include enabling decimal mode, disabling interrupts, and clearing the carry flag. This offers fine-grained control over CPU state. ```go // Enable decimal mode cpu.P |= cpu6502.D // Disable interrupts cpu.P |= cpu6502.I // Clear carry flag cpu.P &^= cpu6502.C ``` -------------------------------- ### Create and Configure 6502 CPU Instances in Go Source: https://context7.com/drewwalton19216801/sixty502/llms.txt Demonstrates various methods for creating and configuring 6502 CPU instances using the Sixty502 library in Go. Includes basic instantiation, using specific variants, the builder pattern, and advanced configuration with CPUConfig. A SimpleBus implementation is provided for memory access. ```go package main import ( "fmt" cpu6502 "github.com/drewwalton19216801/sixty502" ) // SimpleBus implements the Bus interface with 64KB RAM 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 with default config (NMOS 6502) bus := &SimpleBus{} cpu := cpu6502.NewCPU(bus) // Configure CPU with specific variant cpu2 := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantCMOS65C02) // Full configuration with builder pattern cpu3 := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantRicoh2A03). WithStrictMode(). DisableDecimalMode(). Build() // Advanced configuration with CPUConfig config := cpu6502.DefaultConfig() config.Variant = cpu6502.VariantCMOS65C02 config.StrictMode = true config.EnableInstructionCache = true cpu4 := cpu6502.NewCPUWithConfig(bus, config) fmt.Printf("Created %d CPU instances\n", 4) fmt.Printf("CPU1 variant: %s\n", cpu.Variant()) fmt.Printf("CPU2 variant: %s\n", cpu2.Variant()) fmt.Printf("CPU3 variant: %s\n", cpu3.Variant()) fmt.Printf("CPU4 variant: %s\n", cpu4.Variant()) } ``` -------------------------------- ### Detecting 6502 Page Boundary Crossings in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/troubleshooting.md This Go code snippet provides a function `willCrossPage` to determine if a memory access will cross a 256-byte page boundary, which affects instruction cycle counts on the 6502. It also includes a basic structure `PageCrossMonitor` for monitoring bus accesses and demonstrates a usage example. Understanding page crossing is vital for accurate 6502 timing. ```go package main import "fmt" // SimpleBus is a placeholder for a memory bus implementation type SimpleBus struct{} func (bus *SimpleBus) Read(addr uint16) uint8 { // Placeholder implementation return 0 } func (bus *SimpleBus) Write(addr uint16, data uint8) { // Placeholder implementation } // Monitor page crossings type PageCrossMonitor struct { bus *SimpleBus crosses int } func (m *PageCrossMonitor) Read(addr uint16) uint8 { return m.bus.Read(addr) } func (m *PageCrossMonitor) Write(addr uint16, data uint8) { m.bus.Write(addr, data) } // Check if instruction will cross page func willCrossPage(base uint16, index uint8) bool { result := base + uint16(index) return (base & 0xFF00) != (result & 0xFF00) } func main() { // Test page crossing baseAddr := uint16(0x10FF) index := uint8(0x01) if willCrossPage(baseAddr, index) { fmt.Println("This access will cross page boundary") } baseAddr = uint16(0x1000) index = uint8(0x01) if !willCrossPage(baseAddr, index) { fmt.Println("This access will NOT cross page boundary") } } ``` -------------------------------- ### PLA - Pull Accumulator Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the PLA instruction, which pulls a value from the stack into the Accumulator (A). ```assembly PLA ; Pull a value from the stack into register A ``` -------------------------------- ### Create a Custom 6502 CPU Example (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/README.md This Go code snippet demonstrates how to create your own 6502 programs using the emulator. It involves implementing the `Bus` interface, creating a CPU instance, setting the reset vector, and then executing the program by clocking the CPU. ```go // 1. Implement the Bus interface type MyBus struct { ram [65536]uint8 } func (b *MyBus) Read(addr uint16) uint8 { return b.ram[addr] } func (b *MyBus) Write(addr uint16, data uint8) { b.ram[addr] = data } // 2. Create CPU and load program bus := &MyBus{} cpu := cpu6502.NewCPU(bus) // 3. Set reset vector and reset CPU bus.Write(0xFFFC, 0x00) bus.Write(0xFFFD, 0x80) cpu.Reset() // 4. Execute for cpu.RemainingCycles() > 0 { cpu.Clock() } ``` -------------------------------- ### Create CPU with Variant and Error Handler in Go Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Initializes a new sixty502 CPU instance, allowing both the CPU variant and a custom error handler to be specified simultaneously. This provides flexibility in configuring the emulator's core behavior. ```go cpu := cpu6502.NewCPUWithVariantAndErrorHandler(bus, cpu6502.VariantCMOS65C02, &MyErrorHandler{}) ``` -------------------------------- ### Illegal NOPs (Implied) Examples Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example lists various implied illegal NOP opcodes supported by the emulator. ```assembly *NOP ; Implied NOPs: $1A, $3A, $5A, $7A, $DA, $FA ``` -------------------------------- ### Illegal NOP (Absolute) Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example shows the absolute addressing mode for an illegal NOP opcode supported by the emulator. ```assembly *NOP $0C ; Absolute NOP ``` -------------------------------- ### Go: Create CPU with default configuration Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/api-reference.md Creates a new 6502 CPU instance with default settings, including the NMOS 6502 variant and logging error handler. A Bus object is required for memory access. ```go func NewCPU(bus Bus) *CPU ``` -------------------------------- ### SEC - Set Carry Flag Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the SEC instruction, which sets the Carry flag (C) to 1. ```assembly SEC ; Set the Carry flag (C=1) ``` -------------------------------- ### CLC - Clear Carry Flag Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the CLC instruction, which resets the Carry flag (C) to 0. ```assembly CLC ; Clear the Carry flag (C=0) ``` -------------------------------- ### PHA - Push Accumulator Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the PHA instruction, which pushes the current value of the Accumulator (A) onto the stack. ```assembly PHA ; Push the value of register A onto the stack ``` -------------------------------- ### Illegal NOPs (Zero Page) Examples Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example lists various zero page illegal NOP opcodes supported by the emulator. ```assembly *NOP $04 ; Zero Page NOPs: $04, $44, $64 ``` -------------------------------- ### Emulate Apple IIc System (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Demonstrates initializing the 6502 CPU emulator for an Apple IIc, utilizing the CMOS65C02 variant and its typical operating frequency. ```go cpu := cpu6502.NewCPUWithVariant(bus, cpu6502.VariantCMOS65C02) // Apple IIc runs at ~1.023 MHz ``` -------------------------------- ### Implement 6502 Memory-Mapped I/O Bus (Go) Source: https://context7.com/drewwalton19216801/sixty502/llms.txt Implements a custom bus for the 6502 CPU that separates ROM, RAM, and memory-mapped I/O ports. This example demonstrates writing to an I/O port which captures output, simulating interaction with external devices. It includes a program that outputs the string 'HELLO'. ```go package main import ( "fmt" cpu6502 "github.com/drewwalton19216801/sixty502" ) // MemoryMappedBus implements ROM/RAM/IO separation type MemoryMappedBus struct { ram [0x6000]uint8 // RAM: $0000-$5FFF io [0x2000]uint8 // I/O: $6000-$7FFF rom [0x8000]uint8 // ROM: $8000-$FFFF output []uint8 // Captured output } func (b *MemoryMappedBus) Read(addr uint16) uint8 { switch { case addr < 0x6000: return b.ram[addr] case addr < 0x8000: // Memory-mapped I/O read return b.io[addr-0x6000] default: // ROM area return b.rom[addr-0x8000] } } func (b *MemoryMappedBus) Write(addr uint16, data uint8) { switch { case addr < 0x6000: b.ram[addr] = data case addr < 0x8000: // Memory-mapped I/O write b.io[addr-0x6000] = data // Output port at $6000 if addr == 0x6000 { b.output = append(b.output, data) if data >= 0x20 && data < 0x7F { fmt.Printf("I/O: '%c'\n", data) } } default: // ROM writes ignored } } func main() { bus := &MemoryMappedBus{} cpu := cpu6502.NewCPU(bus) // Program outputs 'HELLO' to I/O port program := []uint8{ 0xA9, 0x48, 0x8D, 0x00, 0x60, // LDA #'H', STA $6000 0xA9, 0x45, 0x8D, 0x00, 0x60, // LDA #'E', STA $6000 0xA9, 0x4C, 0x8D, 0x00, 0x60, // LDA #'L', STA $6000 0xA9, 0x4C, 0x8D, 0x00, 0x60, // LDA #'L', STA $6000 0xA9, 0x4F, 0x8D, 0x00, 0x60, // LDA #'O', STA $6000 0x00, // BRK } copy(bus.rom[:], program) bus.rom[0x7FFC] = 0x00 // Reset vector low bus.rom[0x7FFD] = 0x80 // Reset vector high cpu.Reset() for cpu.RemainingCycles() > 0 { cpu.Clock() } // Execute until BRK for i := 0; i < 1000; i++ { cpu.Clock() if cpu.RemainingCycles() == 0 && cpu.CurrentOpcode() == 0x00 { break } } fmt.Printf("\nOutput captured: %s\n", string(bus.output)) } ``` -------------------------------- ### JMP Absolute Addressing Mode Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the JMP instruction using absolute addressing mode to jump to a specific memory address. ```assembly JMP $1234 ; Jump to address 1234 ``` -------------------------------- ### Emulate Commodore 64 System (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Shows the initialization of the 6502 CPU emulator for a Commodore 64, using the default NMOS 6502 variant and mentioning its common clock frequencies. ```go cpu := cpu6502.NewCPU(bus) // Default NMOS 6502 // C64 runs at ~1.023 MHz (NTSC) or ~0.985 MHz (PAL) ``` -------------------------------- ### BVC - Branch if Overflow Clear Assembly Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example shows the BVC instruction, which branches to a specified label if the Overflow flag (V) is 0. ```assembly BVC overflow_clear_label ; Branch to overflow_clear_label if V=0 ``` -------------------------------- ### BMI - Branch if Minus Assembly Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example shows the BMI instruction, which branches to a specified label if the Negative flag (N) is set to 1. ```assembly BMI minus_label ; Branch to minus_label if N=1 ``` -------------------------------- ### Configure 6502 CPU using Builder Pattern (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/README.md Illustrates the use of the builder pattern to configure a 6502 CPU with various options like specific variants, strict mode, and disabling decimal mode. This provides a flexible way to customize the CPU instance. ```go cpu := cpu6502.NewBuilder(bus). WithVariant(cpu6502.VariantRicoh2A03). WithStrictMode(). DisableDecimalMode(). Build() ``` -------------------------------- ### SEI - Set Interrupt Disable Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the SEI instruction, which sets the Interrupt Disable flag (I) to 1, disabling maskable interrupts (IRQ). ```assembly SEI ; Set the Interrupt Disable flag (I=1), disabling IRQs ``` -------------------------------- ### CLI - Clear Interrupt Disable Example Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/instruction-set.md This example demonstrates the CLI instruction, which resets the Interrupt Disable flag (I) to 0, enabling maskable interrupts (IRQ). ```assembly CLI ; Clear the Interrupt Disable flag (I=0), enabling IRQs ``` -------------------------------- ### Troubleshoot Poor Performance by Enabling Instruction Cache (Go) Source: https://github.com/drewwalton19216801/sixty502/blob/dev/docs/configuration.md Provides a solution for poor 6502 CPU performance by enabling the instruction cache and checking its hit rate. This snippet shows how to enable the cache, retrieve statistics, and print the hit rate. It emphasizes verifying cache effectiveness to improve execution speed. ```go cpu.EnableInstructionCache() hits, misses, rate := cpu.InstructionCacheStats() fmt.Printf("Cache hit rate: %.1f%%\n", rate*100) ```