cl-6502 is a Common Lisp emulator, assembler and disassembler for the MOS 6502 processor. In case that sounds weird to you, the MOS 6502 is famous for its use in...
- the Apple II,
- the original NES,
- the Commodore 64,
- and Michael Steil's phenomenal talk at 27C3.
A few notes on why I'm doing this are here. Some notes on the design of cl-6502 are here.
You are strongly encouraged to use this library via Quicklisp. Simply start your lisp and run: (ql:quickload 'cl-6502)
.
- Check out the docs for the cl-6502 and 6502-cpu packages. There is also a 6502 package but it exists primarily to house the implementation of all the opcodes.
- Play around at the REPL!
- Use it to create your own wacky code artifacts. (NOTE: As the 6502 package shadows BIT and AND, you're hereby advised not to :use it in any other packages.)
In particular, asm, disasm, execute, 6502-step, and reset are likely of interest.
(An example program, *benchmark*
, currently exists.)
- Load cl-6502.
- Write some 6502 code and run it through
asm
(e.g.(asm "brk")
) to get a bytevector to execute. Optionally, check the disassembly with(disasm *my-bytevector*)
. - Load it into memory and run it with
(execute *cpu* *my-bytevector*)
OR load it with(setf (get-range 0) *my-bytevector*)
, set the program counter to 0 with(setf (cpu-pc *cpu*) 0)
and manually step through it with(6502-step *cpu* (get-byte (immediate *cpu*)))
.
The assembler supports comments, constants, and a limited form of labels in addition to 6502 assembler code. There should only be one statement per line. A label currently stores the absolute address of the next instruction. Thus, loop: {newline} lda
should store the absolute address of lda. Instructions and register names are case insensitive; labels and constants names are case sensitive. Syntax Table:
- Label definition:
name:
- Label usage:
jmp !label
where ! is the syntax of the desired addressing mode. - Constant definition:
name=val
- Constant usage:
lda !name
where ! is the syntax of the desired addressing mode.- Currently, labels and constants only support: indirect, absolute, absolute-x, and absolute-y addressed instructions.
- Comments:
foo ; a note about foo
- Implied mode:
BRK
- Accumulator mode:
ldx a
- Immediate mode:
lda #$00
- Zero-page mode:
lda $03
- Zero-page-x mode:
lda $03, x
- Zero-page-y mode:
ldx $03, y
- Absolute mode:
sbc $0001
- Absolute-x mode:
lda $1234, x
- Absolute-y mode:
lda $1234, y
- Indirect mode:
jmp ($1234)
- Indirect-x mode:
lda ($12), x
- Indirect-y mode:
lda ($34), y
- Relative mode:
bne &fd
- Using Quicklisp: For local development, git clone this repository into the
local-projects
subdirectory of quicklisp.
To run the tests, after you've loaded cl-6502 just run (asdf:oos 'asdf:test-op 'cl-6502)
. You may need to (ql:quickload 'cl-6502-tests)
to ensure that the fiveam dependency is satisfied first. There is a dearth of tests at the moment but there will be more soon as the design has recently solidified.