Reading and writing absolute addresses in the expression evaluator.
This commit is contained in:
parent
e20e81befd
commit
eaca0634aa
121
Core/debugger.c
121
Core/debugger.c
@ -6,6 +6,11 @@
|
|||||||
#include "z80_cpu.h"
|
#include "z80_cpu.h"
|
||||||
#include "gb.h"
|
#include "gb.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool has_bank;
|
||||||
|
uint16_t bank:9;
|
||||||
|
uint16_t value;
|
||||||
|
} value_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
@ -16,16 +21,10 @@ typedef struct {
|
|||||||
} kind;
|
} kind;
|
||||||
union {
|
union {
|
||||||
uint16_t *register_address;
|
uint16_t *register_address;
|
||||||
uint16_t memory_address;
|
value_t memory_address;
|
||||||
};
|
};
|
||||||
} lvalue_t;
|
} lvalue_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool has_bank;
|
|
||||||
uint16_t bank:9;
|
|
||||||
uint16_t value;
|
|
||||||
} value_t;
|
|
||||||
|
|
||||||
#define VALUE_16(x) ((value_t){false, 0, (x)})
|
#define VALUE_16(x) ((value_t){false, 0, (x)})
|
||||||
|
|
||||||
struct GB_breakpoint_s {
|
struct GB_breakpoint_s {
|
||||||
@ -79,6 +78,48 @@ static uint16_t bank_for_addr(GB_gameboy_t *gb, uint16_t addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t rom0_bank;
|
||||||
|
uint16_t rom_bank;
|
||||||
|
uint8_t mbc_ram_bank;
|
||||||
|
bool mbc_ram_enable;
|
||||||
|
uint8_t ram_bank;
|
||||||
|
uint8_t vram_bank;
|
||||||
|
} banking_state_t;
|
||||||
|
|
||||||
|
static inline void save_banking_state(GB_gameboy_t *gb, banking_state_t *state)
|
||||||
|
{
|
||||||
|
state->rom0_bank = gb->mbc_rom0_bank;
|
||||||
|
state->rom_bank = gb->mbc_rom_bank;
|
||||||
|
state->mbc_ram_bank = gb->mbc_ram_bank;
|
||||||
|
state->mbc_ram_enable = gb->mbc_ram_enable;
|
||||||
|
state->ram_bank = gb->cgb_ram_bank;
|
||||||
|
state->vram_bank = gb->cgb_vram_bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void restore_banking_state(GB_gameboy_t *gb, banking_state_t *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
gb->mbc_rom0_bank = state->rom0_bank;
|
||||||
|
gb->mbc_rom_bank = state->rom_bank;
|
||||||
|
gb->mbc_ram_bank = state->mbc_ram_bank;
|
||||||
|
gb->mbc_ram_enable = state->mbc_ram_enable;
|
||||||
|
gb->cgb_ram_bank = state->ram_bank;
|
||||||
|
gb->cgb_vram_bank = state->vram_bank;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void switch_banking_state(GB_gameboy_t *gb, uint16_t bank)
|
||||||
|
{
|
||||||
|
gb->mbc_rom0_bank = bank;
|
||||||
|
gb->mbc_rom_bank = bank;
|
||||||
|
gb->mbc_ram_bank = bank;
|
||||||
|
gb->mbc_ram_enable = true;
|
||||||
|
if (gb->is_cgb) {
|
||||||
|
gb->cgb_ram_bank = bank & 7;
|
||||||
|
gb->cgb_vram_bank = bank & 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const char *value_to_string(GB_gameboy_t *gb, uint16_t value, bool prefer_name)
|
static const char *value_to_string(GB_gameboy_t *gb, uint16_t value, bool prefer_name)
|
||||||
{
|
{
|
||||||
static __thread char output[256];
|
static __thread char output[256];
|
||||||
@ -162,7 +203,15 @@ static value_t read_lvalue(GB_gameboy_t *gb, lvalue_t lvalue)
|
|||||||
/* Not used until we add support for operators like += */
|
/* Not used until we add support for operators like += */
|
||||||
switch (lvalue.kind) {
|
switch (lvalue.kind) {
|
||||||
case LVALUE_MEMORY:
|
case LVALUE_MEMORY:
|
||||||
return VALUE_16(GB_read_memory(gb, lvalue.memory_address));
|
if (lvalue.memory_address.has_bank) {
|
||||||
|
banking_state_t state;
|
||||||
|
save_banking_state(gb, &state);
|
||||||
|
switch_banking_state(gb, lvalue.memory_address.bank);
|
||||||
|
value_t r = VALUE_16(GB_read_memory(gb, lvalue.memory_address.value));
|
||||||
|
restore_banking_state(gb, &state);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return VALUE_16(GB_read_memory(gb, lvalue.memory_address.value));
|
||||||
|
|
||||||
case LVALUE_REG16:
|
case LVALUE_REG16:
|
||||||
return VALUE_16(*lvalue.register_address);
|
return VALUE_16(*lvalue.register_address);
|
||||||
@ -179,7 +228,15 @@ static void write_lvalue(GB_gameboy_t *gb, lvalue_t lvalue, uint16_t value)
|
|||||||
{
|
{
|
||||||
switch (lvalue.kind) {
|
switch (lvalue.kind) {
|
||||||
case LVALUE_MEMORY:
|
case LVALUE_MEMORY:
|
||||||
GB_write_memory(gb, lvalue.memory_address, value);
|
if (lvalue.memory_address.has_bank) {
|
||||||
|
banking_state_t state;
|
||||||
|
save_banking_state(gb, &state);
|
||||||
|
switch_banking_state(gb, lvalue.memory_address.bank);
|
||||||
|
GB_write_memory(gb, lvalue.memory_address.value, value);
|
||||||
|
restore_banking_state(gb, &state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GB_write_memory(gb, lvalue.memory_address.value, value);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case LVALUE_REG16:
|
case LVALUE_REG16:
|
||||||
@ -325,8 +382,7 @@ static lvalue_t debugger_evaluate_lvalue(GB_gameboy_t *gb, const char *string,
|
|||||||
if (string[i] == ']') depth--;
|
if (string[i] == ']') depth--;
|
||||||
}
|
}
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
/* Todo: Warn the user when dereferencing a specific bank, but it's not mapped */
|
return (lvalue_t){LVALUE_MEMORY, .memory_address = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value)};
|
||||||
return (lvalue_t){LVALUE_MEMORY, .memory_address = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value).value};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,13 +466,17 @@ value_t debugger_evaluate(GB_gameboy_t *gb, const char *string,
|
|||||||
}
|
}
|
||||||
if (string[i] == ']') depth--;
|
if (string[i] == ']') depth--;
|
||||||
}
|
}
|
||||||
/* Todo: Warn the user when dereferencing a specific bank, but it's not mapped */
|
|
||||||
if (depth == 0)
|
if (depth == 0) {
|
||||||
return VALUE_16(
|
value_t addr = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value);
|
||||||
GB_read_memory(gb,
|
banking_state_t state;
|
||||||
debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value).value
|
save_banking_state(gb, &state);
|
||||||
)
|
switch_banking_state(gb, addr.bank);
|
||||||
);
|
value_t r = VALUE_16(GB_read_memory(gb, addr.value));
|
||||||
|
restore_banking_state(gb, &state);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// Search for lowest priority operator
|
// Search for lowest priority operator
|
||||||
signed int depth = 0;
|
signed int depth = 0;
|
||||||
@ -1019,21 +1079,9 @@ static bool examine(GB_gameboy_t *gb, char *arguments)
|
|||||||
value_t addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
value_t addr = debugger_evaluate(gb, arguments, (unsigned int)strlen(arguments), &error, NULL, NULL);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (addr.has_bank) {
|
if (addr.has_bank) {
|
||||||
uint16_t old_rom0_bank = gb->mbc_rom0_bank;
|
banking_state_t old_state;
|
||||||
uint16_t old_rom_bank = gb->mbc_rom_bank;
|
save_banking_state(gb, &old_state);
|
||||||
uint8_t old_mbc_ram_bank = gb->mbc_ram_bank;
|
switch_banking_state(gb, addr.bank);
|
||||||
bool old_mbc_ram_enable = gb->mbc_ram_enable;
|
|
||||||
uint8_t old_ram_bank = gb->cgb_ram_bank;
|
|
||||||
uint8_t old_vram_bank = gb->cgb_vram_bank;
|
|
||||||
|
|
||||||
gb->mbc_rom0_bank = addr.bank;
|
|
||||||
gb->mbc_rom_bank = addr.bank;
|
|
||||||
gb->mbc_ram_bank = addr.bank;
|
|
||||||
gb->mbc_ram_enable = true;
|
|
||||||
if (gb->is_cgb) {
|
|
||||||
gb->cgb_ram_bank = addr.bank & 7;
|
|
||||||
gb->cgb_vram_bank = addr.bank & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GB_log(gb, "%02x:%04x: ", addr.bank, addr.value);
|
GB_log(gb, "%02x:%04x: ", addr.bank, addr.value);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
@ -1041,12 +1089,7 @@ static bool examine(GB_gameboy_t *gb, char *arguments)
|
|||||||
}
|
}
|
||||||
GB_log(gb, "\n");
|
GB_log(gb, "\n");
|
||||||
|
|
||||||
gb->mbc_rom0_bank = old_rom0_bank;
|
restore_banking_state(gb, &old_state);
|
||||||
gb->mbc_rom_bank = old_rom_bank;
|
|
||||||
gb->mbc_ram_bank = old_mbc_ram_bank;
|
|
||||||
gb->mbc_ram_enable = old_mbc_ram_enable;
|
|
||||||
gb->cgb_ram_bank = old_ram_bank;
|
|
||||||
gb->cgb_vram_bank = old_vram_bank;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GB_log(gb, "%04x: ", addr.value);
|
GB_log(gb, "%04x: ", addr.value);
|
||||||
|
Loading…
Reference in New Issue
Block a user