NESe (pronounced "Nessie") is a NES emulator based on the e6502 emulator, also written in C with a focus on speed and portability for use on embedded platforms, especially ARM.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

1640 rindas
42KB

  1. #include <stdbool.h>
  2. #include <string.h>
  3. #include "f6502.h"
  4. #include "f6502_consts.h"
  5. #ifdef F6502_TRACE
  6. #include "f6502_opcodes.h"
  7. #include <stdio.h>
  8. #endif
  9. #ifdef F6502_TEST
  10. #include <stddef.h>
  11. #define container_of(ptr, type, member) ({ \
  12. const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  13. (type *)((char *)__mptr - offsetof(type,member));})
  14. #endif
  15. //#define DEBUG "Core"
  16. #include "log.h"
  17. // TOTO: Temp Hack
  18. volatile uint8_t memval;
  19. static inline uint8_t f6502_read_zp(nes_Memory* mem,
  20. uint8_t addr) {
  21. return mem->ram[addr];
  22. }
  23. static inline uint16_t f6502_read16_zp(nes_Memory* mem,
  24. uint8_t addr) {
  25. return ( f6502_read_zp(mem, addr) |
  26. ((uint16_t)f6502_read_zp(mem, addr + 1) << 8));
  27. }
  28. static inline uint8_t read_gamepad_bit(nes_Gamepad* gamepad) {
  29. uint8_t state = 1;
  30. if (gamepad->shift < 0) {
  31. state = (gamepad->buttons >> Button_A) & 1;
  32. } else if (gamepad->shift < nes_controller_num_buttons) {
  33. state = (gamepad->buttons >> gamepad->shift) & 1;
  34. gamepad->shift++;
  35. }
  36. return state;
  37. }
  38. static inline uint8_t f6502_read(nes_Memory* mem,
  39. uint16_t addr) {
  40. #ifdef F6502_FLAT
  41. #ifdef F6502_TRACE
  42. // printf("R $%04X -> %02X\n", addr, mem->ram[addr]);
  43. #endif
  44. return mem->ram[addr];
  45. #else
  46. if (addr >= 0x8000U) {
  47. return mem->rom_bank[(addr - 0x8000U) >> 13][addr & 0x1FFFU];
  48. }
  49. switch (addr & 0x6000U) {
  50. case 0x0000:
  51. return mem->ram[addr & 0x7FFU];
  52. case 0x2000:
  53. switch(addr & 0x7) {
  54. case ppu_reg_status:
  55. { uint8_t val = mem->ppu.status;
  56. mem->ppu.status &= ~ppu_Status_VBlank;
  57. mem->ppu.latch = 0;
  58. // TODO: Set nametable to 0 when in VBlank??
  59. return val;
  60. }
  61. case ppu_reg_oam_data:
  62. return mem->ppu.oam[mem->ppu.oam_addr++];
  63. case ppu_reg_data:
  64. { addr = mem->ppu.addr & 0x3FFFU;
  65. mem->ppu.addr += mem->ppu.addr_inc;
  66. uint8_t val = mem->ppu.data;
  67. mem->ppu.data = mem->ppu.bank[addr >> 10][addr & 0x3FFU];
  68. return val;
  69. }
  70. }
  71. break;
  72. case 0x4000:
  73. switch (addr & 0x1FU) {
  74. case 0x16:
  75. case 0x17:
  76. { nes_Gamepad* gamepad = &mem->input.gamepads[addr & 1];
  77. return ((addr >> 8) & nes_controller_bus_mask) |
  78. read_gamepad_bit(gamepad);
  79. } break;
  80. default:
  81. // TODO: APU Reg
  82. }
  83. break;
  84. case 0x6000:
  85. if (mem->sram_bank) {
  86. return mem->sram_bank[addr & 0x1FFFU];
  87. }
  88. }
  89. // Upper byte stays on the bus
  90. return (addr >> 8);
  91. #endif
  92. }
  93. static inline uint16_t f6502_read16(nes_Memory* mem,
  94. uint16_t addr) {
  95. return ( f6502_read(mem, addr) |
  96. ((uint16_t)f6502_read(mem, addr + 1) << 8));
  97. }
  98. static inline int f6502_write(nes_Memory* mem,
  99. uint16_t addr, uint8_t val) {
  100. int ret = 0;
  101. #ifdef F6502_TRACE
  102. printf("W $%04X <- %02X\n", addr, val);
  103. #endif
  104. #ifdef F6502_FLAT
  105. #ifdef F6502_TEST
  106. if (addr == 0xbffc) {
  107. f6502_Core* core = container_of(mem, f6502_Core, memory);
  108. int irq = val & 0b01;
  109. int nmi = val & 0b10;
  110. #ifdef F6502_TRACE
  111. if (!irq ^ !(core->interrupts & f6502_Int_IRQ)) {
  112. fprintf(stdout, "%s IRQ\n", irq ? "Set" : "Clear");
  113. }
  114. if (!nmi ^ !(core->interrupts & f6502_Int_NMI)) {
  115. fprintf(stdout, "%s NMI\n", nmi ? "Set" : "Clear");
  116. }
  117. #endif
  118. f6502_set_NMI(core, nmi);
  119. f6502_set_IRQ(core, irq);
  120. // Interrupt [may have been] triggered
  121. // We're not strictly counting cycles,
  122. // so just overload the counter
  123. ret = 1000;
  124. }
  125. #endif
  126. mem->ram[addr] = val;
  127. #else
  128. switch (addr & 0xe000) {
  129. case 0x0000:
  130. mem->ram[addr & 0x7FFU] = val;
  131. break;
  132. case 0x2000:
  133. switch (addr & 0x7U) {
  134. case ppu_reg_ctrl:
  135. mem->ppu.ctrl &= ppu_Control_Nametable_Mask;
  136. mem->ppu.ctrl |= (val & ~ppu_Control_Nametable_Mask);
  137. mem->ppu.t &= ~(ppu_Control_Nametable_Mask << 10);
  138. mem->ppu.t |= ((uint16_t)val & ppu_Control_Nametable_Mask) << 10;
  139. mem->ppu.addr_inc = (val & ppu_Control_VRAM_Inc) ? 32 : 1;
  140. // TODO: Trigger NMI if VBlank status is set?
  141. break;
  142. case ppu_reg_mask:
  143. mem->ppu.mask = val;
  144. break;
  145. case ppu_reg_oam_addr:
  146. mem->ppu.oam_addr = val;
  147. break;
  148. case ppu_reg_oam_data:
  149. mem->ppu.oam[(int)mem->ppu.oam_addr++] = val;
  150. break;
  151. case ppu_reg_scroll:
  152. if (mem->ppu.latch) {
  153. LOGI("PPU: SCROLL_Y %02X", val);
  154. mem->ppu.t &= 0b0000110000011111U;
  155. mem->ppu.t |= (uint16_t)(val & 0b00000111U) << 12;
  156. mem->ppu.t |= (uint16_t)(val & 0b11111000U) << 2;
  157. } else {
  158. LOGI("PPU: SCROLL_X %02X", val);
  159. mem->ppu.t &= ~(0b11111U);
  160. mem->ppu.t |= (val & 0b11111000U) >> 3;
  161. mem->ppu.x = (val & 0b111U);
  162. }
  163. mem->ppu.latch = !mem->ppu.latch;
  164. break;
  165. case ppu_reg_addr:
  166. if (mem->ppu.latch) {
  167. mem->ppu.t &= 0xFF00U;
  168. mem->ppu.t |= val;
  169. mem->ppu.addr = (mem->ppu.t & 0x3FFFU);
  170. // Keep ctrl & t nametable in sync
  171. mem->ppu.ctrl &= ~ppu_Control_Nametable_Mask;
  172. mem->ppu.ctrl |= ((val >> 10) & ppu_Control_Nametable_Mask);
  173. LOGI("PPU: ADDR %04X", mem->ppu.addr);
  174. } else {
  175. mem->ppu.t &= 0x00FFU;
  176. mem->ppu.t |= (uint16_t)(val & 0x3FU) << 8;
  177. }
  178. mem->ppu.latch = !mem->ppu.latch;
  179. break;
  180. case ppu_reg_data:
  181. // Disallow CHR ROM writes
  182. addr = mem->ppu.addr & 0x3FFFU;
  183. if (addr >= NES_PPU_CHR_SIZE || mem->ppu.chr_ram) {
  184. LOGI("PPU W %04X < %02X", addr, val);
  185. mem->ppu.bank[addr >> 10][addr & 0x3FFU] = val;
  186. if (addr >= NES_PPU_PAL_START) {
  187. // Copy to render reference
  188. addr &= 0x1FU;
  189. uint8_t* pal = mem->ppu.palette;
  190. if (0 == (addr & 0x3)) {
  191. // TODO: Just initialize this
  192. pal[0] = pal[4] = pal[8] = pal[12] =
  193. pal[16] = pal[20] = pal[24] =
  194. pal[28] = 0xFFU;
  195. } else {
  196. pal[addr] = val;
  197. }
  198. // Memory-mapped mirroring
  199. addr |= 0x300U;
  200. for (int mirror = 0; mirror < 0x100; mirror += 0x20) {
  201. mem->ppu.pal_bank[addr + mirror] = val;
  202. }
  203. if (0 == (addr & 3)) {
  204. for (int mirror = 0; mirror < 0x100; mirror += 0x20) {
  205. mem->ppu.pal_bank[(addr ^ 0x10U) + mirror] = val;
  206. }
  207. }
  208. }
  209. } else {
  210. LOGE("PPU W %04X < %02X : INVALID", addr, val);
  211. }
  212. mem->ppu.addr += mem->ppu.addr_inc;
  213. break;
  214. }
  215. break;
  216. case 0x4000:
  217. // TODO: APU
  218. switch (addr & 0x1FU) {
  219. case 0x14: // OAM DMA
  220. { uint8_t* src = NULL;
  221. // OAM DMA
  222. switch (val >> 5) {
  223. case 0: // 0x0000 - 0x1FFF RAM
  224. src = &mem->ram[((int)val << 8) & 0x7FFU];
  225. break;
  226. case 3: // 0x6000 - 0x7FFF SRAM
  227. if (mem->sram_bank) {
  228. src = &mem->sram_bank[((int)val << 8) & 0x1FFFU];
  229. }
  230. break;
  231. case 4: // 0x8000 - 0x9FFF ROM
  232. case 5: // 0xA000 - 0xBFFF ROM
  233. case 6: // 0xC000 - 0xDFFF ROM
  234. case 7: // 0xE000 - 0xFFFF ROM
  235. src = &mem->rom_bank[(val >> 5) & 3][((int)val << 8) & 0x1FFFU];
  236. break;
  237. }
  238. if (NULL != src) {
  239. memcpy(mem->ppu.oam, src, NES_PPU_OAM_SIZE);
  240. }
  241. ret = 513;
  242. } break;
  243. case 0x16: // Reset Gamepad
  244. if (val & 1) {
  245. mem->input.gamepads[0].shift = -1;
  246. mem->input.gamepads[1].shift = -1;
  247. } else {
  248. mem->input.gamepads[0].shift = 0;
  249. mem->input.gamepads[1].shift = 0;
  250. }
  251. break;
  252. }
  253. break;
  254. case 0x6000:
  255. if (mem->sram_bank) {
  256. mem->sram_bank[addr & 0x1FFFU] = val;
  257. mem->flags |= nes_Mem_SRAM_Used;
  258. } else if (mem->mapper.write_sram) {
  259. ret = mem->mapper.write_sram(&mem->mapper,
  260. addr, val);
  261. }
  262. }
  263. #endif
  264. return ret;
  265. }
  266. void f6502_init(f6502_Core* core) {
  267. // TODO: Nothing for now
  268. }
  269. void f6502_reset(f6502_Core* core) {
  270. core->registers.PC = f6502_read16(&core->memory,
  271. f6502_Vector_Reset),
  272. core->registers.S -= 3;
  273. core->registers.P |= (f6502_Status_B | f6502_Status_1);
  274. }
  275. void f6502_set_NMI(f6502_Core* core, bool active) {
  276. if (active) core->interrupts |= f6502_Int_NMI;
  277. else core->interrupts &= ~(f6502_Int_NMI | f6502_Int_NMI_Serviced);
  278. }
  279. void f6502_set_IRQ(f6502_Core* core, bool active) {
  280. if (active) core->interrupts |= f6502_Int_IRQ;
  281. else core->interrupts &= ~f6502_Int_IRQ;
  282. }
  283. #define PUSH(core, S, val) \
  284. f6502_write(&core->memory, f6502_Base_Stack + S--, (val))
  285. #define PUSH16(core, S, val) \
  286. PUSH(core, S, ((val) >> 8)); \
  287. PUSH(core, S, ((val) & 0xFFU))
  288. #define POP(core, S, dst) \
  289. dst = f6502_read(&core->memory, f6502_Base_Stack + ++S)
  290. #define POP16(core, S, dst) \
  291. POP(core, S, dst); \
  292. dst |= (f6502_read(&core->memory, \
  293. f6502_Base_Stack + ++S) << 8)
  294. #define CLR(R, flags) R &= ~(flags)
  295. #define SET(R, flags) R |= (flags)
  296. static inline int f6502_interrupt(f6502_Core* core,
  297. uint16_t addr) {
  298. PUSH16(core, core->registers.S, core->registers.PC);
  299. PUSH(core, core->registers.S,
  300. core->registers.P & ~f6502_Status_B);
  301. SET(core->registers.P, f6502_Status_I);
  302. core->registers.PC = f6502_read16(&core->memory, addr);
  303. return 7;
  304. }
  305. static inline bool f6502_nmi_ready(const f6502_Core* core) {
  306. return ( (core->interrupts & f6502_Int_NMI) &&
  307. !(core->interrupts & f6502_Int_NMI_Serviced));
  308. }
  309. static inline bool f6502_irq_ready(const f6502_Core* core) {
  310. return ( (core->interrupts & f6502_Int_IRQ) &&
  311. !(core->registers.P & f6502_Status_I));
  312. }
  313. static inline int f6502_check_interrupts(f6502_Core* core) {
  314. if (f6502_nmi_ready(core)) {
  315. core->interrupts |= f6502_Int_NMI_Serviced;
  316. return f6502_interrupt(core, f6502_Vector_NMI);
  317. } else if (f6502_irq_ready(core)) {
  318. return f6502_interrupt(core, f6502_Vector_IRQ);
  319. }
  320. return 0;
  321. }
  322. #define CLK(n) clocks_elapsed += n
  323. #define TEST(val) \
  324. CLR(P, f6502_Status_Z | f6502_Status_N); \
  325. SET(P, table_test[val])
  326. #define A_ABS ({ \
  327. uint16_t addr_lo = f6502_read(&core->memory, PC++); \
  328. uint16_t addr_hi = f6502_read(&core->memory, PC++); \
  329. (addr_lo | (addr_hi << 8)); \
  330. })
  331. #define A_ABSX (A_ABS + X)
  332. #define A_ABSY (A_ABS + Y)
  333. #define A_ZP f6502_read(&core->memory, PC++)
  334. #define A_ZPX (uint8_t)(f6502_read(&core->memory, PC++) + X)
  335. #define A_ZPY (uint8_t)(f6502_read(&core->memory, PC++) + Y)
  336. #define A_IX f6502_read16_zp( \
  337. &core->memory, \
  338. f6502_read(&core->memory, PC++) + X \
  339. )
  340. #define A_IY (f6502_read16_zp( \
  341. &core->memory, \
  342. f6502_read(&core->memory, PC++) \
  343. ) + Y)
  344. #define D_IMM f6502_read(&core->memory, PC++)
  345. #define D_ABS f6502_read(&core->memory, A_ABS)
  346. #define D_ABSX ({ \
  347. register uint16_t addr_base = A_ABS; \
  348. register uint16_t addr = addr_base + X; \
  349. CLK((addr_base & 0x100U) != (addr & 0x100U)); \
  350. f6502_read(&core->memory, addr); \
  351. })
  352. #define D_ABSY ({ \
  353. register uint16_t addr_base = A_ABS; \
  354. register uint16_t addr = addr_base + Y; \
  355. CLK((addr_base & 0x100U) != (addr & 0x100U)); \
  356. f6502_read(&core->memory, addr); \
  357. })
  358. #define D_ZP f6502_read_zp(&core->memory, A_ZP)
  359. #define D_ZPX f6502_read_zp(&core->memory, A_ZPX)
  360. #define D_ZPY f6502_read_zp(&core->memory, A_ZPY)
  361. #define D_IX f6502_read(&core->memory, A_IX)
  362. #define D_IY ({ \
  363. register uint16_t addr_base = f6502_read16_zp( \
  364. &core->memory, \
  365. f6502_read(&core->memory, PC++) \
  366. ); \
  367. register uint16_t addr = addr_base + Y; \
  368. CLK((addr_base & 0x100U) != (addr & 0x100U)); \
  369. f6502_read(&core->memory, addr); \
  370. })
  371. #define ADC(v) { \
  372. register uint8_t val = v; \
  373. register uint16_t res = A + val + (P & f6502_Status_C); \
  374. CLR(P, f6502_Status_N | f6502_Status_V | \
  375. f6502_Status_Z | f6502_Status_C); \
  376. SET(P, table_test[(uint8_t)res]); \
  377. SET(P, (res > 0xFFU)); \
  378. if ((~(A ^ val) & (A ^ (uint8_t)res)) & 0x80) { \
  379. SET(P, f6502_Status_V); \
  380. } \
  381. A = res; \
  382. }
  383. #define AND(v) A &= (v); TEST(A)
  384. #define ASL(a) ({ \
  385. CLR(P, f6502_Status_N | f6502_Status_Z | f6502_Status_C); \
  386. register uint16_t addr = a; \
  387. register uint8_t val = f6502_read(&core->memory, addr); \
  388. SET(P, table_asl[val]); \
  389. val <<= 1; \
  390. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  391. })
  392. #define ASL_A() \
  393. CLR(P, f6502_Status_N | f6502_Status_Z | f6502_Status_C); \
  394. SET(P, table_asl[A]); \
  395. A <<= 1
  396. #ifdef F6502_HCF
  397. #define BIF_HCF() \
  398. if (pc_prev == PC + 2) { \
  399. ++PC; \
  400. clocks_elapsed = -clocks_elapsed; \
  401. goto step_done; \
  402. }
  403. #else
  404. #define BIF_HCF()
  405. #endif
  406. #define BIF(cond) \
  407. if (cond) { \
  408. register uint16_t pc_prev = PC; \
  409. PC += (int8_t)f6502_read(&core->memory, PC); \
  410. BIF_HCF(); \
  411. CLK(3 + ((pc_prev & 0x100U) != (PC & 0x100U))); \
  412. } else { \
  413. CLK(2); \
  414. } \
  415. ++PC
  416. #define BIT(v) { \
  417. register uint8_t val = (v); \
  418. CLR(P, f6502_Status_N | f6502_Status_V | f6502_Status_Z); \
  419. SET(P, (val & (f6502_Status_N | f6502_Status_V))); \
  420. if (!(val & A)) SET(P, f6502_Status_Z); \
  421. }
  422. #define CP(reg, v) { \
  423. uint16_t diff = (uint16_t)reg - (v); \
  424. CLR(P, f6502_Status_N | f6502_Status_Z | f6502_Status_C); \
  425. SET(P, table_test[diff & 0xFFU]); \
  426. if (diff < 0x100) SET(P, f6502_Status_C); \
  427. }
  428. #define DEC(a) ({ \
  429. register uint16_t addr = a; \
  430. register uint8_t val = f6502_read(&core->memory, addr); \
  431. --val; \
  432. TEST(val); \
  433. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  434. })
  435. #define EOR(v) A ^= (v); TEST(A)
  436. #define INC(a) ({ \
  437. register uint16_t addr = a; \
  438. register uint8_t val = f6502_read(&core->memory, addr); \
  439. ++val; \
  440. TEST(val); \
  441. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  442. })
  443. #define JMP(a) PC = (a)
  444. #define LD(reg, v) reg = (v); TEST(reg)
  445. #define LSR(a) ({ \
  446. register uint16_t addr = a; \
  447. register uint8_t val = f6502_read(&core->memory, addr); \
  448. CLR(P, f6502_Status_N | f6502_Status_Z | f6502_Status_C); \
  449. SET(P, val & f6502_Status_C); \
  450. val >>= 1; \
  451. SET(P, val & f6502_Status_N); \
  452. if (!val) SET(P, f6502_Status_Z); \
  453. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  454. })
  455. #define LSR_A() \
  456. CLR(P, f6502_Status_N | f6502_Status_Z | f6502_Status_C); \
  457. SET(P, A & f6502_Status_C); \
  458. A >>= 1; \
  459. SET(P, A & f6502_Status_N); \
  460. if (!A) SET(P, f6502_Status_Z)
  461. #define ORA(v) A |= (v); TEST(A)
  462. #define ROL(a) ({ \
  463. register uint16_t addr = a; \
  464. register uint8_t val = f6502_read(&core->memory, addr); \
  465. register uint8_t new_c = (val & 0x80) ? f6502_Status_C : 0; \
  466. val = (val << 1) | (P & f6502_Status_C); \
  467. CLR(P, f6502_Status_C | f6502_Status_Z | f6502_Status_N); \
  468. P |= new_c; \
  469. if (!val) SET(P, f6502_Status_Z); \
  470. SET(P, val & f6502_Status_N); \
  471. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  472. })
  473. #define ROL_A() { \
  474. register uint8_t new_c = (A & 0x80) ? f6502_Status_C : 0; \
  475. A = (A << 1) | (P & f6502_Status_C); \
  476. CLR(P, f6502_Status_C | f6502_Status_Z | f6502_Status_N); \
  477. P |= new_c; \
  478. if (!A) SET(P, f6502_Status_Z); \
  479. SET(P, A & f6502_Status_N); \
  480. }
  481. #define ROR(a) ({ \
  482. register uint16_t addr = a; \
  483. register uint8_t val = f6502_read(&core->memory, addr); \
  484. register uint8_t new_c = (val & f6502_Status_C); \
  485. val >>= 1; \
  486. if (P & f6502_Status_C) val |= f6502_Status_N; \
  487. CLR(P, f6502_Status_C | f6502_Status_Z | f6502_Status_N); \
  488. P |= new_c; \
  489. if (!val) SET(P, f6502_Status_Z); \
  490. SET(P, (val & f6502_Status_N)); \
  491. clocks_elapsed += f6502_write(&core->memory, addr, val); \
  492. })
  493. #define ROR_A() { \
  494. register uint8_t new_c = (A & f6502_Status_C); \
  495. A >>= 1; \
  496. if (P & f6502_Status_C) A |= f6502_Status_N; \
  497. CLR(P, f6502_Status_C | f6502_Status_Z | f6502_Status_N); \
  498. P |= new_c; \
  499. if (!A) SET(P, f6502_Status_Z); \
  500. SET(P, (A & f6502_Status_N)); \
  501. }
  502. #define SBC(v) { \
  503. register uint8_t val = v; \
  504. register uint16_t res = A - val - (~P & f6502_Status_C);\
  505. CLR(P, f6502_Status_N | f6502_Status_V | \
  506. f6502_Status_Z | f6502_Status_C); \
  507. SET(P, table_test[(uint8_t)res]); \
  508. SET(P, (res < 0x100U)); \
  509. if (((A ^ val) & (A ^ (uint8_t)res)) & 0x80) { \
  510. SET(P, f6502_Status_V); \
  511. } \
  512. A = res; \
  513. }
  514. #define ST(reg, a) clocks_elapsed += f6502_write(&core->memory, (a), reg)
  515. static int f6502_do_step(f6502_Core* core, int clocks) {
  516. register int clocks_elapsed = 0;
  517. register uint16_t PC = core->registers.PC;
  518. register uint8_t S = core->registers.S;
  519. register uint8_t A = core->registers.A;
  520. register uint8_t X = core->registers.X;
  521. register uint8_t Y = core->registers.Y;
  522. register uint8_t P = core->registers.P;
  523. while (clocks_elapsed < clocks) {
  524. uint8_t opcode = f6502_read(&core->memory, PC++);
  525. #ifdef F6502_TRACE
  526. printf("S:%02x A:%02x X:%02x Y:%02x P:%02x\n",
  527. S, A, X, Y, P);
  528. printf("$%04x:", (int)S + f6502_Base_Stack);
  529. for (int i = S; i < 256; ++i)
  530. printf(" %02x", (int)f6502_read(&core->memory, i + f6502_Base_Stack));
  531. putc('\n', stdout);
  532. // printf("INT %02x\n", core->interrupts);
  533. uint16_t operand = f6502_read16(&core->memory, PC);
  534. printf("$%04x: ", PC - 1);
  535. f6502_dump_instr(core, opcode, (uint8_t*)&operand);
  536. printf(" -> ");
  537. f6502_fprintf_instr(stdout, opcode, (uint8_t*)&operand);
  538. putc('\n', stdout);
  539. #endif
  540. switch (opcode) {
  541. case 0x00: // BRK
  542. ++PC;
  543. PUSH16(core, S, PC);
  544. PUSH(core, S, P | f6502_Status_B | f6502_Status_1);
  545. SET(P, f6502_Status_I);
  546. PC = f6502_read16(&core->memory, f6502_Vector_IRQ);
  547. CLK(7);
  548. break;
  549. case 0x01: // ORA (zp, X)
  550. ORA(D_IX);
  551. CLK(6);
  552. break;
  553. // Undefined: 0x02 - 0x04
  554. case 0x05: // ORA zp
  555. ORA(D_ZP);
  556. CLK(3);
  557. break;
  558. case 0x06: // ASL zp
  559. ASL(A_ZP);
  560. CLK(5);
  561. break;
  562. // Undefined: 0x07
  563. case 0x08: // PHP
  564. SET(P, f6502_Status_B);
  565. PUSH(core, S, P);
  566. CLK(3);
  567. break;
  568. case 0x09: // ORA imm
  569. ORA(D_IMM);
  570. CLK(2);
  571. break;
  572. case 0x0A: // ASL A
  573. ASL_A();
  574. CLK(2);
  575. break;
  576. // Undefined: 0x0B
  577. // Special: 0x0C
  578. case 0x0D: // ORA abs
  579. ORA(D_ABS);
  580. CLK(4);
  581. break;
  582. case 0x0E: // ASL abs
  583. ASL(A_ABS);
  584. CLK(6);
  585. break;
  586. // Undefined: 0x0F
  587. case 0x10: // BPL
  588. BIF(!(P & f6502_Status_N));
  589. break;
  590. case 0x11: // ORA (zp), Y
  591. ORA(D_IY);
  592. CLK(5);
  593. break;
  594. // Undefined: 0x12 - 0x13
  595. // Special: 0x14
  596. case 0x15: // ORA zp, X
  597. ORA(D_ZPX);
  598. CLK(4);
  599. break;
  600. case 0x16: // ASL zp, X
  601. ASL(A_ZPX);
  602. CLK(4);
  603. break;
  604. // Undefined: 0x17
  605. case 0x18: // CLC
  606. CLR(P, f6502_Status_C);
  607. CLK(2);
  608. break;
  609. case 0x19: // ORA abs, Y
  610. ORA(D_ABSY);
  611. CLK(4);
  612. break;
  613. // Special: 0x1A
  614. // Undefined: 0x1B
  615. // Special: 0x1C
  616. case 0x1D: // ORA abs, X
  617. ORA(D_ABSX);
  618. CLK(4);
  619. break;
  620. case 0x1E: // ASL abs, X
  621. ASL(A_ABSX);
  622. CLK(7);
  623. break;
  624. // Undefined: 0x1F
  625. case 0x20: // JSR
  626. { uint16_t addr_lo = f6502_read(&core->memory, PC++);
  627. uint16_t addr_hi = f6502_read(&core->memory, PC);
  628. PUSH16(core, S, PC);
  629. PC = addr_lo | (addr_hi << 8);
  630. CLK(6);
  631. } break;
  632. case 0x21: // AND (zp, X)
  633. AND(D_IX);
  634. CLK(6);
  635. break;
  636. // Undefined: 0x22 - 0x23
  637. case 0x24: // BIT zp
  638. BIT(D_ZP);
  639. CLK(3);
  640. break;
  641. case 0x25: // AND zp
  642. AND(D_ZP);
  643. CLK(3);
  644. break;
  645. case 0x26: // ROL zp
  646. ROL(A_ZP);
  647. CLK(5);
  648. break;
  649. // Undefined: 0x27
  650. case 0x28: // PLP
  651. POP(core, S, P);
  652. SET(P, f6502_Status_1 | f6502_Status_B);
  653. CLK(4);
  654. break;
  655. case 0x29: // AND imm
  656. AND(D_IMM);
  657. CLK(2);
  658. break;
  659. case 0x2A: // ROL A
  660. ROL_A();
  661. CLK(2);
  662. break;
  663. // Undefined: 0x2B
  664. case 0x2C: // BIT abs
  665. BIT(D_ABS);
  666. CLK(4);
  667. break;
  668. case 0x2D: // AND abs
  669. AND(D_ABS);
  670. CLK(4);
  671. break;
  672. case 0x2E: // ROL abs
  673. ROL(A_ABS);
  674. CLK(6);
  675. break;
  676. // Undefined: 0x2F
  677. case 0x30: // BMI
  678. BIF(P & f6502_Status_N);
  679. break;
  680. case 0x31: // AND (zp), Y
  681. AND(D_IY);
  682. CLK(5);
  683. break;
  684. // Undefined: 0x32 - 0x33
  685. // Special: 0x34
  686. case 0x35: // AND zp, X
  687. AND(D_ZPX);
  688. CLK(4);
  689. break;
  690. case 0x36: // ROL zp, X
  691. ROL(A_ZPX);
  692. CLK(6);
  693. break;
  694. // Undefined: 0x37
  695. case 0x38: // SEC
  696. SET(P, f6502_Status_C);
  697. CLK(2);
  698. break;
  699. case 0x39: // AND abs, Y
  700. AND(D_ABSY);
  701. CLK(4);
  702. break;
  703. // Special: 0x3A
  704. // Undefined: 0x3B
  705. // Special: 0x3C
  706. case 0x3D: // AND abs, X
  707. AND(D_ABSX);
  708. CLK(4);
  709. break;
  710. case 0x3E: // ROL abs, X
  711. ROL(A_ABSX);
  712. CLK(7);
  713. break;
  714. // Undefined: 0x3F
  715. case 0x40: // RTI
  716. POP(core, S, P);
  717. SET(P, f6502_Status_1 | f6502_Status_B);
  718. POP16(core, S, PC);
  719. CLK(6);
  720. // Interrupt might be triggered; break out
  721. clocks = 0;
  722. break;
  723. case 0x41: // EOR (zp, X)
  724. EOR(D_IX);
  725. CLK(6);
  726. break;
  727. // Undefined: 0x42 - 0x43
  728. // Special: 0x44
  729. case 0x45: // EOR zp
  730. EOR(D_ZP);
  731. CLK(3);
  732. break;
  733. case 0x46: // LSR zp
  734. LSR(A_ZP);
  735. CLK(5);
  736. break;
  737. // Undefined: 0x47
  738. case 0x48: // PHA
  739. PUSH(core, S, A);
  740. CLK(3);
  741. break;
  742. case 0x49: // EOR imm
  743. EOR(D_IMM);
  744. CLK(2);
  745. break;
  746. case 0x4A: // LSR A
  747. LSR_A();
  748. CLK(2);
  749. break;
  750. // Undefined: 0x4B
  751. case 0x4C: // JMP abs
  752. #ifdef F6502_HCF
  753. { uint16_t addr = A_ABS;
  754. if (PC - 3 == addr) {
  755. JMP(addr);
  756. clocks_elapsed = -clocks_elapsed;
  757. goto step_done;
  758. }
  759. JMP(addr);
  760. }
  761. #else
  762. JMP(A_ABS);
  763. #endif
  764. CLK(3);
  765. break;
  766. case 0x4D: // EOR abs
  767. EOR(D_ABS);
  768. CLK(4);
  769. break;
  770. case 0x4E: // LSR abs
  771. LSR(A_ABS);
  772. CLK(6);
  773. break;
  774. // Undefined: 0x4F
  775. case 0x50: // BVC
  776. BIF(!(P & f6502_Status_V));
  777. break;
  778. case 0x51: // EOR (zp), Y
  779. EOR(D_IY);
  780. CLK(5);
  781. break;
  782. // Undefined: 0x52 - 0x53
  783. // Special: 0x54
  784. case 0x55: // EOR zp, X
  785. EOR(D_ZPX);
  786. CLK(4);
  787. break;
  788. case 0x56: // LSR zp, X
  789. LSR(A_ZPX);
  790. CLK(6);
  791. break;
  792. // Undefined: 0x57
  793. case 0x58: // CLI
  794. { register uint8_t p_old = P;
  795. CLR(P, f6502_Status_I);
  796. CLK(2);
  797. if ( (p_old & f6502_Status_I) &&
  798. (core->interrupts & f6502_Int_IRQ)) {
  799. CLK(7);
  800. PUSH16(core, S, PC);
  801. PUSH(core, S, P & ~f6502_Status_B);
  802. SET(P, f6502_Status_I);
  803. PC = f6502_read16(&core->memory,
  804. f6502_Vector_IRQ);
  805. }
  806. } break;
  807. case 0x59: // EOR abs, Y
  808. EOR(D_ABSY);
  809. CLK(4);
  810. break;
  811. // Special: 0x5A
  812. // Undefined: 0x5B
  813. // Special: 0x5C
  814. case 0x5D: // EOR abs, X
  815. EOR(D_ABSX);
  816. CLK(4);
  817. break;
  818. case 0x5E: // LSR abs, X
  819. LSR(A_ABSX);
  820. CLK(7);
  821. break;
  822. // Undefined: 0x5F
  823. case 0x60: // RTS
  824. POP16(core, S, PC);
  825. ++PC;
  826. CLK(6);
  827. break;
  828. case 0x61: // ADC (zp, X)
  829. ADC(D_IX);
  830. CLK(6);
  831. break;
  832. // Undefined: 0x62 - 0x63
  833. // Special: 0x64
  834. case 0x65: // ADC zp
  835. ADC(D_ZP);
  836. CLK(3);
  837. break;
  838. case 0x66: // ROR zp
  839. ROR(A_ZP);
  840. CLK(5);
  841. break;
  842. // Undefined: 0x67
  843. case 0x68: // PLA
  844. POP(core, S, A);
  845. TEST(A);
  846. CLK(4);
  847. break;
  848. case 0x69: // ADC imm
  849. ADC(D_IMM);
  850. CLK(2);
  851. break;
  852. case 0x6A: // ROR A
  853. ROR_A();
  854. CLK(2);
  855. break;
  856. // Undefined: 0x6B
  857. case 0x6C: // JMP (abs)
  858. { // Reproduce the indirect addressing bug
  859. register uint16_t addr = A_ABS;
  860. register uint8_t addr_lo = f6502_read(&core->memory,
  861. addr);
  862. if ((addr & 0xFFU) == 0xFFU) {
  863. addr = f6502_read(&core->memory, addr - 0xffU);
  864. } else {
  865. addr = f6502_read(&core->memory, addr + 1);
  866. }
  867. JMP(addr_lo | (addr << 8));
  868. CLK(5);
  869. } break;
  870. case 0x6D: // ADC abs
  871. ADC(D_ABS);
  872. CLK(4);
  873. break;
  874. case 0x6E: // ROR abs
  875. ROR(A_ABS);
  876. CLK(6);
  877. break;
  878. // Undefined: 0x6F
  879. case 0x70: // BVS
  880. BIF(P & f6502_Status_V);
  881. break;
  882. case 0x71: // ADC (zp), Y
  883. ADC(D_IY);
  884. CLK(5);
  885. break;
  886. // Undefined: 0x72 - 0x73
  887. // Special: 0x74
  888. case 0x75: // ADC zp, X
  889. ADC(D_ZPX);
  890. CLK(4);
  891. break;
  892. case 0x76: // ROR zp, X
  893. ROR(A_ZPX);
  894. CLK(6);
  895. break;
  896. // Undefined: 0x77
  897. case 0x78: // SEI
  898. SET(P, f6502_Status_I);
  899. CLK(2);
  900. break;
  901. case 0x79: // ADC abs, Y
  902. ADC(D_ABSY);
  903. CLK(4);
  904. break;
  905. // Special: 0x7A
  906. // Undefined: 0x7B
  907. // Special: 0x7C
  908. case 0x7D: // ADC abs, X
  909. ADC(D_ABSX);
  910. CLK(4);
  911. break;
  912. case 0x7E: // ROR abs, X
  913. ROR(A_ABSX);
  914. CLK(7);
  915. break;
  916. // Undefined: 0x7F
  917. // Special: 0x80
  918. case 0x81: // STA (zp, X)
  919. ST(A, A_IX);
  920. CLK(6);
  921. break;
  922. // Special: 0x82
  923. // Undefined: 0x83
  924. case 0x84: // STY zp
  925. ST(Y, A_ZP);
  926. CLK(3);
  927. break;
  928. case 0x85: // STA zp
  929. ST(A, A_ZP);
  930. CLK(3);
  931. break;
  932. case 0x86: // STX zp
  933. ST(X, A_ZP);
  934. CLK(3);
  935. break;
  936. // Undefined: 0x87
  937. case 0x88: // DEY
  938. --Y;
  939. TEST(Y);
  940. CLK(2);
  941. break;
  942. // Undefined: 0x89
  943. case 0x8A: // TXA
  944. A = X;
  945. TEST(A);
  946. CLK(2);
  947. break;
  948. // Undefined: 0x8B
  949. case 0x8C: // STY abs
  950. ST(Y, A_ABS);
  951. CLK(4);
  952. break;
  953. case 0x8D: // STA abs
  954. ST(A, A_ABS);
  955. CLK(4);
  956. break;
  957. case 0x8E: // STX abs
  958. ST(X, A_ABS);
  959. CLK(4);
  960. break;
  961. case 0x90: // BCC
  962. BIF(!(P & f6502_Status_C));
  963. break;
  964. case 0x91: // STA (zp), Y
  965. ST(A, A_IY);
  966. CLK(6);
  967. break;
  968. // Undefined: 0x92 - 0x93
  969. case 0x94: // STY zp, X
  970. ST(Y, A_ZPX);
  971. CLK(4);
  972. break;
  973. case 0x95: // STA zp, X
  974. ST(A, A_ZPX);
  975. CLK(4);
  976. break;
  977. case 0x96: // STX zp, Y
  978. ST(X, A_ZPY);
  979. CLK(4);
  980. break;
  981. // Undefined: 0x97
  982. case 0x98: // TYA
  983. A = Y;
  984. TEST(A);
  985. CLK(2);
  986. break;
  987. case 0x99: // STA abs, Y
  988. ST(A, A_ABSY);
  989. CLK(5);
  990. break;
  991. case 0x9A: // TXS
  992. S = X;
  993. CLK(2);
  994. break;
  995. // Undefined: 0x9B - 0x9C
  996. case 0x9D: // STA abs, X
  997. ST(A, A_ABSX);
  998. CLK(5);
  999. break;
  1000. // Undefined: 0x9E - 0x9F
  1001. case 0xA0: // LDY imm
  1002. LD(Y, D_IMM);
  1003. CLK(2);
  1004. break;
  1005. case 0xA1: // LDA (zp, X)
  1006. LD(A, D_IX);
  1007. CLK(6);
  1008. break;
  1009. case 0xA2: // LDX imm
  1010. LD(X, D_IMM);
  1011. CLK(2);
  1012. break;
  1013. // Undefined: 0xA3
  1014. case 0xA4: // LDY zp
  1015. LD(Y, D_ZP);
  1016. CLK(3);
  1017. break;
  1018. case 0xA5: // LDA zp
  1019. LD(A, D_ZP);
  1020. CLK(3);
  1021. break;
  1022. case 0xA6: // LDX zp
  1023. LD(X, D_ZP);
  1024. CLK(3);
  1025. break;
  1026. // Undefined: 0xA7
  1027. case 0xA8: // TAY
  1028. Y = A;
  1029. TEST(A);
  1030. CLK(2);
  1031. break;
  1032. case 0xA9: // LDA imm
  1033. LD(A, D_IMM);
  1034. CLK(2);
  1035. break;
  1036. case 0xAA: // TAX
  1037. X = A;
  1038. TEST(A);
  1039. CLK(2);
  1040. break;
  1041. // Undefined: 0xAB
  1042. case 0xAC: // LDY abs
  1043. LD(Y, D_ABS);
  1044. CLK(4);
  1045. break;
  1046. case 0xAD: // LDA abs
  1047. LD(A, D_ABS);
  1048. CLK(4);
  1049. break;
  1050. case 0xAE: // LDX abs
  1051. LD(X, D_ABS);
  1052. CLK(4);
  1053. break;
  1054. // Undefined: 0xAF
  1055. case 0xB0: // BCS
  1056. BIF(P & f6502_Status_C);
  1057. break;
  1058. case 0xB1: // LDA (zp), Y
  1059. LD(A, D_IY);
  1060. CLK(5);
  1061. break;
  1062. // Undefined: 0xB2 - 0xB3
  1063. case 0xB4: // LDY zp, X
  1064. LD(Y, D_ZPX);
  1065. CLK(4);
  1066. break;
  1067. case 0xB5: // LDA zp, X
  1068. LD(A, D_ZPX);
  1069. CLK(4);
  1070. break;
  1071. case 0xB6: // LDX zp, Y
  1072. LD(X, D_ZPY);
  1073. CLK(4);
  1074. break;
  1075. // Undefined: 0xB7
  1076. case 0xB8: // CLV
  1077. CLR(P, f6502_Status_V);
  1078. CLK(2);
  1079. break;
  1080. case 0xB9: // LDA abs, Y
  1081. LD(A, D_ABSY);
  1082. CLK(4);
  1083. break;
  1084. case 0xBA: // TSX
  1085. X = S;
  1086. TEST(X);
  1087. CLK(2);
  1088. break;
  1089. // Undefined: 0xBB
  1090. case 0xBC: // LDY abs, X
  1091. LD(Y, D_ABSX);
  1092. CLK(4);
  1093. break;
  1094. case 0xBD: // LDA abs, X
  1095. LD(A, D_ABSX);
  1096. CLK(4);
  1097. break;
  1098. case 0xBE: // LDX abs, Y
  1099. LD(X, D_ABSY);
  1100. CLK(4);
  1101. break;
  1102. // Undefined: 0xBF
  1103. case 0xC0: // CPY imm
  1104. CP(Y, D_IMM);
  1105. CLK(2);
  1106. break;
  1107. case 0xC1: // CMP (zp, X)
  1108. CP(A, D_IX);
  1109. CLK(6);
  1110. break;
  1111. // Special: 0xC2
  1112. // Undefined: 0xC3
  1113. case 0xC4: // CPY zp
  1114. CP(Y, D_ZP);
  1115. CLK(3);
  1116. break;
  1117. case 0xC5: // CMP zp
  1118. CP(A, D_ZP);
  1119. CLK(3);
  1120. break;
  1121. case 0xC6: // DEC zp
  1122. DEC(A_ZP);
  1123. CLK(5);
  1124. break;
  1125. // Undefined: 0xC7
  1126. case 0xC8: // INY
  1127. ++Y;
  1128. TEST(Y);
  1129. CLK(2);
  1130. break;
  1131. case 0xC9: // CMP imm
  1132. CP(A, D_IMM);
  1133. CLK(2);
  1134. break;
  1135. case 0xCA: // DEX
  1136. --X;
  1137. TEST(X);
  1138. CLK(2);
  1139. break;
  1140. // Undefined: 0xCB
  1141. case 0xCC: // CPY abs
  1142. CP(Y, D_ABS);
  1143. CLK(4);
  1144. break;
  1145. case 0xCD: // CMP abs
  1146. CP(A, D_ABS);
  1147. CLK(4);
  1148. break;
  1149. case 0xCE: // DEC abs
  1150. DEC(A_ABS);
  1151. CLK(6);
  1152. break;
  1153. // Undefined: 0xCF
  1154. case 0xD0: // BNE
  1155. BIF(!(P & f6502_Status_Z));
  1156. break;
  1157. case 0xD1: // CMP (zp), Y
  1158. CP(A, D_IY);
  1159. CLK(5);
  1160. break;
  1161. // Undefined: 0xD2 - 0xD3
  1162. // Special: 0xD4
  1163. case 0xD5: // CMP zp, X
  1164. CP(A, D_ZPX);
  1165. CLK(4);
  1166. break;
  1167. case 0xD6: // DEC zp, X
  1168. DEC(A_ZPX);
  1169. CLK(6);
  1170. break;
  1171. // Undefined: 0xD7
  1172. case 0xD8: // CLD
  1173. CLR(P, f6502_Status_D);
  1174. CLK(2);
  1175. break;
  1176. case 0xD9: // CMP abs, Y
  1177. CP(A, D_ABSY);
  1178. CLK(4);
  1179. break;
  1180. // Special: 0xDA
  1181. // Undefined: 0xDB
  1182. // Special: 0xDC
  1183. case 0xDD: // CMP abs, X
  1184. CP(A, D_ABSX);
  1185. CLK(4);
  1186. break;
  1187. case 0xDE: // DEC abs, X
  1188. DEC(A_ABSX);
  1189. CLK(7);
  1190. break;
  1191. // Undefined: 0xDF
  1192. case 0xE0: // CPX imm
  1193. CP(X, D_IMM);
  1194. CLK(2);
  1195. break;
  1196. case 0xE1: // SBC (xp, X)
  1197. SBC(D_IX);
  1198. CLK(6);
  1199. break;
  1200. // Special: 0xE2
  1201. // Undefined: 0xE3
  1202. case 0xE4: // CPX zp
  1203. CP(X, D_ZP);
  1204. CLK(3);
  1205. break;
  1206. case 0xE5: // SBC zp
  1207. SBC(D_ZP);
  1208. CLK(3);
  1209. break;
  1210. case 0xE6: // INC zp
  1211. INC(A_ZP);
  1212. CLK(5);
  1213. break;
  1214. case 0xE8: // INX
  1215. ++X;
  1216. TEST(X);
  1217. CLK(2);
  1218. break;
  1219. case 0xE9: // SBC imm
  1220. SBC(D_IMM);
  1221. CLK(2);
  1222. break;
  1223. case 0xEA: // NOP
  1224. CLK(2);
  1225. break;
  1226. // Undefined: 0xEB
  1227. case 0xEC: // CPX abs
  1228. CP(X, D_ABS);
  1229. CLK(4);
  1230. break;
  1231. case 0xED: // SBC abs
  1232. SBC(D_ABS);
  1233. CLK(4);
  1234. break;
  1235. case 0xEE: // INC abs
  1236. INC(A_ABS);
  1237. CLK(6);
  1238. break;
  1239. // Undefined: 0xEF
  1240. case 0xF0: // BEQ
  1241. BIF(P & f6502_Status_Z);
  1242. break;
  1243. case 0xF1: // SBC (zp), Y
  1244. SBC(D_IY);
  1245. CLK(5);
  1246. break;
  1247. // Undefined: 0xF2 - 0xF3
  1248. // Special: 0xF4
  1249. case 0xF5: // SBC zp, X
  1250. SBC(D_ZPX);
  1251. CLK(4);
  1252. break;
  1253. case 0xF6: // INC zp, X
  1254. INC(A_ZPX);
  1255. CLK(6);
  1256. break;
  1257. // Undefined: 0xF7
  1258. case 0xF8: // SED
  1259. SET(P, f6502_Status_D);
  1260. CLK(2);
  1261. break;
  1262. case 0xF9: // SBC abs, Y
  1263. SBC(D_ABSY);
  1264. CLK(4);
  1265. break;
  1266. // Special: 0xFA
  1267. // Undefined: 0xFB
  1268. // Special: 0xFC
  1269. case 0xFD: // SBC abs, X
  1270. SBC(D_ABSX);
  1271. CLK(4);
  1272. break;
  1273. case 0xFE: // INC abs, X
  1274. INC(A_ABSX);
  1275. CLK(7);
  1276. break;
  1277. /* "Special" i.e. "unofficial" instructions */
  1278. /* Timing & progression only, no side effects */
  1279. // DOP, 2 Cycles
  1280. case 0x80:
  1281. case 0x82:
  1282. case 0x89:
  1283. case 0xC2:
  1284. case 0xE2:
  1285. ++PC;
  1286. CLK(2);
  1287. break;
  1288. // DOP, 3 Cycles
  1289. case 0x04:
  1290. case 0x44:
  1291. case 0x64:
  1292. ++PC;
  1293. CLK(3);
  1294. break;
  1295. // DOP, 4 Cycles
  1296. case 0x14:
  1297. case 0x34:
  1298. case 0x54:
  1299. case 0x74:
  1300. case 0xD4:
  1301. case 0xF4:
  1302. ++PC;
  1303. CLK(4);
  1304. break;
  1305. // TOP, 4 Cycles
  1306. case 0x1C:
  1307. case 0x3C:
  1308. case 0x5C:
  1309. case 0x7C:
  1310. case 0xDC:
  1311. case 0xFC:
  1312. PC += 2;
  1313. CLK(4);
  1314. break;
  1315. // NOP, 2 Cycles
  1316. default:
  1317. CLK(2);
  1318. break;
  1319. }
  1320. }
  1321. #ifdef F6502_TRACE
  1322. // if (int_trig) printf("Possible interrupt trigger\n");
  1323. #endif
  1324. #ifdef F6502_HCF
  1325. step_done:
  1326. #endif
  1327. core->registers = (f6502_Registers){
  1328. .PC = PC,
  1329. .S = S,
  1330. .A = A,
  1331. .X = X,
  1332. .Y = Y,
  1333. .P = P,
  1334. };
  1335. return clocks_elapsed;
  1336. }
  1337. int f6502_step(f6502_Core* core, int clocks) {
  1338. int clocks_elapsed = 0;
  1339. // TODO: Why are we processing seven clocks prior to NMI?
  1340. // This passes the interrupt test with 6 steps
  1341. /*
  1342. if (f6502_nmi_ready(core)) {
  1343. clocks_elapsed += f6502_do_step(core, 7);
  1344. clocks -= clocks_elapsed;
  1345. }
  1346. */
  1347. clocks_elapsed += f6502_check_interrupts(core);
  1348. return ( f6502_do_step(core, clocks - clocks_elapsed) +
  1349. clocks_elapsed);
  1350. }