Skip to content

Highly portable MOS 6502 CPU emulator written in ANSI C

License

Notifications You must be signed in to change notification settings

stahta01/6502_emulator

 
 

Repository files navigation

al-tag


MOS Technology 6502 CPU Emulator

Copyright © 1999-2018 Manuel Sainz de Baranda y Goñi.
Released under the terms of the GNU General Public License v3.

This is a very accurate 6502 emulator I wrote many years ago. It has been used in several machine emulators by other people and it has been extensivelly tested. It is fast, small (17 KB when compiled as a x86-64 dynamic library), easy to understand, and the code is commented.

If you are looking for a MOS 6502 CPU emulator for your project maybe you have found the correct one. I use this core in the Nintendo Entertainment System emulator I started as hobby.


Building

You must first install Z, a header-only library that provides types and macros. This is the only dependency, the emulator does not use the C standard library or its headers. Then add 6502.h and 6502.c to your project and configure its build system so that CPU_6502_STATIC and CPU_6502_USE_LOCAL_HEADER are predefined when compiling the sources.

If you preffer to build the emulator as a library, you can use premake4:

$ cd building
$ premake4 gmake                         # generate Makefile
$ make help                              # list available targets
$ make [config=<configuration>] [target] # build the emulator

There is also an Xcode project in development/Xcode with several targets:

Target Description
6502 (dynamic) Shared library.
6502 (dynamic module) Shared library with a generic module ABI to be used in modular multi-machine emulators.
6502 (static) Static library.
6502 (static module) Static library with a generic CPU emulator ABI to be used in monolithic multi-machine emulators.

Code configuration

There are some predefined macros that control the compilation:

Name Description
CPU_6502_DEPENDENCIES_H If defined, it replaces the inclusion of any external header with this one. If you don't want to use Z, you can provide your own header with the types and macros used by the emulator.
CPU_6502_HIDE_ABI Makes the generic CPU emulator ABI private.
CPU_6502_HIDE_API Makes the public functions private.
CPU_6502_STATIC You need to define this to compile or use the emulator as a static library or if you have added 6502.h and 6502.c to your project.
CPU_6502_USE_LOCAL_HEADER Use this if you have imported 6502.h and 6502.c to your project. 6502.c will #include "6502.h" instead of <emulation/CPU/6502.h>.
CPU_6502_WITH_ABI Builds the generic CPU emulator ABI and declares its prototype in 6502.h.
CPU_6502_WITH_MODULE_ABI Builds the generic module ABI. This macro also enables CPU_6502_WITH_ABI, so the generic CPU emulator ABI will be built too. This option is intended to be used when building a true module loadable at runtime with dlopen(), LoadLibrary() or similar. The ABI module can be accessed via the weak symbol __module_abi__.

API: M6502 emulator instance

This structure contains the state of the emulated CPU and callback pointers necessary to interconnect the emulator with external logic. There is no constructor function, so, before using an object of this type, some of its members must be initialized, in particular the following: context, read and write.

zusize cycles;

Description
Number of cycles executed in the current call to m6502_run.
Details
m6502_run sets this variable to 0 before starting to execute instructions and its value persists after returning. The callbacks can use this variable to know during what cycle they are being called.

void *context;

Description
The value used as the first argument when calling a callback.
Details
This variable should be initialized before using the emulator and can be used to reference the context/instance of the machine being emulated.

zuint8 (* read)(void *context, zuint16 address);

Description
Callback: Called when the CPU needs to read 8 bits from memory.
Parameters
context → The value of the member context.
address → The memory address to read from.
Returns
The 8 bits read from memory.

void (* write)(void *context, zuint16 address, zuint8 value);

Description
Callback: Called when the CPU needs to write 8 bits to memory.
Parameters
context → The value of the member context.
address → The memory address to write to.
value → The value to write.

Z6502State state;

Description
CPU registers and internal bits.
Details
It contains the state of the registers and the interrupt flags. This is what a debugger should use as its data source.

zuint8 opcode;

Description
Temporary storage for memory address resolution.
Details
This is an internal private variable.

zuint8 ea_cycles;

Description
Temporary storage for the number of cycles consumed by instructions requiring memory address resolution.
Details
This is an internal private variable.

zuint16 ea;

Description
Temporary storage for the resolved memory address.
Details
This is an internal private variable.


API: Public Functions

void m6502_power(M6502 *object, zboolean state);

Description
Changes the CPU power status.
Parameters
object → A pointer to a 6502 emulator instance.
stateTRUE = power ON; FALSE = power OFF.

void m6502_reset(M6502 *object);

Description
Resets the CPU.
Details
This is equivalent to a pulse on the RESET line of a real 6502.
Parameters
object → A pointer to a 6502 emulator instance.

zusize m6502_run(M6502 *object, zusize cycles);

Description
Runs the CPU for a given number of cycles.
Note
Given the fact that one 6502 instruction needs between 2 and 7 cycles to be executed, it's not always possible to run the CPU the exact number of cycles specfified.
Parameters
object → A pointer to a 6502 emulator instance.
cycles → The number of cycles to be executed.
Returns
The number of cycles executed.

void m6502_nmi(M6502 *object);

Description
Performs a non-maskable interrupt (NMI).
Details
This is equivalent to a pulse on the NMI line of a real 6502.
Parameters
object → A pointer to a 6502 emulator instance.

void m6502_irq(M6502 *object, zboolean state);

Description
Changes the state of the maskable interrupt (IRQ).
Details
This is equivalent to a change on the IRQ line of a real 6502.
Parameters
object → A pointer to a 6502 emulator instance.
stateTRUE = line high; FALSE = line low.


Use in Proprietary Software

This library is released under the terms of the GNU General Public License v3, but I can license it for non-free/propietary projects if you contact me.

About

Highly portable MOS 6502 CPU emulator written in ANSI C

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 97.9%
  • Lua 2.1%