This repo contains the code for a MOS 6502 processor emulator library.
The 6502Emulator solution consists of the following projects:
- 6502EmulatorConsoleTestApp: A simple console application that demonstrates the functionality of the library.
- 6502EmulatorLib: The code for the library itself.
- 6502Emulator.Tests: An extensive set of tests.
The simple answer is "just for fun" :-)
There are already many 6502 emulators out there and, to be honest, this one doesn't bring anything new to the table. I just quite fancied writing an emulator for one of the processors I programmed for way back in the 1980's, and as the 6502 is about the simplest that I have used, it seemed like as good a place to start as any.
Also, I used this project as a way to practice some Test Driven Development (TDD).
This library does not support any of the undocumented 6502 instructions.
It also currently does nothing for the BRK and RTI instructions.
The included 6502EmulatorConsoleTestApp project demonstrates how to use the emulator. This application has a couple of simple 6502 code examples that it runs through the emulator.
From a developer's point of view, the emulator is used as follows:
- Create an instance of the
Machineclass. - Load binary executable data into the machine by calling the
LoadExecutableDatamethod, supplying a byte array containing the binary data and the address at which the data should be loaded in memory. - Load any other binary data into the machine [if required] by calling the
LoadDatamethod, supplying a byte array containing the binary data and the address at which the data should be loaded in memory. The final parameter passed toLoadDatashould befalseto avoid clearing all memory before loading the data (otherwise any previously loaded executable data will be lost). - Set the initial state of the machine (e.g. register values, flags, etc.) [if required] by calling the
SetStatemethod. - Call the
Executemethod to execute the loaded 6502 code. - Once execution has completed, the
GetStatemethod can be called to retrieve the final state of the machine (register values, flags, etc.). - The
Dumpmethod can be called to get a string detailing the final state of the machine (which can be useful for debugging purposes).
The disassembler takes binary 6502 code and converts it to 6502 Assembly Language instructions. The included 6502EmulatorConsoleTestApp project includes a simple demonstration of this.
The disassembler functionality is used as follows:
- Create an instance of the
Machineclass and load executable data into it (as above). - Create an instance of the
Disassemblerclass, supplying theMachineclass instance, the address in memory at which to start disassembly, and the length of the code (in bytes). - Add non-executable data sections as required - these allow you to mark specific blocks of memory as containing data that is not executable (this tells the disassembler not to attempt to disassemble this data into [what would be invalid] 6502 instructions; instead, it will output them as byte values using a DB assembler directive).
- Call the
Disassemblemethod to perform the disassembly. This method returns a collection of tuple values, each of which consists of the address of the instruction and a string containing the disassembled instruction; for example, (20000, "LDA #$50"). - Iterate through the collection of tuples, outputting each address and disassembled instruction string (see the 6502EmulatorConsoleTestApp project for an example of this).
The assembler takes 6502 assembly language source code and generates 6502 binary code from it. The included 6502EmulatorConsoleTestApp project includes a demonstration of this.
The assembler functionality is used as follows:
- Create an instance of the
Assemblerclass. - Call the
Assemblemethod, passing a list of strings containing the lines of 6502 assembly language source code (one string per line of source code). This method returns a tuple, the first value of which indicates if the assembler successfully processed the supplied source code, if so, the second tuple value is a collection of bytes consisting of the generated binary data. - Once successfully assembled, the binary data can then be written out to a file or fed straight into the emulator to be executed (see the 6502EmulatorConsoleTestApp project for an example of this).
- If the assembler failed to process the source code then the
AsmErrorsproperty of the instance of theAssemblerclass can be accessed to obtain information about any errors that occurred during assembly.
The following are features that are being considered for the future:
- Implement some form of interactive debugger (with features such as single stepping, breakpoint handling, etc.).
- Add support for undocumented 6502 instructions.
| Version | Details |
|---|---|
| 1.0.0 | Initial implementation of 6502 emulator. |
| 1.1.0 | Added Disassembler support. |
| 1.2.0 | Added Assembler functionality. |