From 058913f8a2d85a2573947d6a6ed0f3ab966cb06a Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 20 Feb 2018 19:57:33 +0200 Subject: [PATCH 1/6] Fixed libretro-Android build --- libretro/jni/Android.mk | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index 3401c10..4c4a7b6 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -23,14 +23,29 @@ ifeq ($(TARGET_ARCH),mips) LOCAL_CXXFLAGS += -DANDROID_MIPS endif -CORE_DIR := ../.. +CORE_DIR := $(realpath ../..) include ../Makefile.common LOCAL_SRC_FILES := $(SOURCES_CXX) $(SOURCES_C) -LOCAL_CFLAGS += -DINLINE=inline -DHAVE_STDINT_H -DHAVE_INTTYPES_H -D__LIBRETRO__ -DNDEBUG -D_USE_MATH_DEFINES -DGB_INTERNAL -std=c99 -I$(CORE_DIR) -DSAMEBOY_CORE_VERSION=\"$(VERSION)\" - +LOCAL_CFLAGS += -DINLINE=inline -DHAVE_STDINT_H -DHAVE_INTTYPES_H -D__LIBRETRO__ -DNDEBUG -D_USE_MATH_DEFINES -DGB_INTERNAL -std=c99 -I$(CORE_DIR) -DSAMEBOY_CORE_VERSION=\"$(VERSION)\" -DDISABLE_DEBUGGER -DDISABLE_TIMEKEEPING -Wno-multichar LOCAL_C_INCLUDES = $(INCFLAGS) include $(BUILD_SHARED_LIBRARY) +$(CORE_DIR)/libretro/%_boot.c: $(CORE_DIR)/build/bin/BootROMs/%_boot.bin + echo "/* AUTO-GENERATED */" > $@ + echo "const unsigned char $(notdir $(@:%.c=%))[] = {" >> $@ +ifneq ($(findstring Haiku,$(shell uname -s)),) + # turns out od is posix, hexdump is not hence is less portable + # this is still rather ugly and could be done better I guess + od -A none -t x1 -v $< | sed -e 's/^\ /0x/' -e 's/\ /,\ 0x/g' -e 's/$$/,/g' | tr '\n' ' ' >> $@ +else + hexdump -v -e '/1 "0x%02x, "' $< >> $@ +endif + echo "};" >> $@ + echo "const unsigned $(notdir $(@:%.c=%))_length = sizeof($(notdir $(@:%.c=%)));" >> $@ + +$(CORE_DIR)/build/bin/BootROMs/%_boot.bin: + $(MAKE) -C .. $(patsubst $(CORE_DIR)/%,%,$@) + From 90a943d05a007155d67f6528fd260718e0e7582d Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 25 Feb 2018 22:32:41 +0200 Subject: [PATCH 2/6] Emulate an HDMA quirk required to properly emulate Aevilia --- Core/display.c | 2 ++ Core/gb.h | 3 ++- Core/memory.c | 6 +++++- Core/z80_cpu.c | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Core/display.c b/Core/display.c index 41f85bf..dda9fab 100755 --- a/Core/display.c +++ b/Core/display.c @@ -527,6 +527,8 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->vram_read_blocked = false; gb->oam_write_blocked = false; gb->vram_write_blocked = false; + } + else if (position_in_line == MODE2_LENGTH + MODE3_LENGTH + stat_delay + scx_delay + 16) { if (gb->hdma_on_hblank) { gb->hdma_on = true; gb->hdma_cycles = 0; diff --git a/Core/gb.h b/Core/gb.h index 3dea996..c93aa3d 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -254,7 +254,7 @@ struct GB_gameboy_internal_s { bool halted; bool stopped; bool boot_rom_finished; - bool ime_toggle; /* ei (and di in CGB) have delayed effects.*/ + bool ime_toggle; /* ei has delayed a effect.*/ bool halt_bug; /* Misc state */ @@ -275,6 +275,7 @@ struct GB_gameboy_internal_s { uint16_t dma_current_src; int16_t dma_cycles; bool is_dma_restarting; + uint8_t last_opcode_read; /* Required to emulte HDMA reads from Exxx */ ); /* MBC */ diff --git a/Core/memory.c b/Core/memory.c index ef2f007..dca92aa 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -111,6 +111,9 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) { if (addr < 0xFE00) { + if (gb->hdma_on) { + return gb->last_opcode_read; + } return gb->ram[addr & 0x0FFF]; } @@ -122,7 +125,8 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) } if (addr < 0xFF00) { - /* Unusable. CGB results are verified, but DMG results were tested on a SGB2 */ + /* Unusable. CGB results are verified, but DMG results were tested on a SGB2 */ + /* Also, writes to this area are not emulated */ if ((gb->io_registers[GB_IO_STAT] & 0x3) >= 2) { /* Seems to be disabled in Modes 2 and 3 */ return 0xFF; } diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 16dbd08..4794df5 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1392,12 +1392,12 @@ void GB_cpu_run(GB_gameboy_t *gb) GB_debugger_call_hook(gb, call_addr); } else if(!gb->halted && !gb->stopped) { - uint8_t opcode = GB_read_memory(gb, gb->pc++); + gb->last_opcode_read = GB_read_memory(gb, gb->pc++); if (gb->halt_bug) { gb->pc--; gb->halt_bug = false; } - opcodes[opcode](gb, opcode); + opcodes[gb->last_opcode_read](gb, gb->last_opcode_read); } else { GB_advance_cycles(gb, 4); From b02e40d5a2865a97fa4e65c940660e74baa44fdd Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 25 Feb 2018 23:23:55 +0200 Subject: [PATCH 3/6] Refinement to that last fix --- Core/memory.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/memory.c b/Core/memory.c index dca92aa..2bd8215 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -110,10 +110,11 @@ static uint8_t read_banked_ram(GB_gameboy_t *gb, uint16_t addr) static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) { + if (gb->hdma_on) { + return gb->last_opcode_read; + } + if (addr < 0xFE00) { - if (gb->hdma_on) { - return gb->last_opcode_read; - } return gb->ram[addr & 0x0FFF]; } From 980acc3fb877a8e5d13d18c85d7a844f470ec45b Mon Sep 17 00:00:00 2001 From: Panda Habert Date: Mon, 26 Feb 2018 02:27:50 +0100 Subject: [PATCH 4/6] Make the last option's purpose more explicit I mistook it several times for the option to exit the menu :/ --- SDL/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDL/gui.c b/SDL/gui.c index 03c9513..c152e59 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -239,7 +239,7 @@ static const struct menu_item paused_menu[] = { {"Keyboard", enter_controls_menu}, {"Joypad", enter_joypad_menu}, {"Help", item_help}, - {"Exit", item_exit}, + {"Quit SameBoy", item_exit}, {NULL,} }; From fb03479a1f0598c2783b3978be09a476c810cf9d Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 28 Feb 2018 19:39:22 +0200 Subject: [PATCH 5/6] Added 16-bit dereferencing operator (`{address}`) to the debugger. Closes #38 --- Core/debugger.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/Core/debugger.c b/Core/debugger.c index 7fc7b2a..9fe6854 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -12,6 +12,7 @@ typedef struct { typedef struct { enum { LVALUE_MEMORY, + LVALUE_MEMORY16, LVALUE_REG16, LVALUE_REG_H, LVALUE_REG_L, @@ -209,6 +210,19 @@ static value_t read_lvalue(GB_gameboy_t *gb, lvalue_t lvalue) return r; } return VALUE_16(GB_read_memory(gb, lvalue.memory_address.value)); + + case LVALUE_MEMORY16: + 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) | + (GB_read_memory(gb, lvalue.memory_address.value + 1) * 0x100)); + case LVALUE_REG16: return VALUE_16(*lvalue.register_address); @@ -235,6 +249,19 @@ static void write_lvalue(GB_gameboy_t *gb, lvalue_t lvalue, uint16_t value) } GB_write_memory(gb, lvalue.memory_address.value, value); return; + + case LVALUE_MEMORY16: + 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); + GB_write_memory(gb, lvalue.memory_address.value + 1, value >> 8); + return; case LVALUE_REG16: *lvalue.register_address = value; @@ -382,6 +409,22 @@ static lvalue_t debugger_evaluate_lvalue(GB_gameboy_t *gb, const char *string, return (lvalue_t){LVALUE_MEMORY, .memory_address = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value)}; } } + else if (string[0] == '{' && string[length - 1] == '}') { + // Attempt to strip curly parentheses (memory dereference) + signed int depth = 0; + for (int i = 0; i < length; i++) { + if (string[i] == '{') depth++; + if (depth == 0) { + // First and last are not matching + depth = 1; + break; + } + if (string[i] == '}') depth--; + } + if (depth == 0) { + return (lvalue_t){LVALUE_MEMORY16, .memory_address = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value)}; + } + } // Registers if (string[0] != '$' && (string[0] < '0' || string[0] > '9')) { @@ -486,7 +529,33 @@ value_t debugger_evaluate(GB_gameboy_t *gb, const char *string, } goto exit; } - + } + else if (string[0] == '{' && string[length - 1] == '}') { + // Attempt to strip curly parentheses (memory dereference) + signed int depth = 0; + for (int i = 0; i < length; i++) { + if (string[i] == '{') depth++; + if (depth == 0) { + // First and last are not matching + depth = 1; + break; + } + if (string[i] == '}') depth--; + } + + if (depth == 0) { + value_t addr = debugger_evaluate(gb, string + 1, length - 2, error, watchpoint_address, watchpoint_new_value); + banking_state_t state; + if (addr.bank) { + save_banking_state(gb, &state); + switch_banking_state(gb, addr.bank); + } + ret = VALUE_16(GB_read_memory(gb, addr.value) | (GB_read_memory(gb, addr.value + 1) * 0x100)); + if (addr.bank) { + restore_banking_state(gb, &state); + } + goto exit; + } } // Search for lowest priority operator signed int depth = 0; From 94c6dbd2811031d2dce02b7fd9784d80160deeb9 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 1 Mar 2018 21:12:37 +0200 Subject: [PATCH 6/6] =?UTF-8?q?Fixed=20=E2=80=98call=E2=80=99=20instructio?= =?UTF-8?q?n=20not=20being=20properly=20symbolicated.=20Closes=20#37?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/z80_disassembler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/z80_disassembler.c b/Core/z80_disassembler.c index 08fb62f..d45cbe7 100644 --- a/Core/z80_disassembler.c +++ b/Core/z80_disassembler.c @@ -503,7 +503,7 @@ static void call_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc) { (*pc)++; uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8); - const char *symbol = GB_debugger_name_for_address(gb, 0xff00 + addr); + const char *symbol = GB_debugger_name_for_address(gb, addr); if (symbol) { GB_log(gb, "CALL %s ; =$%04x\n", symbol, addr); }