Ruby MOS 6502

A ruby implementation of the MOS Technology 6502 microprocessor.

Image of a MOS Technology 6502 microprocessor (from Wikipedia)

Installation

Add this line to your application's Gemfile:

gem 'mos6502'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install mos6502

Usage

The entry point to this library is Mos6502::Cpu. You can create a new Cpu with the program counter (PC) set to a specific memory address as follows:

cpu = Mos6502::Cpu.new(initial_pc: 0x400)

You can load a snippet of code like this:

cpu.load!([0xa9, 0x33, 0x69, 0x55])

Cpu#load! also resets the CPU; all memory is cleared first, then the registers are set to zero, the PC is returned to its initial value, the stack pointer (SP) is reset to 0xff and the status bits are set to their defaults.

There is no assembler (yet?). The above code is:

LDA #$33 ; load immediate
ADC #$55 ; add with carry

It will load the hex value 0x33 (51) into the accumulator and add the hex value 0x55 (85) to it and store the result back in the accumulator.

To run the next instruction, call Cpu#step. The PC will be advanced to point to the next instruction. To run the above code, which is just two instructions, use:

cpu.step
cpu.step

You can then inspect the current state of the CPU with:

puts cpu.inspect

# a: 0x88, x: 0x00, y: 0x00, sp: 0xff, pc: 0x0404, op: 0x00, status: 0b11110000

You can see here that the accumulator (a) holds the result of 0x33 + 0x55 = 0x88 and that the PC has moved on 4 places to 0x404. You can also see from the status bits that the result is negative in two's complement (bit 7) and that overflow has occurred (bit 6).

For more complex code, you will need to load in an assembled image:

image = File.read(IMAGE_PATH)
cpu.load_image!(image, 0x400)

You will need to know the entry point, and set the initial PC when initializing the Cpu upfront. The above example loads the image at memory location 1024. Cpu#load_image! will reset the CPU in the same way as Cpu#load! above. If you need to load an image in parts (e.g. assembled code and data) you can use Cpu#load_image, which is non-destructive.

There is loads more information on the 6502, and how to program it here:

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

6502 test suites

This repository includes external test suites to more comprehensively test all the features of the 6502 microprocessor. They are not run by default because they can take a few minutes to complete, but can be turned on with environment variables passed into rake. Once this code supports all of a test suite's features it will be run by default in CI.

Klaus Dormann's test suite

This is included as a submodule. Once you've initialized it you can run it as part of the normal test suite with:

MOS6502_KLAUS2M5=on rake

If you want to see a full debug stream of it running, use MOS6502_KLAUS2M5=debug instead.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/hainesr/mos6502.

Code of Conduct

This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

Everyone interacting in the MOS 6502 project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Licence

Copyright (c) 2020, Robert Haines.

Released under the BSD Licence. See LICENCE for details.