SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 06b744259be749cb7a5d6611d76b04581541ea99 parent bdbe02b043d624dc3e0de9f8d0bb79b9b26a1c17 Author: Lior Halphon <LIJI32@gmail.com> Date: Fri, 26 Nov 2021 14:09:41 +0200 Add memory write callback, optimize memory access with likely/unlikely Diffstat:
| M | Core/cheats.c | 7 | ++++--- |
| M | Core/defs.h | 4 | ++-- |
| M | Core/gb.h | 1 | + |
| M | Core/memory.c | 22 | ++++++++++++++++------ |
| M | Core/memory.h | 2 | ++ |
5 files changed, 25 insertions(+), 11 deletions(-)
diff --git 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 @@ -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 @@ -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 @@ -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 @@ -4,7 +4,9 @@ #include <stdint.h> 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
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.