summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-12-05 09:34:21 +0100
committerPeter Fors <peter.fors@mindkiller.com>2025-12-05 09:34:21 +0100
commitb35551ddc948be413d179b798a0350eb2202bba8 (patch)
tree508499b149c4aa147311c0993c061939f5b90ab6
parentd1e416e8657521c77a929bab0dae819e51928088 (diff)
workingHEADmaster
-rwxr-xr-xbuild.sh8
-rw-r--r--linux_timer.c4
-rw-r--r--mknes.c33
-rw-r--r--mknes.h16
-rw-r--r--mknes_apu.c68
-rw-r--r--mknes_sdl.c12
6 files changed, 82 insertions, 59 deletions
diff --git a/build.sh b/build.sh
index d2cb7b2..057cd6a 100755
--- a/build.sh
+++ b/build.sh
@@ -3,11 +3,13 @@
# Use project-local GCC if available, otherwise system GCC
TOOLCHAIN_GCC="./toolchain/gcc-15.2.0/bin/gcc"
if [ -f "${TOOLCHAIN_GCC}" ]; then
- CC="${TOOLCHAIN_GCC}"
+ CC="${TOOLCHAIN_GCC}"
else
- CC=gcc
+ CC=gcc
fi
+CC=gcc
+
# Set the project name here
PROJECT_NAME="mknes" # Change this for each new project
@@ -38,7 +40,7 @@ INCLUDE_PATHS="-Ibase -I../mkfw "
# Linux-specific includes and libraries
LINUX_INCLUDE=" "
-LINUX_LIBS="-lXi -lX11 -lGL -lm -ldl -pthread -larchive -lSDL2"
+LINUX_LIBS="-lXi -lX11 -lGL -lm -ldl -pthread -larchive "
# Windows-specific includes and libraries
WINDOWS_INCLUDE=""
diff --git a/linux_timer.c b/linux_timer.c
index 9a9d296..6a86fdd 100644
--- a/linux_timer.c
+++ b/linux_timer.c
@@ -101,6 +101,10 @@ static void *timer_thread_func(void *arg) {
static struct timer_handle *timer_new(uint64_t interval_ns) {
struct timer_handle *t = calloc(1, sizeof(struct timer_handle));
+ if(!t) {
+ printf("ERROR: Could not allocate a timer!\n");
+ exit(1);
+ }
t->interval_ns = interval_ns;
clock_gettime(CLOCK_MONOTONIC_RAW, &t->next_deadline);
diff --git a/mknes.c b/mknes.c
index 8169fae..044a612 100644
--- a/mknes.c
+++ b/mknes.c
@@ -273,7 +273,17 @@ int main(int argc, char **argv) {
init_opcode_ud_lut();
// protect_opcode_lut();
- struct nes_state *nstate = aligned_alloc(4096, (sizeof(struct nes_state) + 4095) & ~4095);
+ // Add this line to /etc/sysctl.conf or create a new file /etc/sysctl.d/99-hugepages.conf:
+ // vm.nr_hugepages = 20
+ // Then apply it:
+ // sudo sysctl -p /etc/sysctl.d/99-hugepages.conf
+
+ size_t nstate_size = (sizeof(struct nes_state) + 4095) & ~4095; // Round up to page size
+ struct nes_state *nstate = mmap(0, nstate_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_LOCKED, -1, 0);
+ if (nstate == MAP_FAILED) {
+ perror("mmap nstate failed");
+ exit(1);
+ }
#ifdef BENCHMARK
// Run benchmark with configurable parameters
@@ -299,9 +309,9 @@ int main(int argc, char **argv) {
// ines2_load(nstate, "data/0000/10-Yard Fight (USA, Europe).nes");
// ines2_load(nstate, "data/0000/Balloon Fight (USA).nes");
// ines2_load(nstate, "data/0000/Excitebike (Japan, USA).nes");
- ines2_load(nstate, "data/0000/Ice Climber (USA, Europe, Korea).nes");
+ // ines2_load(nstate, "data/0000/Ice Climber (USA, Europe, Korea).nes");
// ines2_load(nstate, "data/0000/Kung Fu (Japan, USA).nes");
- // ines2_load(nstate, "data/0000/Super Mario Bros. (World) (HVC-SM).nes");
+ ines2_load(nstate, "data/0000/Super Mario Bros. (World) (HVC-SM).nes");
// ines2_load(nstate, "data/Super Mario Bros. (W) (V1.0) [!].nes");
// ines2_load(nstate, "data/Super Mario Bros. (JU) [!].nes");
// ines2_load(nstate, "data/0000/Urban Champion (World).nes");
@@ -342,8 +352,8 @@ int main(int argc, char **argv) {
// ines2_load(nstate, "data/2002/Best of the Best - Championship Karate (USA).zip");
// ines2_load(nstate, "data/0001/Kid Icarus (UE) (V1.1) [!].nes");
- ines2_load(nstate, "data/0001/Metroid (U) [!].nes");
- ines2_load(nstate, "data/0001/Legend of Zelda, The (U) (V1.1) [!].nes");
+ // ines2_load(nstate, "data/0001/Metroid (U) [!].nes");
+ // ines2_load(nstate, "data/0001/Legend of Zelda, The (U) (V1.1) [!].nes");
// ines2_load(nstate, "data/Blaster Master (USA).zip"); // mapper 1
// ines2_load(nstate, "AccuracyCoin.nes"); // mapper 1
@@ -408,6 +418,7 @@ int main(int argc, char **argv) {
if(window->keyboard_state[MKS_KEY_LEFT]) { input |= (1 << 6); }
if(window->keyboard_state[MKS_KEY_RIGHT]) { input |= (1 << 7); }
nstate->ppu.input[0] = input;
+ // nstate->ppu.input[0] = tas_input[tas_frame++];
// Run NES emulation for one frame
while(!nstate->ppu.frame_ready) {
@@ -422,14 +433,13 @@ int main(int argc, char **argv) {
// }
// nstate->ppu.open_bus = v;
// }
- // nstate->ppu.input[0] = tas_input[tas_frame++];
frames++;
// Dump state every frame starting from 2400
- if(frames >= 2400 && frames <= 3100) {
- dump_state(nstate);
- }
+ // if(frames >= 2400 && frames <= 3100) {
+ // dump_state(nstate);
+ // }
// Convert NES pixels to display buffer
uint32_t * restrict dst = display_buffer;
@@ -456,15 +466,14 @@ int main(int argc, char **argv) {
}
// printf("total frames: %6d total cycles: %12llu\n", frames, (unsigned long long)nstate->cpu.cycles);
- printf("state dumps created: %zu\n", state_dump_count);
+ // printf("state dumps created: %zu\n", state_dump_count);
if(state_dump_file) {
fclose(state_dump_file);
}
timer_destroy(timer);
- free(nstate);
- // free_nes_state(&nstate);
+ munmap(nstate, nstate_size);
timer_shutdown();
mkfw_cleanup(window);
diff --git a/mknes.h b/mknes.h
index 944f762..8972897 100644
--- a/mknes.h
+++ b/mknes.h
@@ -69,14 +69,14 @@ struct ppu_state {
uint8_t palette;
} __attribute__((packed)) sprites[8]; // 32 -> +40
- uint8_t input_strobe; // 76 - Control bit (0 or 1)
- uint8_t input[2]; // 73 - Controller 1 & 2
- uint8_t input_latch[2]; // 74 - Latched inputs after strobe
- uint8_t input_bit[2]; // 75 - Current bit position being shifted out
- uint8_t frame_ready; // 77
- uint8_t sprite_zero_in_range; // 78 - Boolean: is sprite 0 in range (will always be slot 0 if true)
-
- uint8_t palette[32]; // 79
+ uint8_t input_strobe; // 73 - Control bit (0 or 1)
+ uint8_t input[2]; // 74 - Controller 1 & 2
+ uint8_t input_latch[2]; // 76 - Latched inputs after strobe
+ uint8_t input_bit[2]; // 78 - Current bit position being shifted out
+ uint8_t frame_ready; // 80
+ uint8_t sprite_zero_in_range; // 81 - Boolean: is sprite 0 in range (will always be slot 0 if true)
+
+ uint8_t palette[32]; // 82
// NOTE(peter): CACHELINE 5
uint8_t oam[256] __attribute__((aligned(64)));
diff --git a/mknes_apu.c b/mknes_apu.c
index f1c27a8..8b9f45b 100644
--- a/mknes_apu.c
+++ b/mknes_apu.c
@@ -131,38 +131,38 @@ static inline void apu_tick(struct nes_state *state) {
}
}
- if(apu->dmc_dma_enabled && apu->dmc_bytes_remaining > 0) {
- apu->dmc_sample_timer++;
- if(apu->dmc_sample_timer >= dmc_rate_table[apu->dmc_freq_index]) {
- apu->dmc_sample_timer = 0;
-
- uint8_t val = memory_read(state, apu->dmc_current_addr);
- (void)val;
-
- apu->dmc_current_addr++;
- if(apu->dmc_current_addr == 0x0000) {
- apu->dmc_current_addr = 0x8000;
- }
-
- apu->dmc_bytes_remaining--;
-
- if(apu->dmc_bytes_remaining == 0) {
- if(apu->dmc_loop_flag) {
- apu->dmc_current_addr = 0xc000 + ((uint16_t)apu->dmc_sample_addr << 6);
- apu->dmc_bytes_remaining = ((uint16_t)apu->dmc_sample_len << 4);
- } else {
- if(apu->dmc_irq_enable) {
- apu->irq_pending = 1;
- state->cpu.irq_pending = 1;
- }
- apu->dmc_dma_enabled = 0;
- }
- }
-
- for(uint32_t i = 0; i < 4; i++) {
- state->cpu.cycles++;
- ppu_tick(state);
- }
- }
- }
+ // if(apu->dmc_dma_enabled && apu->dmc_bytes_remaining > 0) {
+ // apu->dmc_sample_timer++;
+ // if(apu->dmc_sample_timer >= dmc_rate_table[apu->dmc_freq_index]) {
+ // apu->dmc_sample_timer = 0;
+
+ // uint8_t val = memory_read(state, apu->dmc_current_addr);
+ // (void)val;
+
+ // apu->dmc_current_addr++;
+ // if(apu->dmc_current_addr == 0x0000) {
+ // apu->dmc_current_addr = 0x8000;
+ // }
+
+ // apu->dmc_bytes_remaining--;
+
+ // if(apu->dmc_bytes_remaining == 0) {
+ // if(apu->dmc_loop_flag) {
+ // apu->dmc_current_addr = 0xc000 + ((uint16_t)apu->dmc_sample_addr << 6);
+ // apu->dmc_bytes_remaining = ((uint16_t)apu->dmc_sample_len << 4);
+ // } else {
+ // if(apu->dmc_irq_enable) {
+ // apu->irq_pending = 1;
+ // state->cpu.irq_pending = 1;
+ // }
+ // apu->dmc_dma_enabled = 0;
+ // }
+ // }
+
+ // for(uint32_t i = 0; i < 4; i++) {
+ // state->cpu.cycles++;
+ // ppu_tick(state);
+ // }
+ // }
+ // }
}
diff --git a/mknes_sdl.c b/mknes_sdl.c
index 98776b5..f7d94c4 100644
--- a/mknes_sdl.c
+++ b/mknes_sdl.c
@@ -108,7 +108,15 @@ int main(int argc, char **argv) {
init_opcode_lut();
init_opcode_ud_lut();
- struct nes_state *nstate = aligned_alloc(4096, (sizeof(struct nes_state) + 4095) & ~4095);
+ size_t nstate_size = (sizeof(struct nes_state) + 4095) & ~4095; // Round up to page size
+ struct nes_state *nstate = mmap(NULL, nstate_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_LOCKED,
+ -1, 0);
+ if (nstate == MAP_FAILED) {
+ perror("mmap nstate failed");
+ exit(1);
+ }
#ifdef BENCHMARK
// Run benchmark with configurable parameters
@@ -354,7 +362,7 @@ int main(int argc, char **argv) {
for(int i = 0; i < 4; i++) {
free(debug_nt_buffer[i]);
}
- free(nstate);
+ munmap(nstate, nstate_size);
timer_shutdown();
for(int i = 0; i < 4; i++) {