summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-04-28 18:27:17 +0200
committerPeter Fors <peter.fors@mindkiller.com>2025-04-28 18:27:17 +0200
commitc40f7421d8c1ccbe008dbd2191c6642625ae4b83 (patch)
tree9779e0a5cff2adec44897dab43d3838e8e61d3fe
parent8a32bcfac621dfcaa6af832228e56713a4af6156 (diff)
before ppu rearrangement and fix of scanline 261
-rwxr-xr-xbuild.sh3
-rw-r--r--cpu_opcodes.c14
-rw-r--r--memory.c48
-rw-r--r--mknes.c26
-rw-r--r--mknes.h11
-rw-r--r--ppu.c5
-rw-r--r--ppu_registers.c4
7 files changed, 75 insertions, 36 deletions
diff --git a/build.sh b/build.sh
index 611ca19..8858da4 100755
--- a/build.sh
+++ b/build.sh
@@ -9,12 +9,13 @@ CFLAGS+="-mbmi2 "
CFLAGS+="-mfunction-return=keep "
CFLAGS+="-mindirect-branch=keep "
CFLAGS+="-fwrapv -ffast-math -fno-trapping-math -fwhole-program -fvisibility=hidden "
-CFLAGS+="-fno-stack-protector -fno-PIE -no-pie -fno-strict-aliasing -ffunction-sections -fdata-sections "
+CFLAGS+="-fno-stack-protector -fno-PIE -no-pie -fno-strict-aliasing -fcf-protection=none -ffunction-sections -fdata-sections "
# CFLAGS+="-fno-exceptions -fno-rtti -fno-use-cxa-atexit "
CFLAGS+="-fno-non-call-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables "
CFLAGS+="-Wall -Wextra "
CFLAGS+="-Wno-unused-parameter -Wno-sign-compare -Wno-trigraphs -Wno-maybe-uninitialized "
CFLAGS+="-Wno-unused-variable -Wno-unused-const-variable -Wno-unused-function -Wno-write-strings -Wno-missing-field-initializers "
+CFLAGS+="-U_FORTIFY_SOURCE -fno-pic "
LDFLAGS="-Wl,--gc-sections -Wl,--as-needed "
diff --git a/cpu_opcodes.c b/cpu_opcodes.c
index b879015..7e174be 100644
--- a/cpu_opcodes.c
+++ b/cpu_opcodes.c
@@ -1,7 +1,7 @@
// ADC
-
+__attribute__((always_inline, hot))
static inline void adc(struct cpu_state * restrict cpu, uint8_t value) {
#ifdef ENABLE_DECIMAL_MODE
if(cpu->d) {
@@ -407,7 +407,7 @@ static void opcode_brk(struct nes_state * restrict state) {
// BRANCHES
-
+__attribute__((always_inline, hot))
static inline int page_crossed(uint16_t a, uint16_t b) {
return (a & 0xff00) != (b & 0xff00);
}
@@ -583,6 +583,7 @@ static void opcode_sei(struct nes_state * restrict state) {
// CMP
+__attribute__((always_inline, hot))
static inline void cmp(struct cpu_state * restrict cpu, uint8_t value) {
uint8_t result = cpu->a - value;
cpu->c = (cpu->a >= value);
@@ -695,7 +696,7 @@ static void opcode_cmp_absx(struct nes_state * restrict state) {
// CPX
-
+__attribute__((always_inline, hot))
static inline void cpx(struct cpu_state * restrict cpu, uint8_t value) {
uint8_t result = cpu->x - value;
cpu->c = (cpu->x >= value);
@@ -731,7 +732,7 @@ static void opcode_cpx_abs(struct nes_state * restrict state) {
// CPY
-
+__attribute__((always_inline, hot))
static inline void cpy(struct cpu_state * restrict cpu, uint8_t value) {
uint8_t result = cpu->y - value;
cpu->c = (cpu->y >= value);
@@ -1752,7 +1753,7 @@ static void opcode_ror_absx(struct nes_state * restrict state) {
// SBC
-
+__attribute__((always_inline, hot))
static inline void sbc(struct cpu_state * restrict cpu, uint8_t value) {
#ifdef ENABLE_DECIMAL_MODE
if(cpu->d) {
@@ -2123,6 +2124,9 @@ static void opcode_sty_zpx(struct nes_state * restrict state) {
__attribute__((noinline))
static void init_opcode_lut(void) {
+ for(uint32_t i = 0; i < 256; ++i) {
+ opcode_lut[i] = opcode_nop; // make sure erroneous opcodes just do "NOP", this might change in the future!
+ }
opcode_lut[0x00] = opcode_brk;
opcode_lut[0x01] = opcode_ora_indx;
opcode_lut[0x05] = opcode_ora_zp;
diff --git a/memory.c b/memory.c
index 54962a5..e934136 100644
--- a/memory.c
+++ b/memory.c
@@ -5,6 +5,7 @@ __attribute__((hot))
static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) {
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
if(LIKELY(offset < 0x2000)) {
return state->ram[offset & 0x07ff];
@@ -18,6 +19,10 @@ static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) {
state->input_bit[index]++;
return value | 0x40; // Bit 6 open bus high, bit 7 low
+ // } else if(offset == 4015) {
+ // static uint32_t apuread = 0;
+ // // printf("%.5d apu\n", apuread++);
+
} else if(LIKELY(offset >= 0x6000)) {
return state->mapper.prg_read(state, offset);
@@ -29,6 +34,7 @@ __attribute__((hot))
static void memory_write(struct nes_state *restrict state, uint32_t offset, uint8_t value) {
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
if(LIKELY(offset < 0x2000)) {
state->ram[offset & 0x07ff] = value;
@@ -36,21 +42,34 @@ static void memory_write(struct nes_state *restrict state, uint32_t offset, uint
} else if(offset < 0x4000) {
ppu_write(state, offset, value);
- } else if(offset == 0x4014) {
- ppu_dma_4014(state, value);
-
- } else if(offset == 0x4016) {
- uint8_t prev = state->input_strobe;
- state->input_strobe = value & 1;
-
- if(prev == 1 && (value & 1) == 0) {
- // Latch current inputs
- state->input_latch[0] = state->input[0];
- state->input_latch[1] = state->input[1];
- state->input_bit[0] = 0;
- state->input_bit[1] = 0;
+ } else if(offset < 0x4018) {
+ // APU + joypad + DMA
+ if(offset == 0x4014) {
+ ppu_dma_4014(state, value);
+
+ // } else if(offset == 0x4015) { // DMC Enable (APU)
+ // state->apu.dmc_dma_enabled = (value & 0x10) ? 1 : 0;
+
+ } else if(offset == 0x4016) {
+ uint8_t prev = state->input_strobe;
+ state->input_strobe = value & 1;
+
+ if(prev == 1 && (value & 1) == 0) {
+ // Latch current inputs
+ state->input_latch[0] = state->input[0];
+ state->input_latch[1] = state->input[1];
+ state->input_bit[0] = 0;
+ state->input_bit[1] = 0;
+ }
+
+ // } else if(offset == 0x4017) { // Frame Counter (APU)
+ // state->apu.mode = (value >> 7) & 1;
+ // state->apu.irq_inhibit = (value >> 6) & 1;
+ // state->apu.frame_cycle = 0;
+ // if(state->apu.irq_inhibit) {
+ // state->apu.irq_pending = 0;
+ // }
}
-
} else if(offset >= 0x6000) {
state->mapper.prg_write(state, offset, value);
}
@@ -73,6 +92,7 @@ __attribute__((hot))
static uint8_t memory_read_dummy(struct nes_state *restrict state, uint32_t offset) {
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
if(UNLIKELY(offset >= 0x2000 && offset < 0x4000)) {
return ppu_read(state, offset);
diff --git a/mknes.c b/mknes.c
index 6ef4e02..a365ddb 100644
--- a/mknes.c
+++ b/mknes.c
@@ -90,7 +90,7 @@ static GLFWwindow *window;
#include "render.c"
static uint32_t frames; // debug information
-// #include "smb_tas.h" // REMOVE ME
+#include "smb_tas.h" // REMOVE ME
// NES core
#include "mapper.h"
@@ -224,6 +224,19 @@ int main(int argc, char **argv) {
uint32_t hi = nstate->mapper.prg_read(nstate, 0xfffd);
nstate->cpu.pc = (hi << 8) | lo;
+#if 0
+ for(uint32_t i = 0; i < 0x5000; ++ i) {
+ while(!nstate->ppu.frame_ready) {
+ // PROFILE_NAMED("nes emulator");
+ cpu_tick(nstate);
+ }
+ nstate->ppu.frame_ready = 0;
+ frames++;
+ }
+ return 0;
+#endif
+
+
struct timer_handle *timer = timer_new(FRAME_INTERVAL_NS);
if(!timer) {
fprintf(stderr, "Failed to create timer\n");
@@ -263,16 +276,6 @@ int main(int argc, char **argv) {
timer_start(timer);
-#if 1
- for(uint32_t i = 0; i < 0x5000; ++ i) {
- while(!nstate->ppu.frame_ready) {
- // PROFILE_NAMED("nes emulator");
- cpu_tick(nstate);
- }
- nstate->ppu.frame_ready = 0;
- frames++;
- }
-#else
while(!glfwWindowShouldClose(window)) {
timer_wait(timer);
glfwPollEvents();
@@ -305,7 +308,6 @@ int main(int argc, char **argv) {
render_frame();
glfwSwapBuffers(window);
}
-#endif
printf("total frames: %6.6d total cycles: %ld\n", frames, nstate->cycles);
glfwDestroyWindow(window);
} else {
diff --git a/mknes.h b/mknes.h
index f8e4be7..fb1228b 100644
--- a/mknes.h
+++ b/mknes.h
@@ -52,7 +52,6 @@ struct ppu_state {
uint8_t sprite_zero_hit_possible;
uint8_t sprite_count;
-
uint8_t palette[32];
// NOTE(peter): CACHELINE 2 start here!
@@ -68,6 +67,15 @@ struct ppu_state {
uint8_t frame_ready;
} __attribute__((packed, aligned(64)));
+struct apu_state {
+ uint32_t frame_cycle;
+ uint8_t mode;
+ uint8_t irq_inhibit;
+ uint8_t irq_pending;
+ uint8_t dmc_dma_enabled;
+ uint32_t dmc_sample_timer;
+};
+
struct cpu_state {
uint32_t pc; // Program Counter
uint8_t sp; // Stack Pointer
@@ -104,6 +112,7 @@ struct nes_state {
uint8_t input_latch[2]; // Latched inputs after strobe
uint8_t input_bit[2]; // Current bit position being shifted out
uint8_t input_strobe; // Control bit (0 or 1)
+ // struct apu_state apu;
struct ppu_state ppu;
struct mapper_entry mapper;
diff --git a/ppu.c b/ppu.c
index b34115c..cd549d1 100644
--- a/ppu.c
+++ b/ppu.c
@@ -397,8 +397,8 @@ static void ppu_tick(struct nes_state *state) {
}
if(UNLIKELY(scanline == 241) && dot == 1) {
- // static int32_t tas_frame = 0;
- // state->input[0] = tas_input[tas_frame++];
+ static int32_t tas_frame = 0;
+ state->input[0] = tas_input[tas_frame++];
ppu->reg_status |= 0x80;
if(ppu->reg_ctrl & 0x80) {
@@ -432,4 +432,3 @@ static void ppu_tick(struct nes_state *state) {
ppu->scanline = scanline;
}
}
-
diff --git a/ppu_registers.c b/ppu_registers.c
index e2e7940..1f738a1 100644
--- a/ppu_registers.c
+++ b/ppu_registers.c
@@ -122,6 +122,7 @@ static inline void ppu_dma_4014(struct nes_state *state, uint8_t page) {
for(uint8_t i = 0; i < idle_cycles; i++) {
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
}
for(uint32_t i = 0; i < 256; i++) {
@@ -129,10 +130,13 @@ static inline void ppu_dma_4014(struct nes_state *state, uint8_t page) {
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
uint8_t value = memory_read_dma(state, addr);
state->cycles++;
ppu_tick(state);
+ // apu_tick(state);
+
ppu_write(state, 4, value);
}
}