summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-03-29 19:57:00 +0100
committerPeter Fors <peter.fors@mindkiller.com>2025-03-29 19:57:00 +0100
commite8ff6bf2ab9982c5e5ab8d8f4e7adcc5207d079d (patch)
treea91ec214f5cd0e95c3d26ee0ba916cb187e3aede /cpu.c
first mknes commit
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/cpu.c b/cpu.c
new file mode 100644
index 0000000..3e731e5
--- /dev/null
+++ b/cpu.c
@@ -0,0 +1,101 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+// REMOVE FOR NES!!!!!
+// #define ENABLE_DECIMAL_MODE
+
+__attribute__((always_inline))
+static inline uint8_t pack_flags(struct cpu_state *cpu) {
+ return (cpu->n << 7) | (cpu->v << 6) | (1 << 5) | (cpu->d << 3) | (cpu->i << 2) | (cpu->z << 1) | cpu->c;
+}
+
+__attribute__((always_inline))
+static inline void unpack_flags(struct cpu_state *cpu, uint8_t value) {
+ cpu->n = (value >> 7) & 1;
+ cpu->v = (value >> 6) & 1;
+ cpu->d = (value >> 3) & 1;
+ cpu->i = (value >> 2) & 1;
+ cpu->z = (value >> 1) & 1;
+ cpu->c = value & 1;
+}
+
+
+static inline void update_zn(struct cpu_state *cpu, uint8_t result) {
+ cpu->z = (result == 0);
+ cpu->n = (result & 0x80) != 0;
+}
+
+
+
+static void (*opcode_lut[256])(struct nes_state *state);
+
+uint32_t line = 1;
+
+struct addr_result {
+ uint32_t addr;
+ uint8_t value;
+};
+#include "cpu_opcodes.c"
+#include "cpu_opcodes_ud.c"
+
+static inline void do_nmi(struct nes_state * restrict state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ memory_read_dummy(state, cpu->pc); // T1: dummy read (fetch suppressed)
+
+ uint8_t pcl = cpu->pc & 0xff;
+ uint8_t pch = cpu->pc >> 8;
+
+ memory_write(state, 0x0100 + cpu->sp--, pch); // T2
+ memory_write(state, 0x0100 + cpu->sp--, pcl); // T3
+ memory_write(state, 0x0100 + cpu->sp--, pack_flags(cpu) & ~0x10); // T4: push P (B flag clear)
+
+ uint8_t lo = memory_read(state, 0xfffa); // T5
+ uint8_t hi = memory_read(state, 0xfffb); // T6
+
+ cpu->pc = lo | (hi << 8); // T7
+ cpu->i = 1;
+}
+
+static inline void do_irq(struct nes_state * restrict state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ memory_read_dummy(state, cpu->pc); // T1: dummy read (fetch suppressed)
+
+ uint8_t pcl = cpu->pc & 0xff;
+ uint8_t pch = cpu->pc >> 8;
+
+ memory_write(state, 0x0100 + cpu->sp--, pch); // T2
+ memory_write(state, 0x0100 + cpu->sp--, pcl); // T3
+ memory_write(state, 0x0100 + cpu->sp--, pack_flags(cpu) & ~0x10); // T4: push P (B flag clear)
+
+ uint8_t lo = memory_read(state, 0xfffe); // T5
+ uint8_t hi = memory_read(state, 0xffff); // T6
+
+ cpu->pc = lo | (hi << 8); // T7
+ cpu->i = 1;
+}
+
+static inline void check_interrupts(struct nes_state * restrict state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ if(state->nmi_pending) {
+ state->nmi_pending = 0;
+ do_nmi(state);
+ } else if(state->irq_pending && cpu->i == 0) {
+ do_irq(state);
+ }
+}
+
+static void cpu_tick(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ check_interrupts(state);
+
+ // printf("%5.5d %4.4x: ", line++, cpu->pc);
+ uint8_t opcode = memory_read(state, cpu->pc++);
+ // printf("%2.2x a:%2.2x x:%2.2x y:%2.2x p:%2.2x sp:%2.2x cycle: %d\n", opcode, cpu->a, cpu->x, cpu->y, pack_flags(cpu), cpu->sp, cycle);
+ opcode_lut[opcode](state);
+
+}