1 #include "6502.h" 2 3 #include <stdio.h> 4 5 /* included for debugging purposes */ 6 #include <string.h> 7 8 static CPU cpu; 9 static MEM mem; /* 8 bit word */ 10 11 static uint8_t cyc; 12 static uint8_t opc; 13 14 static uint16_t tmp; 15 static uint16_t addr_abs; 16 static uint16_t addr_rel; 17 18 INS decode[0x100]; 19 static INS prev_ins; 20 21 /* Cpu methods */ 22 void CPU_init(void) { 23 cpu.ac = cpu.x = cpu.y = cpu.sp = cpu.st = 0; 24 cyc = opc = tmp = 0; 25 prev_ins = (INS) {"???", &NUL, &IMP, 7}; 26 } 27 28 void CPU_reset(void) { 29 cpu.sp = 0xFF; 30 cpu.st = 0x00; 31 32 /* little endian */ 33 uint16_t lo = MEM_read(0xFFFC); 34 uint16_t hi = MEM_read(0xFFFD); 35 36 cpu.pc = (hi << 8) | lo; 37 38 addr_abs = addr_rel = opc = 0x0000; 39 40 /* simulate 8 cycles needed to reset the cpu */ 41 cyc = 8; 42 } 43 44 void CPU_fetch(INS *ins) { 45 *ins = decode[opc = MEM_read(cpu.pc)]; 46 } 47 48 uint8_t CPU_exec(INS ins) { 49 /* simulate instructions cycles */ 50 do { 51 if (cyc == 0) { 52 if (!strcmp(ins.name, "???")) { 53 /* printf("EXEC: invalid instruction reached\n"); */ 54 return 1; 55 } else if (!strcmp(ins.name, "BNE") && !(strcmp(prev_ins.name, "BNE"))) { 56 /* printf("EXEC: consecutive BNE reached\n"); */ 57 return 1; 58 } 59 60 cpu.pc++; 61 cyc = ins.cycles; 62 63 uint8_t add_cyc_0 = ins.mode(); 64 uint8_t add_cyc_1 = ins.op(); 65 66 prev_ins = ins; 67 cyc += add_cyc_0 & add_cyc_1; 68 } 69 } while(--cyc); 70 71 return 0; 72 } 73 74 /* interrupt request */ 75 void CPU_irq(void) { 76 if(!CPU_get_flag(I)) { 77 /* save pc */ 78 MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF); 79 MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF); 80 81 /* save st */ 82 MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5)); 83 84 CPU_set_flag(I, 1); 85 86 uint16_t lo = MEM_read(0xFFFE); 87 uint16_t hi = MEM_read(0xFFFF); 88 89 cpu.pc = ((hi << 8) & 0xFF00) | (lo & 0x00FF); 90 91 cyc = 8; 92 } 93 } 94 95 /* non maskeable interrupt request */ 96 void CPU_nm_irq(void) { 97 /* save program counter to stack */ 98 MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF); 99 MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF); 100 101 /* save cpu status to stack */ 102 MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5)); 103 CPU_set_flag(I, 1); 104 105 addr_abs = 0xFFFA; 106 uint16_t lo = MEM_read(addr_abs + 0); 107 uint16_t hi = MEM_read(addr_abs + 1); 108 109 cpu.pc = (hi << 8) | lo; 110 111 cyc = 8; 112 } 113 114 void CPU_branch(void) { 115 cyc++; 116 addr_abs = cpu.pc + addr_rel; 117 118 /* if address changes page */ 119 if((addr_abs & 0xFF00) != (cpu.pc & 0xFF00)) 120 cyc++; 121 122 cpu.pc = addr_abs; 123 } 124 125 void CPU_set_flag(ST_FLAG flag, uint8_t val) { 126 cpu.st = val ? cpu.st | (1 << flag) : cpu.st & ~(1 << flag); 127 } 128 129 uint8_t CPU_get_flag(ST_FLAG flag) { 130 return (cpu.st & (1 << flag)) >> flag; 131 } 132 133 void print_reg(uint8_t reg) { 134 for(unsigned long i = ((sizeof(reg) * 8)); i > 0; i--) { 135 putchar((reg & (0x01 << (i - 1))) ? '1' : '0'); 136 putchar(' '); 137 } 138 } 139 140 void CPU_dump(void) { 141 INS aux = decode[MEM_read(cpu.pc)]; 142 143 printf("+--------------------------------------------+\n"); 144 printf("| A: 0x%02X (%03d) N V - B D I Z C |\n" 145 "| X: 0x%02X (%03d) ", cpu.ac, cpu.ac, cpu.x, cpu.x); 146 print_reg(cpu.st); 147 printf("|\n"); 148 printf("| Y: 0x%02X (%03d) |\n" 149 "| SP: 0x%02X (%03d) |\n" 150 "| PC: 0x%04X -> 0x%02X (%s) |\n", 151 cpu.y, cpu.y, cpu.sp, cpu.sp, cpu.pc, mem.ram[cpu.pc], aux.name); 152 printf("+--------------------------------------------+\n\033[7A"); 153 } 154 155 uint16_t CPU_get_pc(void) { 156 return cpu.pc; 157 } 158 159 /* Memory methods */ 160 void MEM_init(void) { 161 for(uint16_t i = 0; i < 0xFFFF; i++) 162 mem.ram[i] = 0; 163 } 164 165 void MEM_set_pc_start(uint16_t addr) { 166 mem.ram[0xFFFC] = (addr & 0x00FF); 167 mem.ram[0xFFFD] = ((addr & 0xFF00) >> 8); 168 } 169 170 int MEM_load_from_file(char *path) { 171 FILE *fp; 172 173 if(path == NULL) { 174 return 1; 175 } 176 177 fp = fopen(path, "rb"); 178 if(fp == NULL) { 179 fprintf(stderr, "[ERROR]: file \"%s\" not found.\n", path); 180 return 2; 181 } 182 183 fread(mem.ram, 1, sizeof(mem.ram), fp); 184 /* fread(mem.ram + 0x8000, 1, 0x7FFF - 0x6, fp); */ 185 186 fclose(fp); 187 return 0; 188 } 189 190 uint8_t MEM_read(uint16_t addr) { 191 return mem.ram[addr]; 192 } 193 194 uint8_t MEM_write(uint16_t addr, uint8_t val) { 195 mem.ram[addr] = val; 196 return val; 197 } 198 199 void MEM_dump() { 200 for(uint16_t i = 0; i < 0xF; i++) 201 printf("%02X ", mem.ram[i]); 202 203 putchar('\n'); 204 } 205 206 void MEM_dump_page(uint16_t page) { 207 uint16_t j = 1; 208 209 printf("Page %04X:\n", page); 210 for(uint16_t i = page; i <= (page + 0xFF); i++, j++) 211 printf("%02X %s", mem.ram[i], (j % 0x1E) ? "" : "\n"); 212 213 putchar('\n'); 214 } 215 216 void MEM_dump_last_six(void) { 217 printf("Last six:\n"); 218 for(size_t i = 0xFFFA; i <= 0xFFFF; i++) 219 printf("%02X ", mem.ram[i]); 220 221 putchar('\n'); 222 } 223 224 char *CPU_mode_name(uint8_t (*mode)(void)) { 225 if(mode == &IMM) return "IMM"; 226 else if(mode == &ABS) return "ABS"; 227 else if(mode == &ABX) return "ABX"; 228 else if(mode == &ABY) return "ABY"; 229 else if(mode == &IMP) return "IMP"; 230 else if(mode == &IND) return "IND"; 231 else if(mode == &IZX) return "IZX"; 232 else if(mode == &IZY) return "IZY"; 233 else if(mode == &REL) return "REL"; 234 else if(mode == &ZP0) return "ZP0"; 235 else if(mode == &ZPX) return "ZPX"; 236 else if(mode == &ZPY) return "ZPY"; 237 238 return "NUL"; 239 } 240 241 /* Addressing modes */ 242 uint8_t ABS(void) { 243 uint16_t lo = MEM_read(cpu.pc++); 244 uint16_t hi = MEM_read(cpu.pc++); 245 246 addr_abs = (hi << 8) | lo; 247 248 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 249 return 0; 250 } 251 252 uint8_t ABX(void) { 253 uint16_t lo = MEM_read(cpu.pc++); 254 uint16_t hi = MEM_read(cpu.pc++); 255 256 addr_abs = (hi << 8) | lo; 257 258 /* printf("address fetched: %04X\nx register: %02X\nend address: %04X (%02X)\n", addr_abs, cpu.x, addr_abs + cpu.x, MEM_read(addr_abs + cpu.x)); */ 259 260 addr_abs += cpu.x; 261 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 262 263 return ((addr_abs & 0x00FF) != (hi << 8)) ? 1 : 0; 264 } 265 266 uint8_t ABY(void) { 267 uint16_t lo = MEM_read(cpu.pc++); 268 uint16_t hi = MEM_read(cpu.pc++); 269 270 addr_abs = (hi << 8) | lo; 271 272 /* printf("address fetched: %04X\ny register: %02X\nend address: %04X (%02X)\n", addr_abs, cpu.y, addr_abs + cpu.y, MEM_read(addr_abs + cpu.y)); */ 273 274 addr_abs += cpu.y; 275 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 276 return ((addr_abs & 0x00FF) != (hi << 8)) ? 1 : 0; 277 } 278 279 uint8_t IMM(void) { 280 addr_abs = cpu.pc++; 281 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 282 return 0; 283 } 284 285 uint8_t IMP(void) { 286 tmp = cpu.ac; 287 return 0; 288 } 289 290 uint8_t IND(void) { 291 /* get a direction from memory */ 292 uint16_t lo = MEM_read(cpu.pc++); 293 uint16_t hi = MEM_read(cpu.pc++); 294 295 /* assign the direction to ptr */ 296 uint16_t p = (hi << 8) | lo; 297 298 /* get the address pointed by p 299 * and simulate page boundary hardware bug */ 300 addr_abs = (MEM_read((lo == 0xFF) ? (p & 0xFF00) : p + 1) << 8) | MEM_read(p); 301 302 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 303 return 0; 304 } 305 306 uint8_t IZX(void) { 307 uint8_t addr = MEM_read(cpu.pc++); 308 309 /* get a direction from memory */ 310 uint16_t lo = MEM_read((addr + cpu.x) & 0xFF); 311 uint16_t hi = MEM_read((addr + cpu.x + 1) & 0xFF); 312 313 addr_abs = ((hi << 8) & 0xFF00) | lo; 314 315 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 316 317 return 0; 318 } 319 320 uint8_t IZY(void) { 321 uint8_t addr = MEM_read(cpu.pc++); 322 323 /* get a direction from memory */ 324 uint16_t lo = MEM_read(addr); 325 uint16_t hi = MEM_read(addr + 1); 326 327 addr_abs = ((hi << 8) & 0xFF00) | lo; 328 addr_abs += cpu.y; 329 330 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 331 332 return ((addr_abs & 0xFF00) != (hi << 8)) ? 1 : 0; 333 } 334 335 uint8_t REL(void) { 336 addr_rel = (MEM_read(cpu.pc++) & 0x00FF); 337 /* printf("REL: offset: %02X (%d)\n", addr_rel, (int8_t)addr_rel); */ 338 339 /* signed byte */ 340 if (addr_rel & (1 << 7)) 341 addr_rel |= 0xFF00; 342 343 return 0; 344 } 345 346 /* read only the offset of the zero page */ 347 uint8_t ZP0(void) { 348 addr_abs = (MEM_read(cpu.pc++) & 0x00FF); 349 350 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 351 return 0; 352 } 353 354 uint8_t ZPX(void) { 355 addr_abs = (MEM_read(cpu.pc++) + cpu.x) & 0x00FF; 356 357 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 358 return 0; 359 } 360 361 uint8_t ZPY(void) { 362 addr_abs = (MEM_read(cpu.pc++) + cpu.y) & 0x00FF; 363 364 /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */ 365 return 0; 366 } 367 368 369 /* Instructions */ 370 uint8_t ADC(void) { 371 uint16_t data = MEM_read(addr_abs); 372 uint16_t res = (cpu.ac + data + (uint16_t)CPU_get_flag(C)); 373 374 CPU_set_flag(N, res & (1 << 7)); 375 CPU_set_flag(Z, (res & 0x00FF) == 0); 376 CPU_set_flag(C, ((res & 0xFF00) >> 7)); 377 CPU_set_flag(V, ((cpu.ac^res) & ~(cpu.ac^data)) & (1 << 7)); 378 379 cpu.ac = (uint8_t)(res & 0x00FF); 380 381 return 1; 382 } 383 384 uint8_t AND(void) { 385 cpu.ac &= MEM_read(addr_abs); 386 387 CPU_set_flag(Z, cpu.ac == 0); 388 CPU_set_flag(N, cpu.ac & (1 << 7)); 389 390 return 1; 391 } 392 393 uint8_t ASL(void) { 394 if(decode[opc].mode == &IMP) { 395 tmp = cpu.ac << 1; 396 CPU_set_flag(C, (cpu.ac & (1 << 7))); 397 cpu.ac = (tmp & 0x00FF); 398 } 399 else { 400 tmp = MEM_read(addr_abs) << 1; 401 CPU_set_flag(C, MEM_read(addr_abs) & (1 << 7)); 402 MEM_write(addr_abs, tmp & 0x00FF); 403 } 404 405 CPU_set_flag(Z, tmp == 0); 406 CPU_set_flag(N, tmp & (1 << 7)); 407 408 return 0; 409 } 410 411 uint8_t BCC(void) { 412 if(!CPU_get_flag(C)) 413 CPU_branch(); 414 415 return 0; 416 } 417 418 uint8_t BCS(void) { 419 if(CPU_get_flag(C)) 420 CPU_branch(); 421 422 return 0; 423 } 424 425 uint8_t BEQ(void) { 426 if(CPU_get_flag(Z)) 427 CPU_branch(); 428 429 return 0; 430 } 431 432 uint8_t BIT(void) { 433 tmp = (MEM_read(addr_abs) & 0x00FF); 434 435 CPU_set_flag(Z, (cpu.ac & tmp) == 0); 436 CPU_set_flag(V, tmp & (1 << 6)); 437 CPU_set_flag(N, tmp & (1 << 7)); 438 439 return 0; 440 } 441 442 uint8_t BMI(void) { 443 if(CPU_get_flag(N)) 444 CPU_branch(); 445 446 return 0; 447 } 448 449 uint8_t BNE(void) { 450 if(!CPU_get_flag(Z)) 451 CPU_branch(); 452 453 return 0; 454 } 455 456 uint8_t BPL(void) { 457 if(!CPU_get_flag(N)) 458 CPU_branch(); 459 460 return 0; 461 } 462 463 uint8_t BRK(void) { 464 /* save program counter to stack */ 465 MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF); 466 MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF); 467 468 /* save cpu status to stack */ 469 MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5)); 470 CPU_set_flag(I, 1); 471 472 uint16_t lo = MEM_read(0xFFFE); 473 uint16_t hi = MEM_read(0xFFFF); 474 475 cpu.pc = (hi << 8) | lo; 476 477 return 0; 478 } 479 480 uint8_t BVC(void) { 481 if(!CPU_get_flag(V)) 482 CPU_branch(); 483 484 return 0; 485 } 486 487 uint8_t BVS(void) { 488 if(CPU_get_flag(V)) 489 CPU_branch(); 490 491 return 0; 492 } 493 494 uint8_t CLC(void) { 495 CPU_set_flag(C, 0); 496 return 0; 497 } 498 499 uint8_t CLD(void) { 500 CPU_set_flag(D, 0); 501 return 0; 502 } 503 504 uint8_t CLI(void) { 505 CPU_set_flag(I, 0); 506 return 0; 507 } 508 509 uint8_t CLV(void) { 510 CPU_set_flag(V, 0); 511 return 0; 512 } 513 514 uint8_t CMP(void) { 515 tmp = (MEM_read(addr_abs) & 0x00FF); 516 517 /* printf("cmp: %d, acc: %d\n", tmp, cpu.ac); */ 518 519 CPU_set_flag(C, cpu.ac >= tmp); 520 CPU_set_flag(Z, cpu.ac == tmp); 521 CPU_set_flag(N, (cpu.ac - tmp) & (1<<7)); 522 523 return 0; 524 } 525 526 uint8_t CPX(void) { 527 tmp = (MEM_read(addr_abs) & 0x00FF); 528 529 CPU_set_flag(C, cpu.x >= tmp); 530 CPU_set_flag(Z, cpu.x == tmp); 531 CPU_set_flag(N, (cpu.x - tmp) & (1<<7)); 532 533 return 0; 534 } 535 536 uint8_t CPY(void) { 537 tmp = (MEM_read(addr_abs) & 0x00FF); 538 539 CPU_set_flag(C, cpu.y >= tmp); 540 CPU_set_flag(Z, cpu.y == tmp); 541 CPU_set_flag(N, (cpu.y - tmp) & (1<<7)); 542 543 return 0; 544 } 545 546 uint8_t DEC(void) { 547 tmp = MEM_write(addr_abs, MEM_read(addr_abs) - 1) & 0x00FF; 548 549 CPU_set_flag(Z, tmp == 0); 550 CPU_set_flag(N, tmp & (1 << 7)); 551 552 return 0; 553 } 554 555 /* Decrements X register */ 556 uint8_t DEX(void) { 557 cpu.x -= 1; 558 559 CPU_set_flag(Z, cpu.x == 0); 560 CPU_set_flag(N, cpu.x & (1 << 7)); 561 562 return 0; 563 } 564 565 /* Decrements Y register */ 566 uint8_t DEY(void) { 567 cpu.y -= 1; 568 569 CPU_set_flag(Z, cpu.y == 0); 570 CPU_set_flag(N, cpu.y & (1 << 7)); 571 572 return 0; 573 } 574 575 uint8_t EOR(void) { 576 cpu.ac ^= MEM_read(addr_abs); 577 578 CPU_set_flag(Z, cpu.ac == 0); 579 CPU_set_flag(N, cpu.ac & (1 << 7)); 580 581 return 1; 582 } 583 584 uint8_t INC(void) { 585 tmp = MEM_write(addr_abs, MEM_read(addr_abs) + 1) & 0x00FF; 586 587 CPU_set_flag(Z, tmp == 0); 588 CPU_set_flag(N, tmp & (1 << 7)); 589 590 return 0; 591 } 592 593 uint8_t INX(void) { 594 cpu.x += 1; 595 596 CPU_set_flag(Z, cpu.x == 0); 597 CPU_set_flag(N, cpu.x & (1 << 7)); 598 599 return 0; 600 } 601 602 uint8_t INY(void) { 603 cpu.y += 1; 604 605 CPU_set_flag(Z, cpu.y == 0); 606 CPU_set_flag(N, cpu.y & (1 << 7)); 607 608 return 0; 609 } 610 611 uint8_t JMP(void) { 612 cpu.pc = addr_abs; 613 return 0; 614 } 615 616 uint8_t JSR(void) { 617 cpu.pc--; 618 619 MEM_write(0x100 + cpu.sp--, (cpu.pc & 0xFF00) >> 8); 620 MEM_write(0x100 + cpu.sp--, (cpu.pc & 0x00FF)); 621 622 cpu.pc = addr_abs; 623 624 return 0; 625 } 626 627 uint8_t LDA(void) { 628 cpu.ac = MEM_read(addr_abs); 629 630 CPU_set_flag(Z, cpu.ac == 0); 631 CPU_set_flag(N, cpu.ac & (1 << 7)); 632 633 return 1; 634 } 635 636 uint8_t LDX(void) { 637 cpu.x = MEM_read(addr_abs); 638 639 CPU_set_flag(Z, cpu.x == 0); 640 CPU_set_flag(N, cpu.x & (1 << 7)); 641 642 return 1; 643 } 644 645 uint8_t LDY(void) { 646 cpu.y = MEM_read(addr_abs); 647 648 CPU_set_flag(Z, cpu.y == 0); 649 CPU_set_flag(N, cpu.y & (1 << 7)); 650 651 return 1; 652 } 653 654 uint8_t LSR(void) { 655 if(decode[opc].mode == &IMP) { 656 tmp = (cpu.ac >> 1); 657 CPU_set_flag(C, cpu.ac & 0x01); 658 cpu.ac = (tmp & 0x00FF); 659 } 660 else { 661 tmp = (MEM_read(addr_abs) >> 1); 662 CPU_set_flag(C, MEM_read(addr_abs) & 0x01); 663 MEM_write(addr_abs, tmp & 0x00FF); 664 } 665 666 CPU_set_flag(Z, tmp == 0); 667 CPU_set_flag(N, tmp & (1 << 7)); 668 669 return 0; 670 } 671 672 uint8_t NOP(void) { 673 return 0; 674 } 675 676 uint8_t ORA(void) { 677 cpu.ac |= MEM_read(addr_abs); 678 679 CPU_set_flag(Z, cpu.ac == 0); 680 CPU_set_flag(N, cpu.ac & (1 << 7)); 681 682 return 1; 683 } 684 685 uint8_t PHA(void) { 686 MEM_write(0x100 + cpu.sp--, cpu.ac); 687 688 return 0; 689 } 690 691 uint8_t PHP(void) { 692 MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5)); 693 694 return 0; 695 } 696 697 uint8_t PLA(void) { 698 cpu.ac = MEM_read(0x100 + ++cpu.sp); 699 700 CPU_set_flag(Z, (cpu.ac == 0)); 701 CPU_set_flag(N, cpu.ac & (1 << 7)); 702 703 return 0; 704 } 705 706 uint8_t PLP(void) { 707 uint8_t B_is_set = CPU_get_flag(B); 708 uint8_t U_is_set = CPU_get_flag(U); 709 710 /* restore status */ 711 cpu.st = MEM_read(0x100 + ++cpu.sp); 712 713 /* This two flags stay the same as before */ 714 CPU_set_flag(B, B_is_set); 715 CPU_set_flag(U, U_is_set); 716 717 return 0; 718 } 719 720 uint8_t ROL(void) { 721 if(decode[opc].mode == &IMP) { 722 tmp = (cpu.ac << 1) & 0xFE; 723 tmp |= CPU_get_flag(C); 724 725 CPU_set_flag(C, cpu.ac & (1 << 7)); 726 cpu.ac = (tmp & 0x00FF); 727 } 728 else { 729 tmp = (MEM_read(addr_abs) << 1) & 0xFE; 730 tmp |= CPU_get_flag(C); 731 732 CPU_set_flag(C, MEM_read(addr_abs) & (1 << 7)); 733 MEM_write(addr_abs, tmp & 0x00FF); 734 } 735 736 CPU_set_flag(Z, tmp == 0); 737 CPU_set_flag(N, tmp & (1 << 7)); 738 739 return 0; 740 } 741 742 uint8_t ROR(void) { 743 if(decode[opc].mode == &IMP) { 744 tmp = (cpu.ac >> 1) & 0x7F; 745 tmp |= (CPU_get_flag(C) << 7); 746 747 CPU_set_flag(C, cpu.ac & 0x01); 748 749 cpu.ac = (tmp & 0x00FF); 750 } 751 else { 752 tmp = (MEM_read(addr_abs) >> 1) & 0x7F; 753 tmp |= (CPU_get_flag(C) << 7); 754 755 CPU_set_flag(C, MEM_read(addr_abs) & 1); 756 MEM_write(addr_abs, tmp & 0x00FF); 757 } 758 759 CPU_set_flag(Z, tmp == 0); 760 CPU_set_flag(N, tmp & (1 << 7)); 761 762 return 0; 763 } 764 765 uint8_t RTI(void) { 766 uint8_t B_is_set = CPU_get_flag(B); 767 uint8_t U_is_set = CPU_get_flag(U); 768 769 /* restore status */ 770 cpu.st = MEM_read(0x100 + ++cpu.sp); 771 772 /* This two flags stay the same as before */ 773 CPU_set_flag(B, B_is_set); 774 CPU_set_flag(U, U_is_set); 775 776 /* restore pc */ 777 cpu.pc = MEM_read(0x100 + ++cpu.sp); 778 cpu.pc |= (MEM_read(0x100 + ++cpu.sp) << 8); 779 780 return 0; 781 } 782 783 uint8_t RTS(void) { 784 cpu.pc = MEM_read(0x100 + ++cpu.sp); 785 cpu.pc |= (MEM_read(0x100 + ++cpu.sp) << 8); 786 787 CPU_set_flag(B, 0); 788 789 cpu.pc++; 790 791 return 0; 792 } 793 794 uint8_t SBC(void) { 795 uint16_t data = MEM_read(addr_abs) ^ 0xFF; 796 uint16_t res = (cpu.ac + data + (uint16_t)CPU_get_flag(C)); 797 798 CPU_set_flag(N, res & (1 << 7)); 799 CPU_set_flag(Z, (res & 0x00FF) == 0); 800 CPU_set_flag(C, ((res & 0xFF00) >> 7)); 801 CPU_set_flag(V, ((cpu.ac^res) & ~(cpu.ac^data)) & (1 << 7)); 802 803 cpu.ac = (uint8_t)(res & 0x00FF); 804 805 return 1; 806 } 807 808 uint8_t SEC(void) { 809 CPU_set_flag(C, 1); 810 return 0; 811 } 812 813 uint8_t SED(void) { 814 CPU_set_flag(D, 1); 815 return 0; 816 } 817 818 uint8_t SEI(void) { 819 CPU_set_flag(I, 1); 820 return 0; 821 } 822 823 uint8_t STA(void) { 824 MEM_write(addr_abs, cpu.ac); 825 return 0; 826 } 827 828 uint8_t STX(void) { 829 MEM_write(addr_abs, cpu.x); 830 return 0; 831 } 832 833 uint8_t STY(void) { 834 MEM_write(addr_abs, cpu.y); 835 return 0; 836 } 837 838 uint8_t TAX(void) { 839 cpu.x = cpu.ac; 840 841 CPU_set_flag(Z, cpu.x == 0); 842 CPU_set_flag(N, cpu.x & (1 << 7)); 843 844 return 0; 845 } 846 847 uint8_t TAY(void) { 848 cpu.y = cpu.ac; 849 850 CPU_set_flag(Z, cpu.y == 0); 851 CPU_set_flag(N, cpu.y & (1 << 7)); 852 853 return 0; 854 } 855 856 uint8_t TSX(void) { 857 cpu.x = cpu.sp; 858 859 CPU_set_flag(Z, cpu.x == 0); 860 CPU_set_flag(N, cpu.x & (1 << 7)); 861 862 return 0; 863 } 864 865 uint8_t TXA(void) { 866 cpu.ac = cpu.x; 867 868 CPU_set_flag(Z, cpu.ac == 0); 869 CPU_set_flag(N, cpu.ac & (1 << 7)); 870 871 return 0; 872 } 873 874 uint8_t TXS(void) { 875 cpu.sp = cpu.x; 876 877 return 0; 878 } 879 880 uint8_t TYA(void) { 881 cpu.ac = cpu.y; 882 883 CPU_set_flag(Z, cpu.ac == 0); 884 CPU_set_flag(N, cpu.ac & (1 << 7)); 885 886 return 0; 887 } 888 889 uint8_t NUL(void) { 890 return 0; 891 } 892 893 /* Lookup table */ 894 INS decode[0x100] = { 895 {"BRK", &BRK, &IMM, 7}, {"ORA", &ORA, &IZX, 6}, {"???", &NUL, &IMP, 2}, 896 {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ORA", &ORA, &ZP0, 3}, 897 {"ASL", &ASL, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PHP", &PHP, &IMP, 3}, 898 {"ORA", &ORA, &IMM, 2}, {"ASL", &ASL, &IMP, 2}, {"???", &NUL, &IMP, 2}, 899 {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABS, 4}, {"ASL", &ASL, &ABS, 6}, 900 {"???", &NUL, &IMP, 6}, {"BPL", &BPL, &REL, 2}, {"ORA", &ORA, &IZY, 5}, 901 {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, 902 {"ORA", &ORA, &ZPX, 4}, {"ASL", &ASL, &ZPX, 6}, {"???", &NUL, &IMP, 6}, 903 {"CLC", &CLC, &IMP, 2}, {"ORA", &ORA, &ABY, 4}, {"???", &NOP, &IMP, 2}, 904 {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABX, 4}, 905 {"ASL", &ASL, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"JSR", &JSR, &ABS, 6}, 906 {"AND", &AND, &IZX, 6}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, 907 {"BIT", &BIT, &ZP0, 3}, {"AND", &AND, &ZP0, 3}, {"ROL", &ROL, &ZP0, 5}, 908 {"???", &NUL, &IMP, 5}, {"PLP", &PLP, &IMP, 4}, {"AND", &AND, &IMM, 2}, 909 {"ROL", &ROL, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"BIT", &BIT, &ABS, 4}, 910 {"AND", &AND, &ABS, 4}, {"ROL", &ROL, &ABS, 6}, {"???", &NUL, &IMP, 6}, 911 {"BMI", &BMI, &REL, 2}, {"AND", &AND, &IZY, 5}, {"???", &NUL, &IMP, 2}, 912 {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"AND", &AND, &ZPX, 4}, 913 {"ROL", &ROL, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SEC", &SEC, &IMP, 2}, 914 {"AND", &AND, &ABY, 4}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7}, 915 {"???", &NOP, &IMP, 4}, {"AND", &AND, &ABX, 4}, {"ROL", &ROL, &ABX, 7}, 916 {"???", &NUL, &IMP, 7}, {"RTI", &RTI, &IMP, 6}, {"EOR", &EOR, &IZX, 6}, 917 {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, 918 {"EOR", &EOR, &ZP0, 3}, {"LSR", &LSR, &ZP0, 5}, {"???", &NUL, &IMP, 5}, 919 {"PHA", &PHA, &IMP, 3}, {"EOR", &EOR, &IMM, 2}, {"LSR", &LSR, &IMP, 2}, 920 {"???", &NUL, &IMP, 2}, {"JMP", &JMP, &ABS, 3}, {"EOR", &EOR, &ABS, 4}, 921 {"LSR", &LSR, &ABS, 6}, {"???", &NUL, &IMP, 6}, {"BVC", &BVC, &REL, 2}, 922 {"EOR", &EOR, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, 923 {"???", &NOP, &IMP, 4}, {"EOR", &EOR, &ZPX, 4}, {"LSR", &LSR, &ZPX, 6}, 924 {"???", &NUL, &IMP, 6}, {"CLI", &CLI, &IMP, 2}, {"EOR", &EOR, &ABY, 4}, 925 {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, 926 {"EOR", &EOR, &ABX, 4}, {"LSR", &LSR, &ABX, 7}, {"???", &NUL, &IMP, 7}, 927 {"RTS", &RTS, &IMP, 6}, {"ADC", &ADC, &IZX, 6}, {"???", &NUL, &IMP, 2}, 928 {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ADC", &ADC, &ZP0, 3}, 929 {"ROR", &ROR, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PLA", &PLA, &IMP, 4}, 930 {"ADC", &ADC, &IMM, 2}, {"ROR", &ROR, &IMP, 2}, {"???", &NUL, &IMP, 2}, 931 {"JMP", &JMP, &IND, 5}, {"ADC", &ADC, &ABS, 4}, {"ROR", &ROR, &ABS, 6}, 932 {"???", &NUL, &IMP, 6}, {"BVS", &BVS, &REL, 2}, {"ADC", &ADC, &IZY, 5}, 933 {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, 934 {"ADC", &ADC, &ZPX, 4}, {"ROR", &ROR, &ZPX, 6}, {"???", &NUL, &IMP, 6}, 935 {"SEI", &SEI, &IMP, 2}, {"ADC", &ADC, &ABY, 4}, {"???", &NOP, &IMP, 2}, 936 {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ADC", &ADC, &ABX, 4}, 937 {"ROR", &ROR, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 2}, 938 {"STA", &STA, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 6}, 939 {"STY", &STY, &ZP0, 3}, {"STA", &STA, &ZP0, 3}, {"STX", &STX, &ZP0, 3}, 940 {"???", &NUL, &IMP, 3}, {"DEY", &DEY, &IMP, 2}, {"???", &NOP, &IMP, 2}, 941 {"TXA", &TXA, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"STY", &STY, &ABS, 4}, 942 {"STA", &STA, &ABS, 4}, {"STX", &STX, &ABS, 4}, {"???", &NUL, &IMP, 4}, 943 {"BCC", &BCC, &REL, 2}, {"STA", &STA, &IZY, 6}, {"???", &NUL, &IMP, 2}, 944 {"???", &NUL, &IMP, 6}, {"STY", &STY, &ZPX, 4}, {"STA", &STA, &ZPX, 4}, 945 {"STX", &STX, &ZPY, 4}, {"???", &NUL, &IMP, 4}, {"TYA", &TYA, &IMP, 2}, 946 {"STA", &STA, &ABY, 5}, {"TXS", &TXS, &IMP, 2}, {"???", &NUL, &IMP, 5}, 947 {"???", &NOP, &IMP, 5}, {"STA", &STA, &ABX, 5}, {"???", &NUL, &IMP, 5}, 948 {"???", &NUL, &IMP, 5}, {"LDY", &LDY, &IMM, 2}, {"LDA", &LDA, &IZX, 6}, 949 {"LDX", &LDX, &IMM, 2}, {"???", &NUL, &IMP, 6}, {"LDY", &LDY, &ZP0, 3}, 950 {"LDA", &LDA, &ZP0, 3}, {"LDX", &LDX, &ZP0, 3}, {"???", &NUL, &IMP, 3}, 951 {"TAY", &TAY, &IMP, 2}, {"LDA", &LDA, &IMM, 2}, {"TAX", &TAX, &IMP, 2}, 952 {"???", &NUL, &IMP, 2}, {"LDY", &LDY, &ABS, 4}, {"LDA", &LDA, &ABS, 4}, 953 {"LDX", &LDX, &ABS, 4}, {"???", &NUL, &IMP, 4}, {"BCS", &BCS, &REL, 2}, 954 {"LDA", &LDA, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 5}, 955 {"LDY", &LDY, &ZPX, 4}, {"LDA", &LDA, &ZPX, 4}, {"LDX", &LDX, &ZPY, 4}, 956 {"???", &NUL, &IMP, 4}, {"CLV", &CLV, &IMP, 2}, {"LDA", &LDA, &ABY, 4}, 957 {"TSX", &TSX, &IMP, 2}, {"???", &NUL, &IMP, 4}, {"LDY", &LDY, &ABX, 4}, 958 {"LDA", &LDA, &ABX, 4}, {"LDX", &LDX, &ABY, 4}, {"???", &NUL, &IMP, 4}, 959 {"CPY", &CPY, &IMM, 2}, {"CMP", &CMP, &IZX, 6}, {"???", &NOP, &IMP, 2}, 960 {"???", &NUL, &IMP, 8}, {"CPY", &CPY, &ZP0, 3}, {"CMP", &CMP, &ZP0, 3}, 961 {"DEC", &DEC, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"INY", &INY, &IMP, 2}, 962 {"CMP", &CMP, &IMM, 2}, {"DEX", &DEX, &IMP, 2}, {"???", &NUL, &IMP, 2}, 963 {"CPY", &CPY, &ABS, 4}, {"CMP", &CMP, &ABS, 4}, {"DEC", &DEC, &ABS, 6}, 964 {"???", &NUL, &IMP, 6}, {"BNE", &BNE, &REL, 2}, {"CMP", &CMP, &IZY, 5}, 965 {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, 966 {"CMP", &CMP, &ZPX, 4}, {"DEC", &DEC, &ZPX, 6}, {"???", &NUL, &IMP, 6}, 967 {"CLD", &CLD, &IMP, 2}, {"CMP", &CMP, &ABY, 4}, {"NOP", &NOP, &IMP, 2}, 968 {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"CMP", &CMP, &ABX, 4}, 969 {"DEC", &DEC, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"CPX", &CPX, &IMM, 2}, 970 {"SBC", &SBC, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 8}, 971 {"CPX", &CPX, &ZP0, 3}, {"SBC", &SBC, &ZP0, 3}, {"INC", &INC, &ZP0, 5}, 972 {"???", &NUL, &IMP, 5}, {"INX", &INX, &IMP, 2}, {"SBC", &SBC, &IMM, 2}, 973 {"NOP", &NOP, &IMP, 2}, {"???", &SBC, &IMP, 2}, {"CPX", &CPX, &ABS, 4}, 974 {"SBC", &SBC, &ABS, 4}, {"INC", &INC, &ABS, 6}, {"???", &NUL, &IMP, 6}, 975 {"BEQ", &BEQ, &REL, 2}, {"SBC", &SBC, &IZY, 5}, {"???", &NUL, &IMP, 2}, 976 {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ZPX, 4}, 977 {"INC", &INC, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SED", &SED, &IMP, 2}, 978 {"SBC", &SBC, &ABY, 4}, {"NOP", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7}, 979 {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ABX, 4}, {"INC", &INC, &ABX, 7}, 980 {"???", &NUL, &IMP, 7} 981 }; 982
