summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2024-06-04 15:54:09 +0530
committervin <git@vineetk.net>2024-06-04 15:54:09 +0530
commit7245191e86e4c8da9fe18788e3daae9b30005812 (patch)
treec2650bf9af2b7c6eb5c43f8d32c342eeb14bfbf9 /cpu.c
parent10567e0be8402bae1cd5d267b5739e9962ea028a (diff)
add peek(), peek16(), and finish lda()
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/cpu.c b/cpu.c
index c7e76b8..770206d 100644
--- a/cpu.c
+++ b/cpu.c
@@ -42,11 +42,25 @@ enum addressing_mode {
42 AM_INDIRECT_INDEXED, 42 AM_INDIRECT_INDEXED,
43}; 43};
44 44
45uint8_t memory[0x10000]; 45/* 64K address space, 16bit words */
46uint8_t memory[0x16000];
46 47
47/* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */ 48/* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */
48uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 }; 49uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 };
49 50
51uint8_t
52peek(uint16_t addr)
53{
54 return memory[addr];
55}
56
57uint16_t
58peek16(uint16_t addr)
59{
60 /* bytes are stored in little-endian (low then high) */
61 return (uint16_t)memory[addr] | ((uint16_t)memory[addr + 1] << 8);
62}
63
50void 64void
51brk(void) 65brk(void)
52{ 66{
@@ -79,39 +93,43 @@ inx(void)
79void 93void
80lda(enum addressing_mode mode) 94lda(enum addressing_mode mode)
81{ 95{
82 uint8_t val; 96 uint8_t arg, val;
97
98 arg = peek(regs.pc++);
83 99
84 switch (mode) { 100 switch (mode) {
85 case AM_IMMEDIATE: /* $A9 */ 101 case AM_IMMEDIATE: /* $A9 */
86 val = memory[regs.pc++]; 102 val = arg;
87 printf("arg1 $%02X\n", val);
88 regs.a = val;
89 break; 103 break;
90 case AM_ZERO_PAGE: /* $A5 */ 104 case AM_ZERO_PAGE: /* $A5 */
91 /* TODO */ 105 val = peek(arg % 256);
92 break;
93 case AM_ZERO_PAGE_X: /* $B5 */
94 /* TODO */
95 break; 106 break;
96 case AM_ABSOLUTE: /* $AD */ 107 case AM_ABSOLUTE: /* $AD */
97 /* TODO */ 108 val = peek(arg);
109 break;
110 case AM_ZERO_PAGE_X: /* $B5 */
111 val = peek((arg + regs.x) % 256);
98 break; 112 break;
99 case AM_ABSOLUTE_X: /* $BD */ 113 case AM_ABSOLUTE_X: /* $BD */
100 /* TODO */ 114 val = peek(arg + regs.x);
101 break; 115 break;
102 case AM_ABSOLUTE_Y: /* $B9 */ 116 case AM_ABSOLUTE_Y: /* $B9 */
103 /* TODO */ 117 val = peek(arg + regs.y);
104 break; 118 break;
105 case AM_INDIRECT_X: /* $A1 */ 119 case AM_INDIRECT_X: /* $A1 */
106 /* TODO */ 120 val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256);
107 break; 121 break;
108 case AM_INDIRECT_Y: /* $B1 */ 122 case AM_INDIRECT_Y: /* $B1 */
109 /* TODO */ 123 val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y);
110 break; 124 break;
111 default: 125 default:
126 regs.pc--;
112 return; 127 return;
113 } 128 }
114 129
130 printf("arg1 $%02X\n", arg);
131 regs.a = val;
132
115 STATUS_UPDATE_ZERO(regs.a); 133 STATUS_UPDATE_ZERO(regs.a);
116 STATUS_UPDATE_NEGATIVE(regs.a); 134 STATUS_UPDATE_NEGATIVE(regs.a);
117} 135}
@@ -122,7 +140,7 @@ interpret(void)
122 uint8_t opcode; 140 uint8_t opcode;
123 141
124 for (;;) { 142 for (;;) {
125 opcode = memory[regs.pc++]; 143 opcode = peek(regs.pc++);
126 144
127 printf("opcode: $%02X\n", opcode); 145 printf("opcode: $%02X\n", opcode);
128 146
@@ -175,9 +193,23 @@ interpret(void)
175 } 193 }
176} 194}
177 195
196/* https://www.nesdev.org/wiki/CPU_power_up_state */
197void
198cpu_init(void)
199{
200 regs.a = regs.x = regs.y = 0;
201 regs.pc = 0xFFFC;
202 regs.sp = 0xFD;
203
204 memset(&regs.status, 0, sizeof(regs.status));
205 regs.status.unused = 1;
206}
207
178int 208int
179main(void) 209main(void)
180{ 210{
211 cpu_init();
212
181 if (sizeof(program) > (0x10000 - 0x8000)) { 213 if (sizeof(program) > (0x10000 - 0x8000)) {
182 fprintf(stderr, "program is too big for memory\n"); 214 fprintf(stderr, "program is too big for memory\n");
183 return 1; 215 return 1;
@@ -185,8 +217,6 @@ main(void)
185 memcpy(memory + 0x8000, program, sizeof(program)); 217 memcpy(memory + 0x8000, program, sizeof(program));
186 regs.pc = 0x8000; 218 regs.pc = 0x8000;
187 219
188 regs.status.unused = 1;
189
190 printf("Initial State:\n"); 220 printf("Initial State:\n");
191 printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry, 221 printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry,
192 regs.status.zero, regs.status.interrupt_disable, 222 regs.status.zero, regs.status.interrupt_disable,