From 06b744259be749cb7a5d6611d76b04581541ea99 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 26 Nov 2021 14:09:41 +0200 Subject: [PATCH] Add memory write callback, optimize memory access with likely/unlikely --- Core/cheats.c | 7 ++++--- Core/defs.h | 4 ++-- Core/gb.h | 1 + Core/memory.c | 22 ++++++++++++++++------ Core/memory.h | 2 ++ 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Core/cheats.c b/Core/cheats.c index 1263183..8b5a7a0 100644 --- a/Core/cheats.c +++ b/Core/cheats.c @@ -32,10 +32,11 @@ static uint16_t bank_for_addr(GB_gameboy_t *gb, uint16_t addr) void GB_apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value) { - if (!gb->cheat_enabled) return; - if (!gb->boot_rom_finished) return; + if (likely(!gb->cheat_enabled)) return; + if (likely(gb->cheat_count == 0)) return; // Optimization + if (unlikely(!gb->boot_rom_finished)) return; const GB_cheat_hash_t *hash = gb->cheat_hash[hash_addr(address)]; - if (hash) { + if (unlikely(hash)) { for (unsigned i = 0; i < hash->size; i++) { GB_cheat_t *cheat = hash->cheats[i]; if (cheat->address == address && cheat->enabled && (!cheat->use_old_value || cheat->old_value == *value)) { diff --git a/Core/defs.h b/Core/defs.h index b4f13f5..0517b22 100644 --- a/Core/defs.h +++ b/Core/defs.h @@ -4,8 +4,8 @@ #ifdef GB_INTERNAL // "Keyword" definitions -#define likely(x) __builtin_expect((x), 1) -#define unlikely(x) __builtin_expect((x), 0) +#define likely(x) __builtin_expect((bool)(x), 1) +#define unlikely(x) __builtin_expect((bool)(x), 0) #define internal __attribute__((visibility("internal"))) diff --git a/Core/gb.h b/Core/gb.h index d7d988d..cc235e8 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -658,6 +658,7 @@ struct GB_gameboy_internal_s { GB_icd_vreset_callback_t icd_hreset_callback; GB_icd_vreset_callback_t icd_vreset_callback; GB_read_memory_callback_t read_memory_callback; + GB_write_memory_callback_t write_memory_callback; GB_boot_rom_load_callback_t boot_rom_load_callback; GB_print_image_callback_t printer_callback; GB_workboy_set_time_callback workboy_set_time_callback; diff --git a/Core/memory.c b/Core/memory.c index f428f05..bedf339 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -688,15 +688,15 @@ void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t cal uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr) { - if (gb->n_watchpoints) { + if (unlikely(gb->n_watchpoints)) { GB_debugger_test_read_watchpoint(gb, addr); } - if (is_addr_in_dma_use(gb, addr)) { + if (unlikely(is_addr_in_dma_use(gb, addr))) { addr = gb->dma_current_src; } uint8_t data = read_map[addr >> 12](gb, addr); GB_apply_cheat(gb, addr, &data); - if (gb->read_memory_callback) { + if (unlikely(gb->read_memory_callback)) { data = gb->read_memory_callback(gb, addr, data); } return data; @@ -708,7 +708,7 @@ uint8_t GB_safe_read_memory(GB_gameboy_t *gb, uint16_t addr) uint8_t data = read_map[addr >> 12](gb, addr); gb->disable_oam_corruption = false; GB_apply_cheat(gb, addr, &data); - if (gb->read_memory_callback) { + if (unlikely(gb->read_memory_callback)) { data = gb->read_memory_callback(gb, addr, data); } return data; @@ -1563,12 +1563,22 @@ static write_function_t *const write_map[] = write_ram, write_high_memory, /* EXXX FXXX */ }; +void GB_set_write_memory_callback(GB_gameboy_t *gb, GB_write_memory_callback_t callback) +{ + gb->write_memory_callback = callback; +} + void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) { - if (gb->n_watchpoints) { + if (unlikely(gb->n_watchpoints)) { GB_debugger_test_write_watchpoint(gb, addr, value); } - if (is_addr_in_dma_use(gb, addr)) { + + if (unlikely(gb->write_memory_callback)) { + if (!gb->write_memory_callback(gb, addr, value)) return; + } + + if (unlikely(is_addr_in_dma_use(gb, addr))) { /* Todo: What should happen? Will this affect DMA? Will data be written? What and where? */ return; } diff --git a/Core/memory.h b/Core/memory.h index f351339..adfdcaa 100644 --- a/Core/memory.h +++ b/Core/memory.h @@ -4,7 +4,9 @@ #include typedef uint8_t (*GB_read_memory_callback_t)(GB_gameboy_t *gb, uint16_t addr, uint8_t data); +typedef bool (*GB_write_memory_callback_t)(GB_gameboy_t *gb, uint16_t addr, uint8_t data); // Return false to prevent the write void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback); +void GB_set_write_memory_callback(GB_gameboy_t *gb, GB_write_memory_callback_t callback); uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr); uint8_t GB_safe_read_memory(GB_gameboy_t *gb, uint16_t addr); // Without side effects