Add memory write callback, optimize memory access with likely/unlikely

This commit is contained in:
Lior Halphon 2021-11-26 14:09:41 +02:00
parent bdbe02b043
commit 06b744259b
5 changed files with 25 additions and 11 deletions

View File

@ -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)) {

View File

@ -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")))

View File

@ -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;

View File

@ -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;
}

View File

@ -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