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.
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.

1698 lines
44KB

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