summaryrefslogtreecommitdiff
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
parent10567e0be8402bae1cd5d267b5739e9962ea028a (diff)
add peek(), peek16(), and finish lda()
-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 {
AM_INDIRECT_INDEXED,
};
-uint8_t memory[0x10000];
+/* 64K address space, 16bit words */
+uint8_t memory[0x16000];
/* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */
uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 };
+uint8_t
+peek(uint16_t addr)
+{
+ return memory[addr];
+}
+
+uint16_t
+peek16(uint16_t addr)
+{
+ /* bytes are stored in little-endian (low then high) */
+ return (uint16_t)memory[addr] | ((uint16_t)memory[addr + 1] << 8);
+}
+
void
brk(void)
{
@@ -79,39 +93,43 @@ inx(void)
void
lda(enum addressing_mode mode)
{
- uint8_t val;
+ uint8_t arg, val;
+
+ arg = peek(regs.pc++);
switch (mode) {
case AM_IMMEDIATE: /* $A9 */
- val = memory[regs.pc++];
- printf("arg1 $%02X\n", val);
- regs.a = val;
+ val = arg;
break;
case AM_ZERO_PAGE: /* $A5 */
- /* TODO */
- break;
- case AM_ZERO_PAGE_X: /* $B5 */
- /* TODO */
+ val = peek(arg % 256);
break;
case AM_ABSOLUTE: /* $AD */
- /* TODO */
+ val = peek(arg);
+ break;
+ case AM_ZERO_PAGE_X: /* $B5 */
+ val = peek((arg + regs.x) % 256);
break;
case AM_ABSOLUTE_X: /* $BD */
- /* TODO */
+ val = peek(arg + regs.x);
break;
case AM_ABSOLUTE_Y: /* $B9 */
- /* TODO */
+ val = peek(arg + regs.y);
break;
case AM_INDIRECT_X: /* $A1 */
- /* TODO */
+ val = peek(peek((arg + regs.x) % 256) + peek((arg + regs.x + 1) % 256) * 256);
break;
case AM_INDIRECT_Y: /* $B1 */
- /* TODO */
+ val = peek(peek(arg) + peek((arg + 1) % 256) * 256 + regs.y);
break;
default:
+ regs.pc--;
return;
}
+ printf("arg1 $%02X\n", arg);
+ regs.a = val;
+
STATUS_UPDATE_ZERO(regs.a);
STATUS_UPDATE_NEGATIVE(regs.a);
}
@@ -122,7 +140,7 @@ interpret(void)
uint8_t opcode;
for (;;) {
- opcode = memory[regs.pc++];
+ opcode = peek(regs.pc++);
printf("opcode: $%02X\n", opcode);
@@ -175,9 +193,23 @@ interpret(void)
}
}
+/* https://www.nesdev.org/wiki/CPU_power_up_state */
+void
+cpu_init(void)
+{
+ regs.a = regs.x = regs.y = 0;
+ regs.pc = 0xFFFC;
+ regs.sp = 0xFD;
+
+ memset(&regs.status, 0, sizeof(regs.status));
+ regs.status.unused = 1;
+}
+
int
main(void)
{
+ cpu_init();
+
if (sizeof(program) > (0x10000 - 0x8000)) {
fprintf(stderr, "program is too big for memory\n");
return 1;
@@ -185,8 +217,6 @@ main(void)
memcpy(memory + 0x8000, program, sizeof(program));
regs.pc = 0x8000;
- regs.status.unused = 1;
-
printf("Initial State:\n");
printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry,
regs.status.zero, regs.status.interrupt_disable,