Add a safe memory read API

This commit is contained in:
Lior Halphon 2021-11-26 13:54:28 +02:00
parent 33090a5cc0
commit bdbe02b043
6 changed files with 19 additions and 4 deletions

View File

@ -1335,7 +1335,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
- (uint8_t) readMemory:(uint16_t)addr - (uint8_t) readMemory:(uint16_t)addr
{ {
while (!GB_is_inited(&gb)); while (!GB_is_inited(&gb));
return GB_read_memory(&gb, addr); return GB_safe_read_memory(&gb, addr);
} }
- (void) writeMemory:(uint16_t)addr value:(uint8_t)value - (void) writeMemory:(uint16_t)addr value:(uint8_t)value

View File

@ -1451,7 +1451,7 @@ static bool examine(GB_gameboy_t *gb, char *arguments, char *modifiers, const de
while (count) { while (count) {
GB_log(gb, "%02x:%04x: ", addr.bank, addr.value); GB_log(gb, "%02x:%04x: ", addr.bank, addr.value);
for (unsigned i = 0; i < 16 && count; i++) { for (unsigned i = 0; i < 16 && count; i++) {
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i)); GB_log(gb, "%02x ", GB_safe_read_memory(gb, addr.value + i));
count--; count--;
} }
addr.value += 16; addr.value += 16;
@ -1464,7 +1464,7 @@ static bool examine(GB_gameboy_t *gb, char *arguments, char *modifiers, const de
while (count) { while (count) {
GB_log(gb, "%04x: ", addr.value); GB_log(gb, "%04x: ", addr.value);
for (unsigned i = 0; i < 16 && count; i++) { for (unsigned i = 0; i < 16 && count; i++) {
GB_log(gb, "%02x ", GB_read_memory(gb, addr.value + i)); GB_log(gb, "%02x ", GB_safe_read_memory(gb, addr.value + i));
count--; count--;
} }
addr.value += 16; addr.value += 16;

View File

@ -742,6 +742,7 @@ struct GB_gameboy_internal_s {
/* Temporary state */ /* Temporary state */
bool wx_just_changed; bool wx_just_changed;
bool tile_sel_glitch; bool tile_sel_glitch;
bool disable_oam_corruption; // For safe memory reads
GB_gbs_header_t gbs_header; GB_gbs_header_t gbs_header;
); );

View File

@ -444,7 +444,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
} }
if (gb->oam_read_blocked) { if (gb->oam_read_blocked) {
if (!GB_is_cgb(gb)) { if (!GB_is_cgb(gb) && !gb->disable_oam_corruption) {
if (addr < 0xFEA0) { if (addr < 0xFEA0) {
uint16_t *oam = (uint16_t *)gb->oam; uint16_t *oam = (uint16_t *)gb->oam;
if (gb->accessed_oam_row == 0) { if (gb->accessed_oam_row == 0) {
@ -702,6 +702,18 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
return data; return data;
} }
uint8_t GB_safe_read_memory(GB_gameboy_t *gb, uint16_t addr)
{
gb->disable_oam_corruption = true;
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) {
data = gb->read_memory_callback(gb, addr, data);
}
return data;
}
static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{ {
switch (gb->cartridge_type->mbc_type) { switch (gb->cartridge_type->mbc_type) {

View File

@ -7,6 +7,7 @@ typedef uint8_t (*GB_read_memory_callback_t)(GB_gameboy_t *gb, uint16_t addr, ui
void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback); void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback);
uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr); 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
void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value); void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value);
#ifdef GB_INTERNAL #ifdef GB_INTERNAL
internal void GB_dma_run(GB_gameboy_t *gb); internal void GB_dma_run(GB_gameboy_t *gb);

View File

@ -2,6 +2,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "gb.h" #include "gb.h"
#define GB_read_memory GB_safe_read_memory
typedef void opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc); typedef void opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc);