Advertisement
Guest User

6502.c

a guest
Jan 30th, 2025
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 68.14 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #define SDL_MAIN_HANDLED
  3. #include <SDL.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdint.h>
  7. #include <string.h>
  8.  
  9. // Define CPU state
  10. typedef struct {
  11. uint8_t A; // Accumulator
  12. uint8_t X; // X Register
  13. uint8_t Y; // Y Register
  14. uint8_t SP; // Stack Pointer
  15. uint16_t PC; // Program Counter
  16. uint8_t P; // Status Register
  17. uint8_t mem[65536]; // 64KB RAM
  18. } CPU;
  19.  
  20. // Status Register Flags
  21. #define FLAG_N 0x80 // Negative
  22. #define FLAG_V 0x40 // Overflow
  23. #define FLAG_B 0x10 // Break
  24. #define FLAG_D 0x08 // Decimal
  25. #define FLAG_I 0x04 // Interrupt
  26. #define FLAG_Z 0x02 // Zero
  27. #define FLAG_C 0x01 // Carry
  28.  
  29. // Function prototypes
  30. void reset(CPU* cpu);
  31. void load_rom(CPU* cpu, const char* filename, uint16_t address);
  32. void dump_memory(CPU* cpu, uint16_t start, uint16_t end);
  33. void dump_registers(CPU* cpu);
  34. uint8_t fetch_byte(CPU* cpu);
  35. uint16_t fetch_word(CPU* cpu);
  36. void push_byte(CPU* cpu, uint8_t val);
  37. uint8_t pull_byte(CPU* cpu);
  38. void set_zero_and_negative_flags(CPU* cpu, uint8_t value);
  39. void branch(CPU* cpu, int8_t offset);
  40. uint16_t get_address(CPU* cpu, uint8_t mode);
  41. void execute_instruction(CPU* cpu);
  42. void handle_interrupt(CPU* cpu, uint16_t vector);
  43.  
  44.  
  45. // Addressing Mode Constants
  46. #define AM_IMM 0 // Immediate
  47. #define AM_ZP 1 // Zero Page
  48. #define AM_ZPX 2 // Zero Page,X
  49. #define AM_ZPY 3 // Zero Page,Y
  50. #define AM_IZX 4 // (Zero Page,X)
  51. #define AM_IZY 5 // (Zero Page),Y
  52. #define AM_ABS 6 // Absolute
  53. #define AM_ABX 7 // Absolute,X
  54. #define AM_ABY 8 // Absolute,Y
  55. #define AM_IND 9 // Indirect
  56. #define AM_REL 10 // Relative
  57. #define AM_IMP 11 // Implied
  58.  
  59. SDL_Window* window = NULL;
  60. SDL_Renderer* renderer = NULL;
  61. SDL_Texture* texture = NULL;
  62. uint32_t pixels[160 * 160]; // Assuming 160x160 screen resolution
  63.  
  64. //Color palette
  65. uint32_t palette[16] = {
  66. 0x000000ff, // Black
  67. 0xffffffff, // White
  68. 0xff0000ff, // Red
  69. 0x00ffffff, // Cyan
  70. 0xff00ffff, // Purple
  71. 0x00ff00ff, // Green
  72. 0x0000ffff, // Blue
  73. 0xffff00ff, // Yellow
  74. 0xffa500ff, // Orange
  75. 0xa52a2aff, // Brown
  76. 0xff69b4ff, // Light red
  77. 0x696969ff, // Dark grey
  78. 0x808080ff, // Grey
  79. 0x90ee90ff, //Light Green
  80. 0xadd8e6ff, //Light Blue
  81. 0xd3d3d3ff // Light grey
  82.  
  83. };
  84.  
  85. int init_sdl() {
  86. if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  87. fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
  88. return 1;
  89. }
  90.  
  91. window = SDL_CreateWindow("6502 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 160 * 2, 160 * 2, SDL_WINDOW_SHOWN);
  92. if (window == NULL) {
  93. fprintf(stderr, "Window could not be created! SDL_Error: %s\n", SDL_GetError());
  94. return 1;
  95. }
  96.  
  97. renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
  98. if (renderer == NULL) {
  99. fprintf(stderr, "Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
  100. return 1;
  101. }
  102. texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 160, 160);
  103. if (texture == NULL)
  104. {
  105. fprintf(stderr, "Texture could not be created! SDL_Error: %s\n", SDL_GetError());
  106. return 1;
  107. }
  108.  
  109. memset(pixels, 0, sizeof(pixels));
  110.  
  111.  
  112. return 0;
  113. }
  114.  
  115. void render_screen()
  116. {
  117. SDL_UpdateTexture(texture, NULL, pixels, 160 * sizeof(uint32_t));
  118. SDL_RenderClear(renderer);
  119. SDL_RenderCopy(renderer, texture, NULL, NULL);
  120. SDL_RenderPresent(renderer);
  121. }
  122.  
  123. int main() {
  124. CPU cpu;
  125. char rom_filename[256];
  126. uint16_t rom_load_address = 0x600; // Default ROM load address
  127.  
  128. if (init_sdl() != 0)
  129. {
  130. return 1;
  131. }
  132.  
  133. reset(&cpu); // Initialize the CPU
  134.  
  135. printf("Enter ROM filename: ");
  136. scanf("%s", rom_filename);
  137.  
  138. // Load the rom
  139. load_rom(&cpu, rom_filename, rom_load_address);
  140. cpu.PC = rom_load_address;
  141.  
  142. // Execution loop
  143. SDL_Event event;
  144. int cycles = 0;
  145. while (cycles < 100000)
  146. {
  147. if (SDL_PollEvent(&event))
  148. {
  149. if (event.type == SDL_QUIT)
  150. {
  151. cycles = 1000000;
  152. break;
  153. }
  154. }
  155. execute_instruction(&cpu);
  156. cycles++;
  157. render_screen();
  158. if (cpu.PC == 0xFFFF)
  159. break;
  160. }
  161.  
  162.  
  163. printf("\n--- CPU State ---\n");
  164. dump_registers(&cpu);
  165. printf("\n--- Memory Dump ---\n");
  166. dump_memory(&cpu, rom_load_address - 10, rom_load_address + 100);
  167.  
  168. SDL_DestroyTexture(texture);
  169. SDL_DestroyRenderer(renderer);
  170. SDL_DestroyWindow(window);
  171. SDL_Quit();
  172.  
  173. return 0;
  174. }
  175.  
  176. void reset(CPU* cpu) {
  177. memset(cpu, 0, sizeof(CPU));
  178. cpu->SP = 0xFF;
  179. // Set the unused bit in status reg
  180. cpu->P |= 0x20;
  181.  
  182. // Load the reset vector
  183. cpu->mem[0xFFFC] = 0x00;
  184. cpu->mem[0xFFFD] = 0x80;
  185.  
  186. // Seed the random number generator
  187. srand(time(NULL));
  188.  
  189. }
  190.  
  191. void load_rom(CPU* cpu, const char* filename, uint16_t address) {
  192. FILE* fp = fopen(filename, "rb");
  193. if (!fp) {
  194. perror("Error opening ROM file");
  195. exit(EXIT_FAILURE);
  196. }
  197.  
  198. fseek(fp, 0, SEEK_END);
  199. long rom_size = ftell(fp);
  200. fseek(fp, 0, SEEK_SET);
  201.  
  202. if (rom_size > 65536 - address) {
  203. fprintf(stderr, "Error: ROM too large to fit in memory.\n");
  204. fclose(fp);
  205. exit(EXIT_FAILURE);
  206. }
  207.  
  208. fread(&cpu->mem[address], 1, rom_size, fp);
  209. fclose(fp);
  210. printf("Loaded ROM '%s' into memory at $%04X. Size %ld bytes\n", filename, address, rom_size);
  211. }
  212.  
  213. void dump_memory(CPU* cpu, uint16_t start, uint16_t end) {
  214. for (uint16_t i = start; i <= end; ++i) {
  215. printf("$%04X: %02X ", i, cpu->mem[i]);
  216. if ((i - start + 1) % 8 == 0) {
  217. printf("\n");
  218. }
  219. }
  220. printf("\n");
  221. }
  222.  
  223.  
  224. void dump_registers(CPU* cpu) {
  225. printf("A: $%02X\n", cpu->A);
  226. printf("X: $%02X\n", cpu->X);
  227. printf("Y: $%02X\n", cpu->Y);
  228. printf("SP: $%02X\n", cpu->SP);
  229. printf("PC: $%04X\n", cpu->PC);
  230. printf("P: $%02X (N=%d, V=%d, B=%d, D=%d, I=%d, Z=%d, C=%d)\n", cpu->P,
  231. (cpu->P & FLAG_N) ? 1 : 0,
  232. (cpu->P & FLAG_V) ? 1 : 0,
  233. (cpu->P & FLAG_B) ? 1 : 0,
  234. (cpu->P & FLAG_D) ? 1 : 0,
  235. (cpu->P & FLAG_I) ? 1 : 0,
  236. (cpu->P & FLAG_Z) ? 1 : 0,
  237. (cpu->P & FLAG_C) ? 1 : 0);
  238. }
  239.  
  240.  
  241. uint8_t fetch_byte(CPU* cpu) {
  242. return cpu->mem[cpu->PC++];
  243. }
  244.  
  245.  
  246. uint16_t fetch_word(CPU* cpu) {
  247. uint16_t low = cpu->mem[cpu->PC++];
  248. uint16_t high = cpu->mem[cpu->PC++];
  249. return (high << 8) | low;
  250. }
  251.  
  252. void push_byte(CPU* cpu, uint8_t val)
  253. {
  254. cpu->mem[0x100 + cpu->SP] = val;
  255. cpu->SP--;
  256. }
  257.  
  258. uint8_t pull_byte(CPU* cpu)
  259. {
  260. cpu->SP++;
  261. return cpu->mem[0x100 + cpu->SP];
  262. }
  263.  
  264. void set_zero_and_negative_flags(CPU* cpu, uint8_t value)
  265. {
  266. cpu->P &= ~(FLAG_N | FLAG_Z);
  267. if (value == 0)
  268. cpu->P |= FLAG_Z;
  269. if (value & 0x80)
  270. cpu->P |= FLAG_N;
  271. }
  272.  
  273. void branch(CPU* cpu, int8_t offset)
  274. {
  275. cpu->PC += offset;
  276. }
  277.  
  278. uint16_t get_address(CPU* cpu, uint8_t mode)
  279. {
  280. uint16_t address = 0;
  281. uint8_t zp_addr;
  282. uint16_t abs_addr;
  283. uint8_t temp_byte;
  284.  
  285.  
  286. switch (mode)
  287. {
  288. case AM_IMM:
  289. address = cpu->PC++;
  290. break;
  291. case AM_ZP:
  292. zp_addr = fetch_byte(cpu);
  293. address = zp_addr;
  294. break;
  295. case AM_ZPX:
  296. zp_addr = fetch_byte(cpu);
  297. address = (zp_addr + cpu->X) & 0xFF;
  298. break;
  299. case AM_ZPY:
  300. zp_addr = fetch_byte(cpu);
  301. address = (zp_addr + cpu->Y) & 0xFF;
  302. break;
  303. case AM_IZX:
  304. zp_addr = fetch_byte(cpu);
  305. temp_byte = (zp_addr + cpu->X) & 0xFF;
  306. address = cpu->mem[temp_byte] | (cpu->mem[(temp_byte + 1) & 0xFF] << 8);
  307. break;
  308. case AM_IZY:
  309. zp_addr = fetch_byte(cpu);
  310. address = cpu->mem[zp_addr] | (cpu->mem[(zp_addr + 1) & 0xFF] << 8);
  311. address += cpu->Y;
  312. break;
  313. case AM_ABS:
  314. address = fetch_word(cpu);
  315. break;
  316. case AM_ABX:
  317. address = fetch_word(cpu);
  318. address += cpu->X;
  319. break;
  320. case AM_ABY:
  321. address = fetch_word(cpu);
  322. address += cpu->Y;
  323. break;
  324. case AM_IND:
  325. abs_addr = fetch_word(cpu);
  326. address = cpu->mem[abs_addr] | (cpu->mem[(abs_addr & 0xFF00) | ((abs_addr + 1) & 0xFF)] << 8);
  327.  
  328. break;
  329. case AM_REL:
  330. address = cpu->PC + (int8_t)fetch_byte(cpu);
  331. break;
  332.  
  333. default:
  334. break;
  335.  
  336. }
  337. return address;
  338. }
  339.  
  340. void execute_instruction(CPU* cpu) {
  341. uint8_t opcode = fetch_byte(cpu);
  342. uint16_t address = 0;
  343. uint8_t value = 0;
  344. uint16_t temp_word = 0;
  345. uint8_t temp_byte = 0;
  346. uint8_t temp_carry = 0;
  347.  
  348. switch (opcode)
  349. {
  350. // --- 0x ---
  351. case 0x00: // BRK
  352. push_byte(cpu, cpu->PC >> 8);
  353. push_byte(cpu, cpu->PC & 0xFF);
  354. push_byte(cpu, cpu->P | FLAG_B);
  355. cpu->P |= FLAG_I; // Set interrupt flag
  356. cpu->PC = (cpu->mem[0xFFFE] | (cpu->mem[0xFFFF] << 8)); // Load interrupt vector
  357. break;
  358. case 0x01: // ORA izx
  359. address = get_address(cpu, AM_IZX);
  360. cpu->A |= cpu->mem[address];
  361. set_zero_and_negative_flags(cpu, cpu->A);
  362. break;
  363. case 0x02: // KIL
  364. case 0x12:
  365. case 0x22:
  366. case 0x32:
  367. case 0x42:
  368. case 0x52:
  369. case 0x62:
  370. case 0x72:
  371. case 0x92:
  372. case 0xB2:
  373. case 0xD2:
  374. case 0xF2:
  375. printf("KIL Instruction executed, halting.\n");
  376. cpu->PC = 0xFFFF;
  377. break;
  378. case 0x03: // SLO izx
  379. address = get_address(cpu, AM_IZX);
  380. value = cpu->mem[address];
  381. cpu->P &= ~FLAG_C;
  382. if (value & 0x80)
  383. cpu->P |= FLAG_C;
  384. cpu->mem[address] = value << 1;
  385. cpu->A |= cpu->mem[address];
  386. set_zero_and_negative_flags(cpu, cpu->A);
  387. break;
  388. case 0x04: // NOP zp
  389. get_address(cpu, AM_ZP);
  390. break;
  391. case 0x05: // ORA zp
  392. address = get_address(cpu, AM_ZP);
  393. cpu->A |= cpu->mem[address];
  394. set_zero_and_negative_flags(cpu, cpu->A);
  395. break;
  396. case 0x06: // ASL zp
  397. address = get_address(cpu, AM_ZP);
  398. value = cpu->mem[address];
  399. cpu->P &= ~FLAG_C;
  400. if (value & 0x80)
  401. cpu->P |= FLAG_C;
  402. cpu->mem[address] = value << 1;
  403. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  404. break;
  405. case 0x07: // SLO zp
  406. address = get_address(cpu, AM_ZP);
  407. value = cpu->mem[address];
  408. cpu->P &= ~FLAG_C;
  409. if (value & 0x80)
  410. cpu->P |= FLAG_C;
  411. cpu->mem[address] = value << 1;
  412. cpu->A |= cpu->mem[address];
  413. set_zero_and_negative_flags(cpu, cpu->A);
  414. break;
  415. case 0x08: // PHP
  416. push_byte(cpu, cpu->P);
  417. break;
  418. case 0x09: // ORA imm
  419. address = get_address(cpu, AM_IMM);
  420. cpu->A |= cpu->mem[address];
  421. set_zero_and_negative_flags(cpu, cpu->A);
  422. break;
  423. case 0x0A: // ASL
  424. cpu->P &= ~FLAG_C;
  425. if (cpu->A & 0x80)
  426. cpu->P |= FLAG_C;
  427. cpu->A = cpu->A << 1;
  428. set_zero_and_negative_flags(cpu, cpu->A);
  429. break;
  430. case 0x0B: // ANC imm
  431. address = get_address(cpu, AM_IMM);
  432. cpu->A &= cpu->mem[address];
  433. if (cpu->A & 0x80)
  434. cpu->P |= FLAG_C;
  435. else
  436. cpu->P &= ~FLAG_C;
  437. set_zero_and_negative_flags(cpu, cpu->A);
  438.  
  439. break;
  440. case 0x0C: // NOP abs
  441. get_address(cpu, AM_ABS);
  442. break;
  443. case 0x0D: // ORA abs
  444. address = get_address(cpu, AM_ABS);
  445. cpu->A |= cpu->mem[address];
  446. set_zero_and_negative_flags(cpu, cpu->A);
  447. break;
  448. case 0x0E: // ASL abs
  449. address = get_address(cpu, AM_ABS);
  450. value = cpu->mem[address];
  451. cpu->P &= ~FLAG_C;
  452. if (value & 0x80)
  453. cpu->P |= FLAG_C;
  454. cpu->mem[address] = value << 1;
  455. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  456. break;
  457. case 0x0F: // SLO abs
  458. address = get_address(cpu, AM_ABS);
  459. value = cpu->mem[address];
  460. cpu->P &= ~FLAG_C;
  461. if (value & 0x80)
  462. cpu->P |= FLAG_C;
  463. cpu->mem[address] = value << 1;
  464. cpu->A |= cpu->mem[address];
  465. set_zero_and_negative_flags(cpu, cpu->A);
  466. break;
  467.  
  468. // --- 1x ---
  469. case 0x10: // BPL rel
  470. address = get_address(cpu, AM_REL);
  471. if (!(cpu->P & FLAG_N))
  472. cpu->PC = address;
  473. break;
  474. case 0x11: // ORA izy
  475. address = get_address(cpu, AM_IZY);
  476. cpu->A |= cpu->mem[address];
  477. set_zero_and_negative_flags(cpu, cpu->A);
  478. break;
  479. case 0x13: // SLO izy
  480. address = get_address(cpu, AM_IZY);
  481. value = cpu->mem[address];
  482. cpu->P &= ~FLAG_C;
  483. if (value & 0x80)
  484. cpu->P |= FLAG_C;
  485. cpu->mem[address] = value << 1;
  486. cpu->A |= cpu->mem[address];
  487. set_zero_and_negative_flags(cpu, cpu->A);
  488. break;
  489. case 0x14: // NOP zpx
  490. get_address(cpu, AM_ZPX);
  491. break;
  492. case 0x15: // ORA zpx
  493. address = get_address(cpu, AM_ZPX);
  494. cpu->A |= cpu->mem[address];
  495. set_zero_and_negative_flags(cpu, cpu->A);
  496. break;
  497. case 0x16: // ASL zpx
  498. address = get_address(cpu, AM_ZPX);
  499. value = cpu->mem[address];
  500. cpu->P &= ~FLAG_C;
  501. if (value & 0x80)
  502. cpu->P |= FLAG_C;
  503. cpu->mem[address] = value << 1;
  504. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  505. break;
  506. case 0x17: // SLO zpx
  507. address = get_address(cpu, AM_ZPX);
  508. value = cpu->mem[address];
  509. cpu->P &= ~FLAG_C;
  510. if (value & 0x80)
  511. cpu->P |= FLAG_C;
  512. cpu->mem[address] = value << 1;
  513. cpu->A |= cpu->mem[address];
  514. set_zero_and_negative_flags(cpu, cpu->A);
  515. break;
  516. case 0x18: // CLC
  517. cpu->P &= ~FLAG_C;
  518. break;
  519. case 0x19: // ORA aby
  520. address = get_address(cpu, AM_ABY);
  521. cpu->A |= cpu->mem[address];
  522. set_zero_and_negative_flags(cpu, cpu->A);
  523. break;
  524. case 0x1A: // NOP
  525. break;
  526. case 0x1B: // SLO aby
  527. address = get_address(cpu, AM_ABY);
  528. value = cpu->mem[address];
  529. cpu->P &= ~FLAG_C;
  530. if (value & 0x80)
  531. cpu->P |= FLAG_C;
  532. cpu->mem[address] = value << 1;
  533. cpu->A |= cpu->mem[address];
  534. set_zero_and_negative_flags(cpu, cpu->A);
  535. break;
  536. case 0x1C: // NOP abx
  537. get_address(cpu, AM_ABX);
  538. break;
  539. case 0x1D: // ORA abx
  540. address = get_address(cpu, AM_ABX);
  541. cpu->A |= cpu->mem[address];
  542. set_zero_and_negative_flags(cpu, cpu->A);
  543. break;
  544. case 0x1E: // ASL abx
  545. address = get_address(cpu, AM_ABX);
  546. value = cpu->mem[address];
  547. cpu->P &= ~FLAG_C;
  548. if (value & 0x80)
  549. cpu->P |= FLAG_C;
  550. cpu->mem[address] = value << 1;
  551. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  552. break;
  553. case 0x1F: // SLO abx
  554. address = get_address(cpu, AM_ABX);
  555. value = cpu->mem[address];
  556. cpu->P &= ~FLAG_C;
  557. if (value & 0x80)
  558. cpu->P |= FLAG_C;
  559. cpu->mem[address] = value << 1;
  560. cpu->A |= cpu->mem[address];
  561. set_zero_and_negative_flags(cpu, cpu->A);
  562. break;
  563.  
  564. // --- 2x ---
  565. case 0x20: // JSR abs
  566. push_byte(cpu, cpu->PC >> 8);
  567. push_byte(cpu, cpu->PC & 0xFF);
  568. cpu->PC = get_address(cpu, AM_ABS);
  569. break;
  570. case 0x21: // AND izx
  571. address = get_address(cpu, AM_IZX);
  572. cpu->A &= cpu->mem[address];
  573. set_zero_and_negative_flags(cpu, cpu->A);
  574. break;
  575. case 0x23: // RLA izx
  576. address = get_address(cpu, AM_IZX);
  577. value = cpu->mem[address];
  578. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  579. cpu->P &= ~FLAG_C;
  580. if (value & 0x80)
  581. cpu->P |= FLAG_C;
  582. cpu->mem[address] = (value << 1) | temp_carry;
  583. cpu->A &= cpu->mem[address];
  584. set_zero_and_negative_flags(cpu, cpu->A);
  585. break;
  586. case 0x24: // BIT zp
  587. address = get_address(cpu, AM_ZP);
  588. value = cpu->mem[address];
  589. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z);
  590. if (value & FLAG_N)
  591. cpu->P |= FLAG_N;
  592. if (value & FLAG_V)
  593. cpu->P |= FLAG_V;
  594. if (!(cpu->A & value))
  595. cpu->P |= FLAG_Z;
  596. break;
  597. case 0x25: // AND zp
  598. address = get_address(cpu, AM_ZP);
  599. cpu->A &= cpu->mem[address];
  600. set_zero_and_negative_flags(cpu, cpu->A);
  601. break;
  602. case 0x26: // ROL zp
  603. address = get_address(cpu, AM_ZP);
  604. value = cpu->mem[address];
  605. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  606. cpu->P &= ~FLAG_C;
  607. if (value & 0x80)
  608. cpu->P |= FLAG_C;
  609. cpu->mem[address] = (value << 1) | temp_carry;
  610. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  611. break;
  612. case 0x27: // RLA zp
  613. address = get_address(cpu, AM_ZP);
  614. value = cpu->mem[address];
  615. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  616. cpu->P &= ~FLAG_C;
  617. if (value & 0x80)
  618. cpu->P |= FLAG_C;
  619. cpu->mem[address] = (value << 1) | temp_carry;
  620. cpu->A &= cpu->mem[address];
  621. set_zero_and_negative_flags(cpu, cpu->A);
  622. break;
  623. case 0x28: // PLP
  624. cpu->P = pull_byte(cpu);
  625. cpu->P |= 0x20; // Ensure B flag is always 1
  626. break;
  627. case 0x29: // AND imm
  628. address = get_address(cpu, AM_IMM);
  629. cpu->A &= cpu->mem[address];
  630. set_zero_and_negative_flags(cpu, cpu->A);
  631. break;
  632. case 0x2A: // ROL
  633. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  634. cpu->P &= ~FLAG_C;
  635. if (cpu->A & 0x80)
  636. cpu->P |= FLAG_C;
  637. cpu->A = (cpu->A << 1) | temp_carry;
  638. set_zero_and_negative_flags(cpu, cpu->A);
  639. break;
  640. case 0x2B: // ANC imm
  641. address = get_address(cpu, AM_IMM);
  642. cpu->A &= cpu->mem[address];
  643. if (cpu->A & 0x80)
  644. cpu->P |= FLAG_C;
  645. else
  646. cpu->P &= ~FLAG_C;
  647. set_zero_and_negative_flags(cpu, cpu->A);
  648.  
  649. break;
  650. case 0x2C: // BIT abs
  651. address = get_address(cpu, AM_ABS);
  652. value = cpu->mem[address];
  653. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z);
  654. if (value & FLAG_N)
  655. cpu->P |= FLAG_N;
  656. if (value & FLAG_V)
  657. cpu->P |= FLAG_V;
  658. if (!(cpu->A & value))
  659. cpu->P |= FLAG_Z;
  660. break;
  661. case 0x2D: // AND abs
  662. address = get_address(cpu, AM_ABS);
  663. cpu->A &= cpu->mem[address];
  664. set_zero_and_negative_flags(cpu, cpu->A);
  665. break;
  666. case 0x2E: // ROL abs
  667. address = get_address(cpu, AM_ABS);
  668. value = cpu->mem[address];
  669. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  670. cpu->P &= ~FLAG_C;
  671. if (value & 0x80)
  672. cpu->P |= FLAG_C;
  673. cpu->mem[address] = (value << 1) | temp_carry;
  674. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  675. break;
  676. case 0x2F: // RLA abs
  677. address = get_address(cpu, AM_ABS);
  678. value = cpu->mem[address];
  679. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  680. cpu->P &= ~FLAG_C;
  681. if (value & 0x80)
  682. cpu->P |= FLAG_C;
  683. cpu->mem[address] = (value << 1) | temp_carry;
  684. cpu->A &= cpu->mem[address];
  685. set_zero_and_negative_flags(cpu, cpu->A);
  686. break;
  687.  
  688. // --- 3x ---
  689. case 0x30: // BMI rel
  690. address = get_address(cpu, AM_REL);
  691. if (cpu->P & FLAG_N)
  692. cpu->PC = address;
  693. break;
  694. case 0x31: // AND izy
  695. address = get_address(cpu, AM_IZY);
  696. cpu->A &= cpu->mem[address];
  697. set_zero_and_negative_flags(cpu, cpu->A);
  698. break;
  699. case 0x33: // RLA izy
  700. address = get_address(cpu, AM_IZY);
  701. value = cpu->mem[address];
  702. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  703. cpu->P &= ~FLAG_C;
  704. if (value & 0x80)
  705. cpu->P |= FLAG_C;
  706. cpu->mem[address] = (value << 1) | temp_carry;
  707. cpu->A &= cpu->mem[address];
  708. set_zero_and_negative_flags(cpu, cpu->A);
  709. break;
  710. case 0x34: // NOP zpx
  711. get_address(cpu, AM_ZPX);
  712. break;
  713. case 0x35: // AND zpx
  714. address = get_address(cpu, AM_ZPX);
  715. cpu->A &= cpu->mem[address];
  716. set_zero_and_negative_flags(cpu, cpu->A);
  717. break;
  718. case 0x36: // ROL zpx
  719. address = get_address(cpu, AM_ZPX);
  720. value = cpu->mem[address];
  721. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  722. cpu->P &= ~FLAG_C;
  723. if (value & 0x80)
  724. cpu->P |= FLAG_C;
  725. cpu->mem[address] = (value << 1) | temp_carry;
  726. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  727. break;
  728. case 0x37: // RLA zpx
  729. address = get_address(cpu, AM_ZPX);
  730. value = cpu->mem[address];
  731. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  732. cpu->P &= ~FLAG_C;
  733. if (value & 0x80)
  734. cpu->P |= FLAG_C;
  735. cpu->mem[address] = (value << 1) | temp_carry;
  736. cpu->A &= cpu->mem[address];
  737. set_zero_and_negative_flags(cpu, cpu->A);
  738. break;
  739. case 0x38: // SEC
  740. cpu->P |= FLAG_C;
  741. break;
  742. case 0x39: // AND aby
  743. address = get_address(cpu, AM_ABY);
  744. cpu->A &= cpu->mem[address];
  745. set_zero_and_negative_flags(cpu, cpu->A);
  746. break;
  747. case 0x3A: // NOP
  748. break;
  749. case 0x3B: // RLA aby
  750. address = get_address(cpu, AM_ABY);
  751. value = cpu->mem[address];
  752. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  753. cpu->P &= ~FLAG_C;
  754. if (value & 0x80)
  755. cpu->P |= FLAG_C;
  756. cpu->mem[address] = (value << 1) | temp_carry;
  757. cpu->A &= cpu->mem[address];
  758. set_zero_and_negative_flags(cpu, cpu->A);
  759. break;
  760. case 0x3C: // NOP abx
  761. get_address(cpu, AM_ABX);
  762. break;
  763. case 0x3D: // AND abx
  764. address = get_address(cpu, AM_ABX);
  765. cpu->A &= cpu->mem[address];
  766. set_zero_and_negative_flags(cpu, cpu->A);
  767. break;
  768. case 0x3E: // ROL abx
  769. address = get_address(cpu, AM_ABX);
  770. value = cpu->mem[address];
  771. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  772. cpu->P &= ~FLAG_C;
  773. if (value & 0x80)
  774. cpu->P |= FLAG_C;
  775. cpu->mem[address] = (value << 1) | temp_carry;
  776. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  777. break;
  778. case 0x3F: // RLA abx
  779. address = get_address(cpu, AM_ABX);
  780. value = cpu->mem[address];
  781. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  782. cpu->P &= ~FLAG_C;
  783. if (value & 0x80)
  784. cpu->P |= FLAG_C;
  785. cpu->mem[address] = (value << 1) | temp_carry;
  786. cpu->A &= cpu->mem[address];
  787. set_zero_and_negative_flags(cpu, cpu->A);
  788. break;
  789. // --- 4x ---
  790. case 0x40: // RTI
  791. cpu->P = pull_byte(cpu);
  792. cpu->P |= 0x20; // Ensure B flag is always 1
  793. cpu->PC = pull_byte(cpu);
  794. cpu->PC |= pull_byte(cpu) << 8;
  795. break;
  796. case 0x41: // EOR izx
  797. address = get_address(cpu, AM_IZX);
  798. cpu->A ^= cpu->mem[address];
  799. set_zero_and_negative_flags(cpu, cpu->A);
  800. break;
  801. case 0x43: // SRE izx
  802. address = get_address(cpu, AM_IZX);
  803. value = cpu->mem[address];
  804. cpu->P &= ~FLAG_C;
  805. if (value & 0x01)
  806. cpu->P |= FLAG_C;
  807. cpu->mem[address] = value >> 1;
  808. cpu->A ^= cpu->mem[address];
  809. set_zero_and_negative_flags(cpu, cpu->A);
  810. break;
  811. case 0x44: // NOP zp
  812. get_address(cpu, AM_ZP);
  813. break;
  814. case 0x45: // EOR zp
  815. address = get_address(cpu, AM_ZP);
  816. cpu->A ^= cpu->mem[address];
  817. set_zero_and_negative_flags(cpu, cpu->A);
  818. break;
  819. case 0x46: // LSR zp
  820. address = get_address(cpu, AM_ZP);
  821. uint8_t value = cpu->mem[address];
  822. cpu->P &= ~FLAG_C;
  823. if (value & 0x01)
  824. cpu->P |= FLAG_C;
  825. cpu->mem[address] = value >> 1;
  826. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  827. break;
  828. case 0x47: // SRE zp
  829. address = get_address(cpu, AM_ZP);
  830. value = cpu->mem[address];
  831. cpu->P &= ~FLAG_C;
  832. if (value & 0x01)
  833. cpu->P |= FLAG_C;
  834. cpu->mem[address] = value >> 1;
  835. cpu->A ^= cpu->mem[address];
  836. set_zero_and_negative_flags(cpu, cpu->A);
  837. break;
  838. case 0x48: // PHA
  839. push_byte(cpu, cpu->A);
  840. break;
  841. case 0x49: // EOR imm
  842. address = get_address(cpu, AM_IMM);
  843. cpu->A ^= cpu->mem[address];
  844. set_zero_and_negative_flags(cpu, cpu->A);
  845. break;
  846. case 0x4A: // LSR
  847. cpu->P &= ~FLAG_C;
  848. if (cpu->A & 0x01)
  849. cpu->P |= FLAG_C;
  850. cpu->A = cpu->A >> 1;
  851. set_zero_and_negative_flags(cpu, cpu->A);
  852. break;
  853. case 0x4B: // ALR imm
  854. address = get_address(cpu, AM_IMM);
  855. cpu->A &= cpu->mem[address];
  856. cpu->P &= ~FLAG_C;
  857. if (cpu->A & 0x01)
  858. cpu->P |= FLAG_C;
  859. cpu->A = cpu->A >> 1;
  860. set_zero_and_negative_flags(cpu, cpu->A);
  861. break;
  862. case 0x4C: // JMP abs
  863. cpu->PC = get_address(cpu, AM_ABS);
  864. break;
  865. case 0x4D: // EOR abs
  866. address = get_address(cpu, AM_ABS);
  867. cpu->A ^= cpu->mem[address];
  868. set_zero_and_negative_flags(cpu, cpu->A);
  869. break;
  870. case 0x4E: // LSR abs
  871. address = get_address(cpu, AM_ABS);
  872. value = cpu->mem[address];
  873. cpu->P &= ~FLAG_C;
  874. if (value & 0x01)
  875. cpu->P |= FLAG_C;
  876. cpu->mem[address] = value >> 1;
  877. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  878. break;
  879. case 0x4F: // SRE abs
  880. address = get_address(cpu, AM_ABS);
  881. value = cpu->mem[address];
  882. cpu->P &= ~FLAG_C;
  883. if (value & 0x01)
  884. cpu->P |= FLAG_C;
  885. cpu->mem[address] = value >> 1;
  886. cpu->A ^= cpu->mem[address];
  887. set_zero_and_negative_flags(cpu, cpu->A);
  888. break;
  889.  
  890. // --- 5x ---
  891. case 0x50: // BVC rel
  892. address = get_address(cpu, AM_REL);
  893. if (!(cpu->P & FLAG_V))
  894. cpu->PC = address;
  895. break;
  896. case 0x51: // EOR izy
  897. address = get_address(cpu, AM_IZY);
  898. cpu->A ^= cpu->mem[address];
  899. set_zero_and_negative_flags(cpu, cpu->A);
  900. break;
  901. case 0x53: // SRE izy
  902. address = get_address(cpu, AM_IZY);
  903. value = cpu->mem[address];
  904. cpu->P &= ~FLAG_C;
  905. if (value & 0x01)
  906. cpu->P |= FLAG_C;
  907. cpu->mem[address] = value >> 1;
  908. cpu->A ^= cpu->mem[address];
  909. set_zero_and_negative_flags(cpu, cpu->A);
  910. break;
  911. case 0x54: // NOP zpx
  912. get_address(cpu, AM_ZPX);
  913. break;
  914. case 0x55: // EOR zpx
  915. address = get_address(cpu, AM_ZPX);
  916. cpu->A ^= cpu->mem[address];
  917. set_zero_and_negative_flags(cpu, cpu->A);
  918. break;
  919. case 0x56: // LSR zpx
  920. address = get_address(cpu, AM_ZPX);
  921. value = cpu->mem[address];
  922. cpu->P &= ~FLAG_C;
  923. if (value & 0x01)
  924. cpu->P |= FLAG_C;
  925. cpu->mem[address] = value >> 1;
  926. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  927. break;
  928. case 0x57: // SRE zpx
  929. address = get_address(cpu, AM_ZPX);
  930. value = cpu->mem[address];
  931. cpu->P &= ~FLAG_C;
  932. if (value & 0x01)
  933. cpu->P |= FLAG_C;
  934. cpu->mem[address] = value >> 1;
  935. cpu->A ^= cpu->mem[address];
  936. set_zero_and_negative_flags(cpu, cpu->A);
  937. break;
  938. case 0x58: // CLI
  939. cpu->P &= ~FLAG_I;
  940. break;
  941. case 0x59: // EOR aby
  942. address = get_address(cpu, AM_ABY);
  943. cpu->A ^= cpu->mem[address];
  944. set_zero_and_negative_flags(cpu, cpu->A);
  945. break;
  946. case 0x5A: // NOP
  947. break;
  948. case 0x5B: // SRE aby
  949. address = get_address(cpu, AM_ABY);
  950. value = cpu->mem[address];
  951. cpu->P &= ~FLAG_C;
  952. if (value & 0x01)
  953. cpu->P |= FLAG_C;
  954. cpu->mem[address] = value >> 1;
  955. cpu->A ^= cpu->mem[address];
  956. set_zero_and_negative_flags(cpu, cpu->A);
  957. break;
  958. case 0x5C: // NOP abx
  959. get_address(cpu, AM_ABX);
  960. break;
  961. case 0x5D: // EOR abx
  962. address = get_address(cpu, AM_ABX);
  963. cpu->A ^= cpu->mem[address];
  964. set_zero_and_negative_flags(cpu, cpu->A);
  965. break;
  966. case 0x5E: // LSR abx
  967. address = get_address(cpu, AM_ABX);
  968. value = cpu->mem[address];
  969. cpu->P &= ~FLAG_C;
  970. if (value & 0x01)
  971. cpu->P |= FLAG_C;
  972. cpu->mem[address] = value >> 1;
  973. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  974. break;
  975. case 0x5F: // SRE abx
  976. address = get_address(cpu, AM_ABX);
  977. value = cpu->mem[address];
  978. cpu->P &= ~FLAG_C;
  979. if (value & 0x01)
  980. cpu->P |= FLAG_C;
  981. cpu->mem[address] = value >> 1;
  982. cpu->A ^= cpu->mem[address];
  983. set_zero_and_negative_flags(cpu, cpu->A);
  984. break;
  985.  
  986. // --- 6x ---
  987. case 0x60: // RTS
  988. cpu->PC = pull_byte(cpu);
  989. cpu->PC |= pull_byte(cpu) << 8;
  990. cpu->PC++; // Increment PC after returning
  991. break;
  992. case 0x61: // ADC izx
  993. address = get_address(cpu, AM_IZX);
  994. value = cpu->mem[address];
  995. uint16_t result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  996. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  997. if (result & 0x100)
  998. cpu->P |= FLAG_C;
  999. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1000. cpu->P |= FLAG_V;
  1001. cpu->A = result & 0xFF;
  1002. set_zero_and_negative_flags(cpu, cpu->A);
  1003. break;
  1004. case 0x63: // RRA izx
  1005. address = get_address(cpu, AM_IZX);
  1006. value = cpu->mem[address];
  1007. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1008. cpu->P &= ~FLAG_C;
  1009. if (value & 0x01)
  1010. cpu->P |= FLAG_C;
  1011. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1012. value = cpu->mem[address];
  1013. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1014. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1015. if (result & 0x100)
  1016. cpu->P |= FLAG_C;
  1017. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1018. cpu->P |= FLAG_V;
  1019. cpu->A = result & 0xFF;
  1020. set_zero_and_negative_flags(cpu, cpu->A);
  1021. break;
  1022. case 0x64: // NOP zp
  1023. get_address(cpu, AM_ZP);
  1024. break;
  1025. case 0x65: // ADC zp
  1026. address = get_address(cpu, AM_ZP);
  1027. value = cpu->mem[address];
  1028. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1029. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1030. if (result & 0x100)
  1031. cpu->P |= FLAG_C;
  1032. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1033. cpu->P |= FLAG_V;
  1034. cpu->A = result & 0xFF;
  1035. set_zero_and_negative_flags(cpu, cpu->A);
  1036. break;
  1037. case 0x66: // ROR zp
  1038. address = get_address(cpu, AM_ZP);
  1039. value = cpu->mem[address];
  1040. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1041. cpu->P &= ~FLAG_C;
  1042. if (value & 0x01)
  1043. cpu->P |= FLAG_C;
  1044. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1045. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  1046. break;
  1047. case 0x67: // RRA zp
  1048. address = get_address(cpu, AM_ZP);
  1049. value = cpu->mem[address];
  1050. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1051. cpu->P &= ~FLAG_C;
  1052. if (value & 0x01)
  1053. cpu->P |= FLAG_C;
  1054. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1055. value = cpu->mem[address];
  1056. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1057. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1058. if (result & 0x100)
  1059. cpu->P |= FLAG_C;
  1060. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1061. cpu->P |= FLAG_V;
  1062. cpu->A = result & 0xFF;
  1063. set_zero_and_negative_flags(cpu, cpu->A);
  1064. break;
  1065. case 0x68: // PLA
  1066. cpu->A = pull_byte(cpu);
  1067. set_zero_and_negative_flags(cpu, cpu->A);
  1068. break;
  1069. case 0x69: // ADC imm
  1070. address = get_address(cpu, AM_IMM);
  1071. value = cpu->mem[address];
  1072. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1073. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1074. if (result & 0x100)
  1075. cpu->P |= FLAG_C;
  1076. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1077. cpu->P |= FLAG_V;
  1078. cpu->A = result & 0xFF;
  1079. set_zero_and_negative_flags(cpu, cpu->A);
  1080. break;
  1081. case 0x6A: // ROR
  1082. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1083. cpu->P &= ~FLAG_C;
  1084. if (cpu->A & 0x01)
  1085. cpu->P |= FLAG_C;
  1086. cpu->A = (cpu->A >> 1) | (temp_carry << 7);
  1087. set_zero_and_negative_flags(cpu, cpu->A);
  1088. break;
  1089. case 0x6B: // ARR imm
  1090. address = get_address(cpu, AM_IMM);
  1091. cpu->A &= cpu->mem[address];
  1092. temp_byte = cpu->A; // Store result of AND
  1093. cpu->P &= ~FLAG_C;
  1094. if ((cpu->A & 0x01))
  1095. cpu->P |= FLAG_C;
  1096. cpu->A = (cpu->A >> 1) | ((cpu->P & FLAG_C) << 7);
  1097. uint8_t temp_result = (temp_byte + (temp_byte & 0x0F));
  1098. cpu->P &= ~FLAG_V;
  1099. if ((temp_result ^ cpu->A) & 0x40)
  1100. cpu->P |= FLAG_V;
  1101.  
  1102. set_zero_and_negative_flags(cpu, cpu->A);
  1103.  
  1104. break;
  1105. case 0x6C: // JMP ind
  1106. cpu->PC = get_address(cpu, AM_IND);
  1107. break;
  1108. case 0x6D: // ADC abs
  1109. address = get_address(cpu, AM_ABS);
  1110. value = cpu->mem[address];
  1111. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1112. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1113. if (result & 0x100)
  1114. cpu->P |= FLAG_C;
  1115. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1116. cpu->P |= FLAG_V;
  1117. cpu->A = result & 0xFF;
  1118. set_zero_and_negative_flags(cpu, cpu->A);
  1119. break;
  1120. case 0x6E: // ROR abs
  1121. address = get_address(cpu, AM_ABS);
  1122. value = cpu->mem[address];
  1123. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1124. cpu->P &= ~FLAG_C;
  1125. if (value & 0x01)
  1126. cpu->P |= FLAG_C;
  1127. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1128. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  1129. break;
  1130. case 0x6F: // RRA abs
  1131. address = get_address(cpu, AM_ABS);
  1132. value = cpu->mem[address];
  1133. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1134. cpu->P &= ~FLAG_C;
  1135. if (value & 0x01)
  1136. cpu->P |= FLAG_C;
  1137. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1138. value = cpu->mem[address];
  1139. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1140. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1141. if (result & 0x100)
  1142. cpu->P |= FLAG_C;
  1143. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1144. cpu->P |= FLAG_V;
  1145. cpu->A = result & 0xFF;
  1146. set_zero_and_negative_flags(cpu, cpu->A);
  1147. break;
  1148. // --- 7x ---
  1149. case 0x70: // BVS rel
  1150. address = get_address(cpu, AM_REL);
  1151. if (cpu->P & FLAG_V)
  1152. cpu->PC = address;
  1153. break;
  1154. case 0x71: // ADC izy
  1155. address = get_address(cpu, AM_IZY);
  1156. value = cpu->mem[address];
  1157. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1158. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1159. if (result & 0x100)
  1160. cpu->P |= FLAG_C;
  1161. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1162. cpu->P |= FLAG_V;
  1163. cpu->A = result & 0xFF;
  1164. set_zero_and_negative_flags(cpu, cpu->A);
  1165. break;
  1166. case 0x73: // RRA izy
  1167. address = get_address(cpu, AM_IZY);
  1168. value = cpu->mem[address];
  1169. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1170. cpu->P &= ~FLAG_C;
  1171. if (value & 0x01)
  1172. cpu->P |= FLAG_C;
  1173. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1174. value = cpu->mem[address];
  1175. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1176. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1177. if (result & 0x100)
  1178. cpu->P |= FLAG_C;
  1179. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1180. cpu->P |= FLAG_V;
  1181. cpu->A = result & 0xFF;
  1182. set_zero_and_negative_flags(cpu, cpu->A);
  1183. break;
  1184. case 0x74: // NOP zpx
  1185. get_address(cpu, AM_ZPX);
  1186. break;
  1187. case 0x75: // ADC zpx
  1188. address = get_address(cpu, AM_ZPX);
  1189. value = cpu->mem[address];
  1190. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1191. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1192. if (result & 0x100)
  1193. cpu->P |= FLAG_C;
  1194. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1195. cpu->P |= FLAG_V;
  1196. cpu->A = result & 0xFF;
  1197. set_zero_and_negative_flags(cpu, cpu->A);
  1198. break;
  1199. case 0x76: // ROR zpx
  1200. address = get_address(cpu, AM_ZPX);
  1201. value = cpu->mem[address];
  1202. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1203. cpu->P &= ~FLAG_C;
  1204. if (value & 0x01)
  1205. cpu->P |= FLAG_C;
  1206. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1207. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  1208. break;
  1209. case 0x77: // RRA zpx
  1210. address = get_address(cpu, AM_ZPX);
  1211. value = cpu->mem[address];
  1212. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1213. cpu->P &= ~FLAG_C;
  1214. if (value & 0x01)
  1215. cpu->P |= FLAG_C;
  1216. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1217. value = cpu->mem[address];
  1218. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1219. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1220. if (result & 0x100)
  1221. cpu->P |= FLAG_C;
  1222. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1223. cpu->P |= FLAG_V;
  1224. cpu->A = result & 0xFF;
  1225. set_zero_and_negative_flags(cpu, cpu->A);
  1226. break;
  1227. case 0x78: // SEI
  1228. cpu->P |= FLAG_I;
  1229. break;
  1230. case 0x79: // ADC aby
  1231. address = get_address(cpu, AM_ABY);
  1232. value = cpu->mem[address];
  1233. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1234. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1235. if (result & 0x100)
  1236. cpu->P |= FLAG_C;
  1237. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1238. cpu->P |= FLAG_V;
  1239. cpu->A = result & 0xFF;
  1240. set_zero_and_negative_flags(cpu, cpu->A);
  1241. break;
  1242. case 0x7A: // NOP
  1243. break;
  1244. case 0x7B: // RRA aby
  1245. address = get_address(cpu, AM_ABY);
  1246. value = cpu->mem[address];
  1247. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1248. cpu->P &= ~FLAG_C;
  1249. if (value & 0x01)
  1250. cpu->P |= FLAG_C;
  1251. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1252. value = cpu->mem[address];
  1253. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1254. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1255. if (result & 0x100)
  1256. cpu->P |= FLAG_C;
  1257. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1258. cpu->P |= FLAG_V;
  1259. cpu->A = result & 0xFF;
  1260. set_zero_and_negative_flags(cpu, cpu->A);
  1261. break;
  1262. case 0x7C: // NOP abx
  1263. get_address(cpu, AM_ABX);
  1264. break;
  1265. case 0x7D: // ADC abx
  1266. address = get_address(cpu, AM_ABX);
  1267. value = cpu->mem[address];
  1268. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1269. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1270. if (result & 0x100)
  1271. cpu->P |= FLAG_C;
  1272. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1273. cpu->P |= FLAG_V;
  1274. cpu->A = result & 0xFF;
  1275. set_zero_and_negative_flags(cpu, cpu->A);
  1276. break;
  1277. case 0x7E: // ROR abx
  1278. address = get_address(cpu, AM_ABX);
  1279. value = cpu->mem[address];
  1280. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1281. cpu->P &= ~FLAG_C;
  1282. if (value & 0x01)
  1283. cpu->P |= FLAG_C;
  1284. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1285. set_zero_and_negative_flags(cpu, cpu->mem[address]);
  1286. break;
  1287. case 0x7F: // RRA abx
  1288. address = get_address(cpu, AM_ABX);
  1289. value = cpu->mem[address];
  1290. temp_carry = (cpu->P & FLAG_C) ? 1 : 0;
  1291. cpu->P &= ~FLAG_C;
  1292. if (value & 0x01)
  1293. cpu->P |= FLAG_C;
  1294. cpu->mem[address] = (value >> 1) | (temp_carry << 7);
  1295. value = cpu->mem[address];
  1296. result = cpu->A + value + (cpu->P & FLAG_C ? 1 : 0);
  1297. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1298. if (result & 0x100)
  1299. cpu->P |= FLAG_C;
  1300. if ((cpu->A ^ result) & (value ^ result) & 0x80)
  1301. cpu->P |= FLAG_V;
  1302. cpu->A = result & 0xFF;
  1303. set_zero_and_negative_flags(cpu, cpu->A);
  1304. break;
  1305.  
  1306. // --- 8x ---
  1307. case 0x80: // NOP imm
  1308. get_address(cpu, AM_IMM);
  1309. break;
  1310. case 0x81: // STA izx
  1311. address = get_address(cpu, AM_IZX);
  1312. cpu->mem[address] = cpu->A;
  1313. break;
  1314. case 0x82: // NOP imm
  1315. get_address(cpu, AM_IMM);
  1316. break;
  1317. case 0x83: // SAX izx
  1318. address = get_address(cpu, AM_IZX);
  1319. cpu->mem[address] = cpu->A & cpu->X;
  1320. break;
  1321. case 0x84: // STY zp
  1322. address = get_address(cpu, AM_ZP);
  1323. cpu->mem[address] = cpu->Y;
  1324. break;
  1325. case 0x85: // STA zp
  1326. address = get_address(cpu, AM_ZP);
  1327. cpu->mem[address] = cpu->A;
  1328. break;
  1329. case 0x86: // STX zp
  1330. address = get_address(cpu, AM_ZP);
  1331. cpu->mem[address] = cpu->X;
  1332. break;
  1333. case 0x87: // SAX zp
  1334. address = get_address(cpu, AM_ZP);
  1335. cpu->mem[address] = cpu->A & cpu->X;
  1336. break;
  1337. case 0x88: // DEY
  1338. cpu->Y--;
  1339. set_zero_and_negative_flags(cpu, cpu->Y);
  1340. break;
  1341. case 0x8A: // TXA
  1342. cpu->A = cpu->X;
  1343. set_zero_and_negative_flags(cpu, cpu->A);
  1344. break;
  1345. case 0x8B: // XAA imm
  1346. address = get_address(cpu, AM_IMM);
  1347. cpu->A = cpu->X & cpu->mem[address];
  1348. set_zero_and_negative_flags(cpu, cpu->A);
  1349.  
  1350. break;
  1351. case 0x8C: // STY abs
  1352. address = get_address(cpu, AM_ABS);
  1353. cpu->mem[address] = cpu->Y;
  1354. break;
  1355. case 0x8D: // STA abs
  1356. address = get_address(cpu, AM_ABS);
  1357. cpu->mem[address] = cpu->A;
  1358. break;
  1359. case 0x8E: // STX abs
  1360. address = get_address(cpu, AM_ABS);
  1361. cpu->mem[address] = cpu->X;
  1362. break;
  1363. case 0x8F: // SAX abs
  1364. address = get_address(cpu, AM_ABS);
  1365. cpu->mem[address] = cpu->A & cpu->X;
  1366. break;
  1367. // --- 9x ---
  1368. case 0x90: // BCC rel
  1369. address = get_address(cpu, AM_REL);
  1370. if (!(cpu->P & FLAG_C))
  1371. cpu->PC = address;
  1372. break;
  1373. case 0x91: // STA izy
  1374. address = get_address(cpu, AM_IZY);
  1375. cpu->mem[address] = cpu->A;
  1376. break;
  1377. case 0x93: // AHX izy
  1378. address = get_address(cpu, AM_IZY);
  1379. cpu->mem[address] = cpu->A & cpu->X & (address >> 8);
  1380. break;
  1381. case 0x94: // STY zpx
  1382. address = get_address(cpu, AM_ZPX);
  1383. cpu->mem[address] = cpu->Y;
  1384. break;
  1385. case 0x95: // STA zpx
  1386. address = get_address(cpu, AM_ZPX);
  1387. cpu->mem[address] = cpu->A;
  1388. break;
  1389. case 0x96: // STX zpy
  1390. address = get_address(cpu, AM_ZPY);
  1391. cpu->mem[address] = cpu->X;
  1392. break;
  1393. case 0x97: // SAX zpy
  1394. address = get_address(cpu, AM_ZPY);
  1395. cpu->mem[address] = cpu->A & cpu->X;
  1396. break;
  1397. case 0x98: // TYA
  1398. cpu->A = cpu->Y;
  1399. set_zero_and_negative_flags(cpu, cpu->A);
  1400. break;
  1401. case 0x99: // STA aby
  1402. address = get_address(cpu, AM_ABY);
  1403. cpu->mem[address] = cpu->A;
  1404. break;
  1405. case 0x9A: // TXS
  1406. cpu->SP = cpu->X;
  1407. break;
  1408. case 0x9B: // TAS aby
  1409. address = get_address(cpu, AM_ABY);
  1410. cpu->SP = cpu->A & cpu->X;
  1411. cpu->mem[address] = cpu->SP & (address >> 8);
  1412. break;
  1413. case 0x9C: // SHY abx
  1414. address = get_address(cpu, AM_ABX);
  1415. cpu->mem[address] = cpu->Y & (address >> 8);
  1416. break;
  1417. case 0x9D: // STA abx
  1418. address = get_address(cpu, AM_ABX);
  1419. cpu->mem[address] = cpu->A;
  1420. break;
  1421. case 0x9E: // SHX aby
  1422. address = get_address(cpu, AM_ABY);
  1423. cpu->mem[address] = cpu->X & (address >> 8);
  1424. break;
  1425. case 0x9F: // AHX aby
  1426. address = get_address(cpu, AM_ABY);
  1427. cpu->mem[address] = cpu->A & cpu->X & (address >> 8);
  1428. break;
  1429. // --- Ax ---
  1430. case 0xA0: // LDY imm
  1431. address = get_address(cpu, AM_IMM);
  1432. cpu->Y = cpu->mem[address];
  1433. set_zero_and_negative_flags(cpu, cpu->Y);
  1434. break;
  1435. case 0xA1: // LDA izx
  1436. address = get_address(cpu, AM_IZX);
  1437. cpu->A = cpu->mem[address];
  1438. set_zero_and_negative_flags(cpu, cpu->A);
  1439. break;
  1440. case 0xA2: // LDX imm
  1441. address = get_address(cpu, AM_IMM);
  1442. cpu->X = cpu->mem[address];
  1443. set_zero_and_negative_flags(cpu, cpu->X);
  1444. break;
  1445. case 0xA3: // LAX izx
  1446. address = get_address(cpu, AM_IZX);
  1447. cpu->A = cpu->X = cpu->mem[address];
  1448. set_zero_and_negative_flags(cpu, cpu->A);
  1449. break;
  1450. case 0xA4: // LDY zp
  1451. address = get_address(cpu, AM_ZP);
  1452. cpu->Y = cpu->mem[address];
  1453. set_zero_and_negative_flags(cpu, cpu->Y);
  1454. break;
  1455. case 0xA5: // LDA zp
  1456. address = get_address(cpu, AM_ZP);
  1457. cpu->A = cpu->mem[address];
  1458. set_zero_and_negative_flags(cpu, cpu->A);
  1459. break;
  1460. case 0xA6: // LDX zp
  1461. address = get_address(cpu, AM_ZP);
  1462. cpu->X = cpu->mem[address];
  1463. set_zero_and_negative_flags(cpu, cpu->X);
  1464. break;
  1465. case 0xA7: // LAX zp
  1466. address = get_address(cpu, AM_ZP);
  1467. cpu->A = cpu->X = cpu->mem[address];
  1468. set_zero_and_negative_flags(cpu, cpu->A);
  1469. break;
  1470. case 0xA8: // TAY
  1471. cpu->Y = cpu->A;
  1472. set_zero_and_negative_flags(cpu, cpu->Y);
  1473. break;
  1474. case 0xA9: // LDA imm
  1475. address = get_address(cpu, AM_IMM);
  1476. cpu->A = cpu->mem[address];
  1477. set_zero_and_negative_flags(cpu, cpu->A);
  1478. break;
  1479. case 0xAA: // TAX
  1480. cpu->X = cpu->A;
  1481. set_zero_and_negative_flags(cpu, cpu->X);
  1482. break;
  1483. case 0xAB: // LAX imm
  1484. address = get_address(cpu, AM_IMM);
  1485. cpu->A = cpu->X = cpu->mem[address];
  1486. set_zero_and_negative_flags(cpu, cpu->A);
  1487. break;
  1488. case 0xAC: // LDY abs
  1489. address = get_address(cpu, AM_ABS);
  1490. cpu->Y = cpu->mem[address];
  1491. set_zero_and_negative_flags(cpu, cpu->Y);
  1492. break;
  1493. case 0xAD: // LDA abs
  1494. address = get_address(cpu, AM_ABS);
  1495. cpu->A = cpu->mem[address];
  1496. set_zero_and_negative_flags(cpu, cpu->A);
  1497. break;
  1498. case 0xAE: // LDX abs
  1499. address = get_address(cpu, AM_ABS);
  1500. cpu->X = cpu->mem[address];
  1501. set_zero_and_negative_flags(cpu, cpu->X);
  1502. break;
  1503. case 0xAF: // LAX abs
  1504. address = get_address(cpu, AM_ABS);
  1505. cpu->A = cpu->X = cpu->mem[address];
  1506. set_zero_and_negative_flags(cpu, cpu->A);
  1507. break;
  1508.  
  1509. // --- Bx ---
  1510. case 0xB0: // BCS rel
  1511. address = get_address(cpu, AM_REL);
  1512. if (cpu->P & FLAG_C)
  1513. cpu->PC = address;
  1514. break;
  1515. case 0xB1: // LDA izy
  1516. address = get_address(cpu, AM_IZY);
  1517. cpu->A = cpu->mem[address];
  1518. set_zero_and_negative_flags(cpu, cpu->A);
  1519. break;
  1520. case 0xB3: // LAX izy
  1521. address = get_address(cpu, AM_IZY);
  1522. cpu->A = cpu->X = cpu->mem[address];
  1523. set_zero_and_negative_flags(cpu, cpu->A);
  1524. break;
  1525. case 0xB4: // LDY zpx
  1526. address = get_address(cpu, AM_ZPX);
  1527. cpu->Y = cpu->mem[address];
  1528. set_zero_and_negative_flags(cpu, cpu->Y);
  1529. break;
  1530. case 0xB5: // LDA zpx
  1531. address = get_address(cpu, AM_ZPX);
  1532. cpu->A = cpu->mem[address];
  1533. set_zero_and_negative_flags(cpu, cpu->A);
  1534. break;
  1535. case 0xB6: // LDX zpy
  1536. address = get_address(cpu, AM_ZPY);
  1537. cpu->X = cpu->mem[address];
  1538. set_zero_and_negative_flags(cpu, cpu->X);
  1539. break;
  1540. case 0xB7: // LAX zpy
  1541. address = get_address(cpu, AM_ZPY);
  1542. cpu->A = cpu->X = cpu->mem[address];
  1543. set_zero_and_negative_flags(cpu, cpu->A);
  1544. break;
  1545. case 0xB8: // CLV
  1546. cpu->P &= ~FLAG_V;
  1547. break;
  1548. case 0xB9: // LDA aby
  1549. address = get_address(cpu, AM_ABY);
  1550. cpu->A = cpu->mem[address];
  1551. set_zero_and_negative_flags(cpu, cpu->A);
  1552. break;
  1553. case 0xBA: // TSX
  1554. cpu->X = cpu->SP;
  1555. set_zero_and_negative_flags(cpu, cpu->X);
  1556. break;
  1557. case 0xBB: // LAS aby
  1558. address = get_address(cpu, AM_ABY);
  1559. cpu->A = cpu->X = cpu->SP = cpu->mem[address] & cpu->SP;
  1560. set_zero_and_negative_flags(cpu, cpu->A);
  1561. break;
  1562. case 0xBC: // LDY abx
  1563. address = get_address(cpu, AM_ABX);
  1564. cpu->Y = cpu->mem[address];
  1565. set_zero_and_negative_flags(cpu, cpu->Y);
  1566. break;
  1567. case 0xBD: // LDA abx
  1568. address = get_address(cpu, AM_ABX);
  1569. cpu->A = cpu->mem[address];
  1570. set_zero_and_negative_flags(cpu, cpu->A);
  1571. break;
  1572. case 0xBE: // LDX aby
  1573. address = get_address(cpu, AM_ABY);
  1574. cpu->X = cpu->mem[address];
  1575. set_zero_and_negative_flags(cpu, cpu->X);
  1576. break;
  1577. case 0xBF: // LAX aby
  1578. address = get_address(cpu, AM_ABY);
  1579. cpu->A = cpu->X = cpu->mem[address];
  1580. set_zero_and_negative_flags(cpu, cpu->A);
  1581. break;
  1582.  
  1583. // --- Cx ---
  1584. case 0xC0: // CPY imm
  1585. address = get_address(cpu, AM_IMM);
  1586. value = cpu->mem[address];
  1587. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1588. if (cpu->Y >= value)
  1589. cpu->P |= FLAG_C;
  1590. set_zero_and_negative_flags(cpu, cpu->Y - value);
  1591. break;
  1592. case 0xC1: // CMP izx
  1593. address = get_address(cpu, AM_IZX);
  1594. value = cpu->mem[address];
  1595. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1596. if (cpu->A >= value)
  1597. cpu->P |= FLAG_C;
  1598. set_zero_and_negative_flags(cpu, cpu->A - value);
  1599. break;
  1600. case 0xC2: // NOP imm
  1601. get_address(cpu, AM_IMM);
  1602. break;
  1603. case 0xC3: // DCP izx
  1604. address = get_address(cpu, AM_IZX);
  1605. value = cpu->mem[address];
  1606. value--;
  1607. cpu->mem[address] = value;
  1608. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1609. if (cpu->A >= value)
  1610. cpu->P |= FLAG_C;
  1611. set_zero_and_negative_flags(cpu, cpu->A - value);
  1612. break;
  1613. case 0xC4: // CPY zp
  1614. address = get_address(cpu, AM_ZP);
  1615. value = cpu->mem[address];
  1616. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1617. if (cpu->Y >= value)
  1618. cpu->P |= FLAG_C;
  1619. set_zero_and_negative_flags(cpu, cpu->Y - value);
  1620. break;
  1621. case 0xC5: // CMP zp
  1622. address = get_address(cpu, AM_ZP);
  1623. value = cpu->mem[address];
  1624. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1625. if (cpu->A >= value)
  1626. cpu->P |= FLAG_C;
  1627. set_zero_and_negative_flags(cpu, cpu->A - value);
  1628. break;
  1629. case 0xC6: // DEC zp
  1630. address = get_address(cpu, AM_ZP);
  1631. value = cpu->mem[address];
  1632. value--;
  1633. cpu->mem[address] = value;
  1634. set_zero_and_negative_flags(cpu, value);
  1635. break;
  1636. case 0xC7: // DCP zp
  1637. address = get_address(cpu, AM_ZP);
  1638. value = cpu->mem[address];
  1639. value--;
  1640. cpu->mem[address] = value;
  1641. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1642. if (cpu->A >= value)
  1643. cpu->P |= FLAG_C;
  1644. set_zero_and_negative_flags(cpu, cpu->A - value);
  1645. break;
  1646. case 0xC8: // INY
  1647. cpu->Y++;
  1648. set_zero_and_negative_flags(cpu, cpu->Y);
  1649. break;
  1650. case 0xC9: // CMP imm
  1651. address = get_address(cpu, AM_IMM);
  1652. value = cpu->mem[address];
  1653. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1654. if (cpu->A >= value)
  1655. cpu->P |= FLAG_C;
  1656. set_zero_and_negative_flags(cpu, cpu->A - value);
  1657. break;
  1658. case 0xCA: // DEX
  1659. cpu->X--;
  1660. set_zero_and_negative_flags(cpu, cpu->X);
  1661. break;
  1662. case 0xCB: // AXS imm
  1663. address = get_address(cpu, AM_IMM);
  1664. value = cpu->mem[address];
  1665. cpu->X = (cpu->A & cpu->X) - value;
  1666. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1667. if ((cpu->A & cpu->X) >= value)
  1668. cpu->P |= FLAG_C;
  1669. set_zero_and_negative_flags(cpu, cpu->X);
  1670.  
  1671. break;
  1672. case 0xCC: // CPY abs
  1673. address = get_address(cpu, AM_ABS);
  1674. value = cpu->mem[address];
  1675. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1676. if (cpu->Y >= value)
  1677. cpu->P |= FLAG_C;
  1678. set_zero_and_negative_flags(cpu, cpu->Y - value);
  1679. break;
  1680. case 0xCD: // CMP abs
  1681. address = get_address(cpu, AM_ABS);
  1682. value = cpu->mem[address];
  1683. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1684. if (cpu->A >= value)
  1685. cpu->P |= FLAG_C;
  1686. set_zero_and_negative_flags(cpu, cpu->A - value);
  1687. break;
  1688. case 0xCE: // DEC abs
  1689. address = get_address(cpu, AM_ABS);
  1690. value = cpu->mem[address];
  1691. value--;
  1692. cpu->mem[address] = value;
  1693. set_zero_and_negative_flags(cpu, value);
  1694. break;
  1695. case 0xCF: // DCP abs
  1696. address = get_address(cpu, AM_ABS);
  1697. value = cpu->mem[address];
  1698. value--;
  1699. cpu->mem[address] = value;
  1700. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1701. if (cpu->A >= value)
  1702. cpu->P |= FLAG_C;
  1703. set_zero_and_negative_flags(cpu, cpu->A - value);
  1704. break;
  1705.  
  1706. // --- Dx ---
  1707. case 0xD0: // BNE rel
  1708. address = get_address(cpu, AM_REL);
  1709. if (!(cpu->P & FLAG_Z))
  1710. cpu->PC = address;
  1711. break;
  1712. case 0xD1: // CMP izy
  1713. address = get_address(cpu, AM_IZY);
  1714. value = cpu->mem[address];
  1715. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1716. if (cpu->A >= value)
  1717. cpu->P |= FLAG_C;
  1718. set_zero_and_negative_flags(cpu, cpu->A - value);
  1719. break;
  1720. case 0xD3: // DCP izy
  1721. address = get_address(cpu, AM_IZY);
  1722. value = cpu->mem[address];
  1723. value--;
  1724. cpu->mem[address] = value;
  1725. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1726. if (cpu->A >= value)
  1727. cpu->P |= FLAG_C;
  1728. set_zero_and_negative_flags(cpu, cpu->A - value);
  1729. break;
  1730. case 0xD4: // NOP zpx
  1731. get_address(cpu, AM_ZPX);
  1732. break;
  1733. case 0xD5: // CMP zpx
  1734. address = get_address(cpu, AM_ZPX);
  1735. value = cpu->mem[address];
  1736. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1737. if (cpu->A >= value)
  1738. cpu->P |= FLAG_C;
  1739. set_zero_and_negative_flags(cpu, cpu->A - value);
  1740. break;
  1741. case 0xD6: // DEC zpx
  1742. address = get_address(cpu, AM_ZPX);
  1743. value = cpu->mem[address];
  1744. value--;
  1745. cpu->mem[address] = value;
  1746. set_zero_and_negative_flags(cpu, value);
  1747. break;
  1748. case 0xD7: // DCP zpx
  1749. address = get_address(cpu, AM_ZPX);
  1750. value = cpu->mem[address];
  1751. value--;
  1752. cpu->mem[address] = value;
  1753. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1754. if (cpu->A >= value)
  1755. cpu->P |= FLAG_C;
  1756. set_zero_and_negative_flags(cpu, cpu->A - value);
  1757. break;
  1758. case 0xD8: // CLD
  1759. cpu->P &= ~FLAG_D;
  1760. break;
  1761. case 0xD9: // CMP aby
  1762. address = get_address(cpu, AM_ABY);
  1763. value = cpu->mem[address];
  1764. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1765. if (cpu->A >= value)
  1766. cpu->P |= FLAG_C;
  1767. set_zero_and_negative_flags(cpu, cpu->A - value);
  1768. break;
  1769. case 0xDA: // NOP
  1770. break;
  1771. case 0xDB: // DCP aby
  1772. address = get_address(cpu, AM_ABY);
  1773. value = cpu->mem[address];
  1774. value--;
  1775. cpu->mem[address] = value;
  1776. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1777. if (cpu->A >= value)
  1778. cpu->P |= FLAG_C;
  1779. set_zero_and_negative_flags(cpu, cpu->A - value);
  1780. break;
  1781. case 0xDC: // NOP abx
  1782. get_address(cpu, AM_ABX);
  1783. break;
  1784. case 0xDD: // CMP abx
  1785. address = get_address(cpu, AM_ABX);
  1786. value = cpu->mem[address];
  1787. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1788. if (cpu->A >= value)
  1789. cpu->P |= FLAG_C;
  1790. set_zero_and_negative_flags(cpu, cpu->A - value);
  1791. break;
  1792. case 0xDE: // DEC abx
  1793. address = get_address(cpu, AM_ABX);
  1794. value = cpu->mem[address];
  1795. value--;
  1796. cpu->mem[address] = value;
  1797. set_zero_and_negative_flags(cpu, value);
  1798. break;
  1799. case 0xDF: // DCP abx
  1800. address = get_address(cpu, AM_ABX);
  1801. value = cpu->mem[address];
  1802. value--;
  1803. cpu->mem[address] = value;
  1804. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1805. if (cpu->A >= value)
  1806. cpu->P |= FLAG_C;
  1807. set_zero_and_negative_flags(cpu, cpu->A - value);
  1808. break;
  1809.  
  1810. // --- Ex ---
  1811. case 0xE0: // CPX imm
  1812. address = get_address(cpu, AM_IMM);
  1813. value = cpu->mem[address];
  1814. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1815. if (cpu->X >= value)
  1816. cpu->P |= FLAG_C;
  1817. set_zero_and_negative_flags(cpu, cpu->X - value);
  1818. break;
  1819. case 0xE1: // SBC izx
  1820. address = get_address(cpu, AM_IZX);
  1821. value = cpu->mem[address];
  1822. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1823. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1824. if (!(result & 0x100))
  1825. cpu->P |= FLAG_C;
  1826.  
  1827. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1828. cpu->P |= FLAG_V;
  1829. cpu->A = result & 0xFF;
  1830. set_zero_and_negative_flags(cpu, cpu->A);
  1831.  
  1832. break;
  1833. case 0xE2: // NOP imm
  1834. get_address(cpu, AM_IMM);
  1835. break;
  1836. case 0xE3: // ISC izx
  1837. address = get_address(cpu, AM_IZX);
  1838. value = cpu->mem[address];
  1839. value++;
  1840. cpu->mem[address] = value;
  1841. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1842. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1843. if (!(result & 0x100))
  1844. cpu->P |= FLAG_C;
  1845. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1846. cpu->P |= FLAG_V;
  1847. cpu->A = result & 0xFF;
  1848. set_zero_and_negative_flags(cpu, cpu->A);
  1849. break;
  1850. case 0xE4: // CPX zp
  1851. address = get_address(cpu, AM_ZP);
  1852. value = cpu->mem[address];
  1853. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1854. if (cpu->X >= value)
  1855. cpu->P |= FLAG_C;
  1856. set_zero_and_negative_flags(cpu, cpu->X - value);
  1857. break;
  1858. case 0xE5: // SBC zp
  1859. address = get_address(cpu, AM_ZP);
  1860. value = cpu->mem[address];
  1861. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1862. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1863. if (!(result & 0x100))
  1864. cpu->P |= FLAG_C;
  1865. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1866. cpu->P |= FLAG_V;
  1867. cpu->A = result & 0xFF;
  1868. set_zero_and_negative_flags(cpu, cpu->A);
  1869. break;
  1870. case 0xE6: // INC zp
  1871. address = get_address(cpu, AM_ZP);
  1872. value = cpu->mem[address];
  1873. value++;
  1874. cpu->mem[address] = value;
  1875. set_zero_and_negative_flags(cpu, value);
  1876. break;
  1877. case 0xE7: // ISC zp
  1878. address = get_address(cpu, AM_ZP);
  1879. value = cpu->mem[address];
  1880. value++;
  1881. cpu->mem[address] = value;
  1882. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1883. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1884. if (!(result & 0x100))
  1885. cpu->P |= FLAG_C;
  1886. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1887. cpu->P |= FLAG_V;
  1888. cpu->A = result & 0xFF;
  1889. set_zero_and_negative_flags(cpu, cpu->A);
  1890. break;
  1891. case 0xE8: // INX
  1892. cpu->X++;
  1893. set_zero_and_negative_flags(cpu, cpu->X);
  1894. break;
  1895. case 0xE9: // SBC imm
  1896. address = get_address(cpu, AM_IMM);
  1897. value = cpu->mem[address];
  1898. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1899. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1900. if (!(result & 0x100))
  1901. cpu->P |= FLAG_C;
  1902. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1903. cpu->P |= FLAG_V;
  1904. cpu->A = result & 0xFF;
  1905. set_zero_and_negative_flags(cpu, cpu->A);
  1906. break;
  1907. case 0xEA: // NOP
  1908. break;
  1909. case 0xEB: // SBC imm
  1910. address = get_address(cpu, AM_IMM);
  1911. value = cpu->mem[address];
  1912. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1913. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1914. if (!(result & 0x100))
  1915. cpu->P |= FLAG_C;
  1916. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1917. cpu->P |= FLAG_V;
  1918. cpu->A = result & 0xFF;
  1919. set_zero_and_negative_flags(cpu, cpu->A);
  1920. break;
  1921. case 0xEC: // CPX abs
  1922. address = get_address(cpu, AM_ABS);
  1923. value = cpu->mem[address];
  1924. cpu->P &= ~(FLAG_N | FLAG_Z | FLAG_C);
  1925. if (cpu->X >= value)
  1926. cpu->P |= FLAG_C;
  1927. set_zero_and_negative_flags(cpu, cpu->X - value);
  1928. break;
  1929. case 0xED: // SBC abs
  1930. address = get_address(cpu, AM_ABS);
  1931. value = cpu->mem[address];
  1932. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1933. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1934. if (!(result & 0x100))
  1935. cpu->P |= FLAG_C;
  1936. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1937. cpu->P |= FLAG_V;
  1938. cpu->A = result & 0xFF;
  1939. set_zero_and_negative_flags(cpu, cpu->A);
  1940. break;
  1941. case 0xEE: // INC abs
  1942. address = get_address(cpu, AM_ABS);
  1943. value = cpu->mem[address];
  1944. value++;
  1945. cpu->mem[address] = value;
  1946. set_zero_and_negative_flags(cpu, value);
  1947. break;
  1948. case 0xEF: // ISC abs
  1949. address = get_address(cpu, AM_ABS);
  1950. value = cpu->mem[address];
  1951. value++;
  1952. cpu->mem[address] = value;
  1953. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1954. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1955. if (!(result & 0x100))
  1956. cpu->P |= FLAG_C;
  1957. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1958. cpu->P |= FLAG_V;
  1959. cpu->A = result & 0xFF;
  1960. set_zero_and_negative_flags(cpu, cpu->A);
  1961. break;
  1962.  
  1963. // --- Fx ---
  1964. case 0xF0: // BEQ rel
  1965. address = get_address(cpu, AM_REL);
  1966. if (cpu->P & FLAG_Z)
  1967. cpu->PC = address;
  1968. break;
  1969. case 0xF1: // SBC izy
  1970. address = get_address(cpu, AM_IZY);
  1971. value = cpu->mem[address];
  1972. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1973. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1974. if (!(result & 0x100))
  1975. cpu->P |= FLAG_C;
  1976. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1977. cpu->P |= FLAG_V;
  1978. cpu->A = result & 0xFF;
  1979. set_zero_and_negative_flags(cpu, cpu->A);
  1980. break;
  1981. case 0xF3: // ISC izy
  1982. address = get_address(cpu, AM_IZY);
  1983. value = cpu->mem[address];
  1984. value++;
  1985. cpu->mem[address] = value;
  1986. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  1987. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  1988. if (!(result & 0x100))
  1989. cpu->P |= FLAG_C;
  1990. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  1991. cpu->P |= FLAG_V;
  1992. cpu->A = result & 0xFF;
  1993. set_zero_and_negative_flags(cpu, cpu->A);
  1994. break;
  1995. case 0xF4: // NOP zpx
  1996. get_address(cpu, AM_ZPX);
  1997. break;
  1998. case 0xF5: // SBC zpx
  1999. address = get_address(cpu, AM_ZPX);
  2000. value = cpu->mem[address];
  2001. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2002. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2003. if (!(result & 0x100))
  2004. cpu->P |= FLAG_C;
  2005. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2006. cpu->P |= FLAG_V;
  2007. cpu->A = result & 0xFF;
  2008. set_zero_and_negative_flags(cpu, cpu->A);
  2009. break;
  2010. case 0xF6: // INC zpx
  2011. address = get_address(cpu, AM_ZPX);
  2012. value = cpu->mem[address];
  2013. value++;
  2014. cpu->mem[address] = value;
  2015. set_zero_and_negative_flags(cpu, value);
  2016. break;
  2017. case 0xF7: // ISC zpx
  2018. address = get_address(cpu, AM_ZPX);
  2019. value = cpu->mem[address];
  2020. value++;
  2021. cpu->mem[address] = value;
  2022. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2023. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2024. if (!(result & 0x100))
  2025. cpu->P |= FLAG_C;
  2026. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2027. cpu->P |= FLAG_V;
  2028. cpu->A = result & 0xFF;
  2029. set_zero_and_negative_flags(cpu, cpu->A);
  2030. break;
  2031. case 0xF8: // SED
  2032. cpu->P |= FLAG_D;
  2033. break;
  2034. case 0xF9: // SBC aby
  2035. address = get_address(cpu, AM_ABY);
  2036. value = cpu->mem[address];
  2037. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2038. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2039. if (!(result & 0x100))
  2040. cpu->P |= FLAG_C;
  2041. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2042. cpu->P |= FLAG_V;
  2043. cpu->A = result & 0xFF;
  2044. set_zero_and_negative_flags(cpu, cpu->A);
  2045. break;
  2046. case 0xFA: // NOP
  2047. break;
  2048. case 0xFB: // ISC aby
  2049. address = get_address(cpu, AM_ABY);
  2050. value = cpu->mem[address];
  2051. value++;
  2052. cpu->mem[address] = value;
  2053. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2054. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2055. if (!(result & 0x100))
  2056. cpu->P |= FLAG_C;
  2057. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2058. cpu->P |= FLAG_V;
  2059. cpu->A = result & 0xFF;
  2060. set_zero_and_negative_flags(cpu, cpu->A);
  2061. break;
  2062. case 0xFC: // NOP abx
  2063. get_address(cpu, AM_ABX);
  2064. break;
  2065. case 0xFD: // SBC abx
  2066. address = get_address(cpu, AM_ABX);
  2067. value = cpu->mem[address];
  2068. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2069. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2070. if (!(result & 0x100))
  2071. cpu->P |= FLAG_C;
  2072. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2073. cpu->P |= FLAG_V;
  2074. cpu->A = result & 0xFF;
  2075. set_zero_and_negative_flags(cpu, cpu->A);
  2076. break;
  2077. case 0xFE: // INC abx
  2078. address = get_address(cpu, AM_ABX);
  2079. value = cpu->mem[address];
  2080. value++;
  2081. cpu->mem[address] = value;
  2082. set_zero_and_negative_flags(cpu, value);
  2083. break;
  2084. case 0xFF: // ISC abx
  2085. address = get_address(cpu, AM_ABX);
  2086. value = cpu->mem[address];
  2087. value++;
  2088. cpu->mem[address] = value;
  2089. result = cpu->A - value - ((cpu->P & FLAG_C) ? 0 : 1);
  2090. cpu->P &= ~(FLAG_N | FLAG_V | FLAG_Z | FLAG_C);
  2091. if (!(result & 0x100))
  2092. cpu->P |= FLAG_C;
  2093. if ((cpu->A ^ result) & (~value ^ result) & 0x80)
  2094. cpu->P |= FLAG_V;
  2095. cpu->A = result & 0xFF;
  2096. set_zero_and_negative_flags(cpu, cpu->A);
  2097. break;
  2098. default:
  2099. printf("Unknown Opcode: 0x%02X at $%04X\n", opcode, cpu->PC - 1);
  2100. cpu->PC = 0xFFFF;
  2101. break;
  2102.  
  2103. }
  2104. if (cpu->PC - 1 == 0x00FE)
  2105. {
  2106. cpu->mem[0x00fe] = rand() & 0xff;
  2107. }
  2108.  
  2109. if (address >= 0x200 && address < (0x200 + 160 * 160))
  2110. {
  2111. pixels[address - 0x200] = palette[cpu->mem[address]];
  2112. }
  2113. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement