summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2024-07-03 19:49:21 -0400
committervin <git@vineetk.net>2024-07-03 19:56:36 -0400
commit2236e79556053d9d59a613634433848f1f7cf513 (patch)
tree2eba2cbaf98b62403bfe210a70728040c5a114fb /cpu.c
parentd8bb5a5ccf96fed7e8084cf691c987ce56a8c995 (diff)
fix SBC bug in the rewrite and improve logging
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c89
1 files changed, 29 insertions, 60 deletions
diff --git a/cpu.c b/cpu.c
index 6e44c7f..df9c852 100644
--- a/cpu.c
+++ b/cpu.c
@@ -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
102static uint8_t
103opcode_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
151static uint16_t 102static uint16_t
152opcode_mem(enum addressing_mode mode) 103opcode_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)
271void 222void
272BIT(uint16_t arg) 223BIT(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)
628void 580void
629SBC(uint16_t arg) 581SBC(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
635void 597void
@@ -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 }
788loop_exit: 757loop_exit: