diff options
| author | vin <git@vineetk.net> | 2024-07-03 19:49:21 -0400 |
|---|---|---|
| committer | vin <git@vineetk.net> | 2024-07-03 19:56:36 -0400 |
| commit | 2236e79556053d9d59a613634433848f1f7cf513 (patch) | |
| tree | 2eba2cbaf98b62403bfe210a70728040c5a114fb /cpu.c | |
| parent | d8bb5a5ccf96fed7e8084cf691c987ce56a8c995 (diff) | |
fix SBC bug in the rewrite and improve logging
Diffstat (limited to 'cpu.c')
| -rw-r--r-- | cpu.c | 89 |
1 files changed, 29 insertions, 60 deletions
| @@ -99,55 +99,6 @@ memwrite16(uint16_t addr, uint16_t word) | |||
| 99 | memory[addr + 1] = (word & 0xFF00) >> 8; | 99 | memory[addr + 1] = (word & 0xFF00) >> 8; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static uint8_t | ||
| 103 | opcode_arg(enum addressing_mode mode) | ||
| 104 | { | ||
| 105 | uint16_t arg, val; | ||
| 106 | |||
| 107 | if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y) { | ||
| 108 | arg = peek(regs.pc++); | ||
| 109 | } else { | ||
| 110 | arg = peek16(regs.pc); | ||
| 111 | regs.pc += 2; | ||
| 112 | } | ||
| 113 | |||
| 114 | switch (mode) { | ||
| 115 | case AM_IMM: | ||
| 116 | case AM_REL: | ||
| 117 | val = arg; | ||
| 118 | break; | ||
| 119 | case AM_ZP: | ||
| 120 | val = peek(arg % 256); | ||
| 121 | break; | ||
| 122 | case AM_ZP_X: | ||
| 123 | val = peek((arg + regs.x) % 256); | ||
| 124 | break; | ||
| 125 | case AM_ZP_Y: | ||
| 126 | val = peek((arg + regs.y) % 256); | ||
| 127 | break; | ||
| 128 | case AM_ABS: | ||
| 129 | val = peek16(arg); | ||
| 130 | break; | ||
| 131 | case AM_ABS_X: | ||
| 132 | val = peek16(arg + regs.x); | ||
| 133 | break; | ||
| 134 | case AM_ABS_Y: | ||
| 135 | val = peek16(arg + regs.y); | ||
| 136 | break; | ||
| 137 | case AM_IND_X: | ||
| 138 | val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256); | ||
| 139 | break; | ||
| 140 | case AM_IND_Y: | ||
| 141 | val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y); | ||
| 142 | break; | ||
| 143 | default: | ||
| 144 | fprintf(stderr, "INVALID ADDRESSING MODE %i\n", mode); | ||
| 145 | abort(); | ||
| 146 | } | ||
| 147 | |||
| 148 | return val; | ||
| 149 | } | ||
| 150 | |||
| 151 | static uint16_t | 102 | static uint16_t |
| 152 | opcode_mem(enum addressing_mode mode) | 103 | opcode_mem(enum addressing_mode mode) |
| 153 | { | 104 | { |
| @@ -193,7 +144,7 @@ opcode_mem(enum addressing_mode mode) | |||
| 193 | val = peek(arg) + peek((arg + 1) % 256) * 256 + regs.y; | 144 | val = peek(arg) + peek((arg + 1) % 256) * 256 + regs.y; |
| 194 | break; | 145 | break; |
| 195 | default: | 146 | default: |
| 196 | fprintf(stderr, "opcode_mem INVALID ADDRESSING MODE %i\n", mode); | 147 | fprintf(stderr, "INVALID ADDRESSING MODE %i\n", mode); |
| 197 | abort(); | 148 | abort(); |
| 198 | } | 149 | } |
| 199 | 150 | ||
| @@ -271,7 +222,8 @@ BEQ(uint16_t arg) | |||
| 271 | void | 222 | void |
| 272 | BIT(uint16_t arg) | 223 | BIT(uint16_t arg) |
| 273 | { | 224 | { |
| 274 | uint8_t tmp = peek(arg); | 225 | uint8_t tmp = arg; |
| 226 | |||
| 275 | regs.status.zero = (regs.a & tmp) == 0; | 227 | regs.status.zero = (regs.a & tmp) == 0; |
| 276 | regs.status.overflow = (tmp & (1 << 6)) != 0; | 228 | regs.status.overflow = (tmp & (1 << 6)) != 0; |
| 277 | STATUS_UPDATE_NEGATIVE(tmp); | 229 | STATUS_UPDATE_NEGATIVE(tmp); |
| @@ -628,8 +580,18 @@ RTS(uint16_t arg) | |||
| 628 | void | 580 | void |
| 629 | SBC(uint16_t arg) | 581 | SBC(uint16_t arg) |
| 630 | { | 582 | { |
| 631 | /* SBC is described online as ADC with argument as two's complement */ | 583 | uint8_t tmp = arg & 0xFF; |
| 632 | ADC(~(uint8_t)arg); | 584 | uint16_t diff; |
| 585 | |||
| 586 | diff = regs.a - tmp - !regs.status.carry; | ||
| 587 | |||
| 588 | regs.status.carry = diff > 0xFF; | ||
| 589 | regs.status.carry = !regs.status.carry; | ||
| 590 | /* overflow flag formula: https://stackoverflow.com/a/29224684 */ | ||
| 591 | regs.status.overflow = ((regs.a ^ arg) & (regs.a ^ diff) & 0x80) != 0; | ||
| 592 | regs.a = diff & 0xFF; | ||
| 593 | |||
| 594 | STATUS_UPDATE_NZ(regs.a); | ||
| 633 | } | 595 | } |
| 634 | 596 | ||
| 635 | void | 597 | void |
| @@ -759,10 +721,10 @@ interpret(void) | |||
| 759 | printf("$%04X", arg); | 721 | printf("$%04X", arg); |
| 760 | break; | 722 | break; |
| 761 | case AM_ABS_X: | 723 | case AM_ABS_X: |
| 762 | printf("$%04X,X", arg); | 724 | printf("$%04X,X @ %04X", arg - regs.x, arg); |
| 763 | break; | 725 | break; |
| 764 | case AM_ABS_Y: | 726 | case AM_ABS_Y: |
| 765 | printf("$%04X,Y", arg); | 727 | printf("$%04X,Y @ %04X", arg - regs.y, arg); |
| 766 | break; | 728 | break; |
| 767 | case AM_IND: | 729 | case AM_IND: |
| 768 | printf("($%04X) = %04X\t\t", arg, peek16(arg)); | 730 | printf("($%04X) = %04X\t\t", arg, peek16(arg)); |
| @@ -776,13 +738,20 @@ interpret(void) | |||
| 776 | break; | 738 | break; |
| 777 | } | 739 | } |
| 778 | 740 | ||
| 779 | if (opcodes[op].didmemory) printf(" = %02X", peek(arg)); | 741 | if (opcodes[op].memread || opcodes[op].memwrite) |
| 780 | printf("\t\t\t"); | 742 | printf(" = %02X", peek(arg)); |
| 743 | |||
| 744 | if (mode != AM_ABS_X && mode != AM_ABS_Y) | ||
| 745 | putchar('\t'); | ||
| 746 | printf("\t\t"); | ||
| 781 | 747 | ||
| 782 | printf("A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%d %08b\n", | 748 | printf("A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%d\n", |
| 783 | regs.a, regs.x, regs.y, STATUS_TO_INT(), regs.sp, cycles, STATUS_TO_INT()); | 749 | regs.a, regs.x, regs.y, STATUS_TO_INT(), regs.sp, cycles); |
| 784 | 750 | ||
| 785 | opcodes[op].instr(arg); | 751 | if (opcodes[op].memread) |
| 752 | opcodes[op].instr(peek(arg)); | ||
| 753 | else | ||
| 754 | opcodes[op].instr(arg); | ||
| 786 | cycles += opcodes[op].cycles; | 755 | cycles += opcodes[op].cycles; |
| 787 | } | 756 | } |
| 788 | loop_exit: | 757 | loop_exit: |
