A MOS 6502 emulator written in C with a focus on speed, especially for ARM targets.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.2KB

  1. #include <stdint.h>
  2. typedef enum {
  3. e6502_Status_C = 0b00000001,
  4. e6502_Status_Z = 0b00000010,
  5. e6502_Status_I = 0b00000100,
  6. e6502_Status_D = 0b00001000,
  7. e6502_Status_B = 0b00010000,
  8. e6502_Status_1 = 0b00100000,
  9. e6502_Status_V = 0b01000000,
  10. e6502_Status_N = 0b10000000,
  11. } e6502_Status_Flag;
  12. typedef enum __attribute__ ((__packed__)) {
  13. e6502_Pin_NMI = 0b01,
  14. e6502_Pin_IRQ = 0b10,
  15. e6502_NMI_Serviced = 0b10000000
  16. } e6502_Pin;
  17. typedef struct __attribute__ ((__packed__)) {
  18. uint16_t PC;
  19. uint8_t S;
  20. uint8_t A;
  21. uint8_t X;
  22. uint8_t Y;
  23. uint8_t P;
  24. } e6502_Registers;
  25. typedef uint16_t e6502_Mem_Addr;
  26. #ifndef E6502_POLL_MEM
  27. typedef uint8_t(e6502_Read)(void*, e6502_Mem_Addr);
  28. typedef void(e6502_Write)(void*, e6502_Mem_Addr, uint8_t);
  29. #endif
  30. typedef struct {
  31. e6502_Registers registers;
  32. e6502_Pin pins;
  33. #ifdef E6502_POLL_MEM
  34. uint8_t memory[65536];
  35. #else
  36. e6502_Read* bus_read;
  37. e6502_Write* bus_write;
  38. void* bus_context;
  39. #endif
  40. int cycle;
  41. } e6502_Core;
  42. #define e6502_Memory_Stack (0x0100U)
  43. #define e6502_IRQ_Vec (0xFFFEU)
  44. #define e6502_Reset_Vec (0xFFFCU)
  45. #define e6502_NMI_Vec (0xFFFAU)
  46. #ifdef E6502_POLL_MEM
  47. static inline uint8_t e6502_r8(e6502_Core* core,
  48. e6502_Mem_Addr adr) {
  49. return core->memory[adr];
  50. }
  51. static inline void e6502_w8(e6502_Core* core,
  52. e6502_Mem_Addr adr,
  53. uint8_t val) {
  54. core->memory[adr] = val;
  55. }
  56. #else
  57. static inline uint8_t e6502_r8(e6502_Core* core,
  58. e6502_Mem_Addr adr) {
  59. return core->bus_read(core->bus_context, adr);
  60. }
  61. static inline void e6502_w8(e6502_Core* core,
  62. e6502_Mem_Addr adr,
  63. uint8_t val) {
  64. return core->bus_write(core->bus_context, adr, val);
  65. }
  66. #endif
  67. static inline uint16_t e6502_r16(e6502_Core* core,
  68. e6502_Mem_Addr adr) {
  69. return e6502_r8(core, adr) |
  70. ((uint16_t)e6502_r8(core, adr + 1) << 8);
  71. }
  72. static inline void e6502_w16(e6502_Core* core,
  73. e6502_Mem_Addr adr,
  74. uint16_t val) {
  75. e6502_w8(core, adr, val);
  76. e6502_w8(core, adr + 1, val >> 8);
  77. }
  78. static inline void e6502_push8(e6502_Core* core, uint8_t val) {
  79. e6502_w8(core, e6502_Memory_Stack + core->registers.S--, val);
  80. }
  81. static inline void e6502_push16(e6502_Core* core, uint16_t val) {
  82. e6502_push8(core, val >> 8);
  83. e6502_push8(core, val & 0xFF);
  84. }
  85. static inline uint8_t e6502_pop8(e6502_Core* core) {
  86. return e6502_r8(core, e6502_Memory_Stack +
  87. ++core->registers.S);
  88. }
  89. static inline uint16_t e6502_pop16(e6502_Core* core) {
  90. return (e6502_pop8(core) | ((uint16_t)e6502_pop8(core) << 8));
  91. }
  92. #ifdef E6502_POLL_MEM
  93. void e6502_init(e6502_Core*);
  94. #else
  95. void e6502_init(e6502_Core*, e6502_Read, e6502_Write, void*);
  96. #endif
  97. int e6502_step(e6502_Core* core);
  98. int e6502_run(e6502_Core* core,
  99. int remaining,
  100. int* run,
  101. int instructions);
  102. void e6502_reset(e6502_Core* core);
  103. void e6502_set_irq(e6502_Core* core, int active);
  104. void e6502_set_nmi(e6502_Core* core, int active);