diff options
Diffstat (limited to 'cpu.c')
| -rw-r--r-- | cpu.c | 101 |
1 files changed, 101 insertions, 0 deletions
@@ -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); + +} |
