summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2024-06-08 17:41:06 +0530
committervin <git@vineetk.net>2024-06-08 17:41:17 +0530
commit1ac30a026b7877ca6b295c661d91b20eaddb01c9 (patch)
tree22b23ab204390641e84ce42581ee5408444dd993 /cpu.c
parentbd85b80ba7a7919a80ce6fd742b37d3e183f2e3a (diff)
add adc and actually fix peek/16
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/cpu.c b/cpu.c
index f018a44..08c6119 100644
--- a/cpu.c
+++ b/cpu.c
@@ -1,7 +1,10 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <stdio.h> 2#include <stdio.h>
3#include <stdlib.h>
3#include <string.h> 4#include <string.h>
4 5
6#define MAX(a, b) ((a > b) ? a : b)
7
5#define STATUS_UPDATE_ZERO(r) \ 8#define STATUS_UPDATE_ZERO(r) \
6 (regs.status.zero = r == 0) 9 (regs.status.zero = r == 0)
7#define STATUS_UPDATE_NEGATIVE(r) \ 10#define STATUS_UPDATE_NEGATIVE(r) \
@@ -47,12 +50,12 @@ uint8_t memory[0x16000];
47uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 }; 50uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 };
48 51
49uint8_t 52uint8_t
50peek(uint8_t addr) 53peek(uint16_t addr)
51{ 54{
52 return memory[addr]; 55 return memory[addr];
53} 56}
54 57
55uint8_t 58uint16_t
56peek16(uint16_t addr) 59peek16(uint16_t addr)
57{ 60{
58 /* bytes are stored in little-endian (low then high) */ 61 /* bytes are stored in little-endian (low then high) */
@@ -60,6 +63,58 @@ peek16(uint16_t addr)
60} 63}
61 64
62void 65void
66adc(enum addressing_mode mode)
67{
68 uint8_t arg, val;
69 uint16_t sum; // 16-bit sum makes it easier to determine carry flag
70
71 if (mode != AM_ABS && mode != AM_ABS_X && mode != AM_ABS_Y)
72 arg = peek(regs.pc++);
73 else
74 arg = peek16(regs.pc++);
75
76 switch (mode) {
77 case AM_IMM: /* $69 */
78 val = arg;
79 break;
80 case AM_ZP: /* $65 */
81 val = peek(arg % 256);
82 break;
83 case AM_ABS: /* $6D */
84 val = peek16(arg);
85 break;
86 case AM_ZP_X: /* $75 */
87 val = peek((arg + regs.x) % 256);
88 break;
89 case AM_ABS_X: /* $7D */
90 val = peek16(arg + regs.x);
91 break;
92 case AM_ABS_Y: /* $79 */
93 val = peek16(arg + regs.y);
94 break;
95 case AM_IND_X: /* $61 */
96 val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256);
97 break;
98 case AM_IND_Y: /* $71 */
99 val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y);
100 break;
101 default:
102 fprintf(stderr, "INVALID ADC ADDRESSING MODE\n");
103 abort();
104 return;
105 }
106
107 sum = regs.a + val + regs.status.carry;
108 regs.a = sum & 0xFF;
109
110 regs.status.carry = sum > 0xFF;
111 /* overflow flag formula: https://stackoverflow.com/a/29224684 */
112 regs.status.overflow = ~(regs.a ^ arg) & (regs.a ^ sum) & 0x80;
113 STATUS_UPDATE_ZERO(regs.a);
114 STATUS_UPDATE_NEGATIVE(regs.a);
115}
116
117void
63brk(void) 118brk(void)
64{ 119{
65 /* $00 */ 120 /* $00 */
@@ -150,6 +205,30 @@ interpret(void)
150 case 0x00: 205 case 0x00:
151 brk(); 206 brk();
152 return; 207 return;
208 case 0x61:
209 adc(AM_IND_X);
210 break;
211 case 0x65:
212 adc(AM_ZP);
213 break;
214 case 0x69:
215 adc(AM_IMM);
216 break;
217 case 0x6D:
218 adc(AM_ABS);
219 break;
220 case 0x71:
221 adc(AM_IND_Y);
222 break;
223 case 0x75:
224 adc(AM_ZP_X);
225 break;
226 case 0x79:
227 adc(AM_ABS_Y);
228 break;
229 case 0x7D:
230 adc(AM_ABS_X);
231 break;
153 case 0xa1: 232 case 0xa1:
154 lda(AM_IND_X); 233 lda(AM_IND_X);
155 break; 234 break;
@@ -216,6 +295,7 @@ main(void)
216 fprintf(stderr, "program is too big for memory\n"); 295 fprintf(stderr, "program is too big for memory\n");
217 return 1; 296 return 1;
218 } 297 }
298
219 memcpy(memory + 0x8000, program, sizeof(program)); 299 memcpy(memory + 0x8000, program, sizeof(program));
220 regs.pc = 0x8000; 300 regs.pc = 0x8000;
221 301