Allow disabling SameBoy features when compiling as a library. Probably introduces some speed improvements to the Libretro core, as well as bsnes and BizHawk

This commit is contained in:
Lior Halphon 2023-06-03 22:37:42 +03:00
parent d62132be38
commit bed26daf73
17 changed files with 118 additions and 43 deletions

View File

@ -3,6 +3,7 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include "gb.h"
static const uint8_t duties[] = {

View File

@ -1,5 +1,6 @@
#ifndef cheats_h
#define cheats_h
#ifndef GB_DISABLE_CHEATS
#include "defs.h"
#define GB_CHEAT_ANY_BANK 0xFFFF
@ -17,12 +18,8 @@ void GB_load_cheats(GB_gameboy_t *gb, const char *path);
int GB_save_cheats(GB_gameboy_t *gb, const char *path);
#ifdef GB_INTERNAL
#ifdef GB_DISABLE_CHEATS
#define GB_apply_cheat(...)
#else
internal void GB_apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value);
#endif
#endif
typedef struct {
size_t size;
@ -38,5 +35,9 @@ struct GB_cheat_s {
bool enabled;
char description[128];
};
#else
#ifdef GB_INTERNAL
#define GB_apply_cheat(...)
#endif // GB_INTERNAL
#endif // GB_DISABLE_CHEATS
#endif

View File

@ -1,5 +1,6 @@
#ifndef debugger_h
#define debugger_h
#ifndef GB_DISABLE_DEBUGGER
#include <stdbool.h>
#include <stdint.h>
#include "defs.h"
@ -7,17 +8,20 @@
void GB_debugger_break(GB_gameboy_t *gb);
#ifdef GB_INTERNAL
#ifdef GB_DISABLE_DEBUGGER
#define GB_debugger_run(gb) (void)0
#define GB_debugger_handle_async_commands(gb) (void)0
#define GB_debugger_ret_hook(gb) (void)0
#define GB_debugger_call_hook(gb, addr) (void)addr
#define GB_debugger_test_write_watchpoint(gb, addr, value) ((void)addr, (void)value)
#define GB_debugger_test_read_watchpoint(gb, addr) (void)addr
#define GB_debugger_add_symbol(gb, bank, address, symbol) ((void)bank, (void)address, (void)symbol)
#define GB_debugger_break(gb) (void)0
bool /* Returns true if debugger waits for more commands. Not relevant for non-GB_INTERNAL */
#else
void
#endif
GB_debugger_execute_command(GB_gameboy_t *gb, char *input); /* Destroys input. */
char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */
void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path);
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr);
bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */
bool GB_debugger_is_stopped(GB_gameboy_t *gb);
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
void GB_debugger_clear_symbols(GB_gameboy_t *gb);
#ifdef GB_INTERNAL
internal void GB_debugger_run(GB_gameboy_t *gb);
internal void GB_debugger_handle_async_commands(GB_gameboy_t *gb);
internal void GB_debugger_call_hook(GB_gameboy_t *gb, uint16_t call_addr);
@ -26,21 +30,20 @@ internal void GB_debugger_test_write_watchpoint(GB_gameboy_t *gb, uint16_t addr,
internal void GB_debugger_test_read_watchpoint(GB_gameboy_t *gb, uint16_t addr);
internal const GB_bank_symbol_t *GB_debugger_find_symbol(GB_gameboy_t *gb, uint16_t addr);
internal void GB_debugger_add_symbol(GB_gameboy_t *gb, uint16_t bank, uint16_t address, const char *symbol);
#endif /* GB_DISABLE_DEBUGGER */
#endif
#else // GB_DISABLE_DEBUGGER
#ifdef GB_INTERNAL
bool /* Returns true if debugger waits for more commands. Not relevant for non-GB_INTERNAL */
#else
void
#endif
GB_debugger_execute_command(GB_gameboy_t *gb, char *input); /* Destroys input. */
char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */
#define GB_debugger_run(gb) (void)0
#define GB_debugger_handle_async_commands(gb) (void)0
#define GB_debugger_ret_hook(gb) (void)0
#define GB_debugger_call_hook(gb, addr) (void)addr
#define GB_debugger_test_write_watchpoint(gb, addr, value) ((void)addr, (void)value)
#define GB_debugger_test_read_watchpoint(gb, addr) (void)addr
#define GB_debugger_add_symbol(gb, bank, address, symbol) ((void)bank, (void)address, (void)symbol)
#define GB_debugger_break(gb) (void)0
#endif // GB_INTERNAL
#endif // GB_DISABLE_DEBUGGER
void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path);
const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr);
bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result, uint16_t *result_bank); /* result_bank is -1 if unused. */
bool GB_debugger_is_stopped(GB_gameboy_t *gb);
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled);
void GB_debugger_clear_symbols(GB_gameboy_t *gb);
#endif

View File

@ -211,11 +211,19 @@ void GB_free(GB_gameboy_t *gb)
if (gb->rom) {
free(gb->rom);
}
if (gb->sgb) {
free(gb->sgb);
}
#ifndef GB_DISABLE_DEBUGGER
GB_debugger_clear_symbols(gb);
#endif
GB_rewind_reset(gb);
#ifndef GB_DISABLE_CHEATS
if (gb->breakpoints) {
free(gb->breakpoints);
}
if (gb->sgb) {
free(gb->sgb);
if (gb->watchpoints) {
free(gb->watchpoints);
}
if (gb->nontrivial_jump_state) {
free(gb->nontrivial_jump_state);
@ -223,11 +231,6 @@ void GB_free(GB_gameboy_t *gb)
if (gb->undo_state) {
free(gb->undo_state);
}
#ifndef GB_DISABLE_DEBUGGER
GB_debugger_clear_symbols(gb);
#endif
GB_rewind_reset(gb);
#ifndef GB_DISABLE_CHEATS
while (gb->cheats) {
GB_remove_cheat(gb, gb->cheats[0]);
}
@ -1762,10 +1765,12 @@ static void GB_reset_internal(GB_gameboy_t *gb, bool quick)
GB_set_internal_div_counter(gb, 8);
#ifndef GB_DISABLE_DEBUGGER
if (gb->nontrivial_jump_state) {
free(gb->nontrivial_jump_state);
gb->nontrivial_jump_state = NULL;
}
#endif
if (!quick) {
reset_ram(gb);
@ -1812,10 +1817,12 @@ void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
gb->ram = realloc(gb->ram, gb->ram_size = 0x2000);
gb->vram = realloc(gb->vram, gb->vram_size = 0x2000);
}
#ifndef GB_DISABLE_DEBUGGER
if (gb->undo_state) {
free(gb->undo_state);
gb->undo_state = NULL;
}
#endif
GB_rewind_reset(gb);
GB_reset(gb);
load_default_border(gb);

View File

@ -724,6 +724,7 @@ struct GB_gameboy_internal_s {
GB_lcd_status_callback_t lcd_status_callback;
GB_debugger_reload_callback_t debugger_reload_callback;
#ifndef GB_DISABLE_DEBUGGER
/*** Debugger ***/
volatile bool debug_stopped, debug_disable;
bool debug_fin_command, debug_next_command;
@ -765,7 +766,9 @@ struct GB_gameboy_internal_s {
/* Undo */
uint8_t *undo_state;
const char *undo_label;
#endif
#ifndef GB_DISABLE_REWIND
/* Rewind */
size_t rewind_buffer_length;
size_t rewind_state_size;
@ -775,6 +778,7 @@ struct GB_gameboy_internal_s {
unsigned pos;
} *rewind_sequences; // lasts about 4 seconds
size_t rewind_pos;
#endif
/* SGB - saved and allocated optionally */
GB_sgb_t *sgb;
@ -783,11 +787,13 @@ struct GB_gameboy_internal_s {
double sgb_intro_sweep_phase;
double sgb_intro_sweep_previous_sample;
/* Cheats */
#ifndef GB_DISABLE_CHEATS
/* Cheats */
bool cheat_enabled;
size_t cheat_count;
GB_cheat_t **cheats;
GB_cheat_hash_t *cheat_hash[256];
#endif
/* Misc */
bool turbo;

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "gb.h"
typedef uint8_t read_function_t(GB_gameboy_t *gb, uint16_t addr);
@ -758,9 +759,11 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
{
GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
#ifndef GB_DISABLE_DEBUGGER
if (unlikely(gb->n_watchpoints)) {
GB_debugger_test_read_watchpoint(gb, addr);
}
#endif
if (unlikely(is_addr_in_dma_use(gb, addr))) {
if (GB_is_cgb(gb) && bus_for_addr(gb, addr) == GB_BUS_MAIN && gb->dma_current_src >= 0xE000) {
/* This is cart specific! Everdrive 7X on a CGB-A or 0 behaves differently. */
@ -1760,10 +1763,11 @@ void GB_set_write_memory_callback(GB_gameboy_t *gb, GB_write_memory_callback_t c
void GB_write_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{
GB_ASSERT_NOT_RUNNING_OTHER_THREAD(gb)
#ifndef GB_DISABLE_DEBUGGER
if (unlikely(gb->n_watchpoints)) {
GB_debugger_test_write_watchpoint(gb, addr, value);
}
#endif
if (bus_for_addr(gb, addr) == GB_BUS_MAIN && addr < 0xFF00) {
gb->data_bus = value;
gb->data_bus_decay_countdown = gb->data_bus_decay;

View File

@ -1,4 +1,5 @@
#include "gb.h"
#include <string.h>
/* TODO: Emulation is VERY basic and assumes the ROM correctly uses the printer's interface.
Incorrect usage is not correctly emulated, as it's not well documented, nor do I

View File

@ -1,6 +1,6 @@
#ifndef rewind_h
#define rewind_h
#ifndef GB_DISABLE_REWIND
#include <stdbool.h>
#include "defs.h"
@ -12,3 +12,4 @@ void GB_set_rewind_length(GB_gameboy_t *gb, double seconds);
void GB_rewind_reset(GB_gameboy_t *gb);
#endif
#endif

View File

@ -2,6 +2,8 @@
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#ifdef GB_BIG_ENDIAN
#define BESS_NAME "SameBoy v" GB_VERSION " (Big Endian)"

View File

@ -2,6 +2,7 @@
#include "random.h"
#include <math.h>
#include <assert.h>
#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846

View File

@ -949,9 +949,11 @@ LD_X_Y(a,b) LD_X_Y(a,c) LD_X_Y(a,d) LD_X_Y(a,e) LD_X_Y(a,h) LD_X_Y(a,l) LD_X_DHL
// fire the debugger if software breakpoints are enabled
static void ld_b_b(GB_gameboy_t *gb, uint8_t opcode)
{
#ifndef GB_DISABLE_DEBUGGER
if (gb->has_software_breakpoints) {
GB_debugger_break(gb);
}
#endif
}
static void add_a_r(GB_gameboy_t *gb, uint8_t opcode)

View File

@ -3,7 +3,9 @@
#include "defs.h"
#include <stdint.h>
#ifndef GB_DISABLE_DEBUGGER
void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count);
#endif
#ifdef GB_INTERNAL
internal void GB_cpu_run(GB_gameboy_t *gb);
#endif

View File

@ -1,6 +1,6 @@
#ifndef symbol_hash_h
#define symbol_hash_h
#ifndef GB_DISABLE_DEBUGGER
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
@ -34,5 +34,5 @@ internal const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16
internal GB_symbol_map_t *GB_map_alloc(void);
internal void GB_map_free(GB_symbol_map_t *map);
#endif
#endif
#endif

View File

@ -436,7 +436,9 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
}
}
#ifndef GB_DISABLE_DEBUGGER
gb->debugger_ticks += cycles;
#endif
if (gb->speed_switch_freeze) {
if (gb->speed_switch_freeze >= cycles) {
@ -451,7 +453,9 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
cycles <<= 1;
}
#ifndef GB_DISABLE_DEBUGGER
gb->absolute_debugger_ticks += cycles;
#endif
// Not affected by speed boost
if (likely(gb->io_registers[GB_IO_LCDC] & GB_LCDC_ENABLE)) {

View File

@ -1,5 +1,6 @@
#include "gb.h"
#include <time.h>
#include <string.h>
static inline uint8_t int_to_bcd(uint8_t i)
{

View File

@ -52,6 +52,46 @@ ifeq ($(MAKECMDGOALS),)
MAKECMDGOALS := $(DEFAULT)
endif
ifneq ($(DISABLE_TIMEKEEPING),)
CFLAGS += -DGB_DISABLE_TIMEKEEPING
CPPP_FLAGS += -DGB_DISABLE_TIMEKEEPING
else
CPPP_FLAGS += -UGB_DISABLE_TIMEKEEPING
endif
ifneq ($(DISABLE_REWIND),)
CFLAGS += -DGB_DISABLE_REWIND
CPPP_FLAGS += -DGB_DISABLE_REWIND
CORE_FILTER += Core/rewind.c
else
CPPP_FLAGS += -UGB_DISABLE_REWIND
endif
ifneq ($(DISABLE_DEBUGGER),)
CFLAGS += -DGB_DISABLE_DEBUGGER
CPPP_FLAGS += -DGB_DISABLE_DEBUGGER
CORE_FILTER += Core/debugger.c Core/sm83_disassembler.c Core/symbol_hash.c
else
CPPP_FLAGS += -UGB_DISABLE_DEBUGGER
endif
ifneq ($(DISABLE_CHEATS),)
CFLAGS += -DGB_DISABLE_CHEATS
CPPP_FLAGS += -DGB_DISABLE_CHEATS
CORE_FILTER += Core/cheats.c
else
CPPP_FLAGS += -UGB_DISABLE_CHEATS
endif
ifneq ($(CORE_FILTER)$(DISABLE_TIMEKEEPING),)
ifneq ($(MAKECMDGOALS),lib)
$(error SameBoy features can only be disabled when compiling the 'lib' target)
endif
endif
CPPP_FLAGS += -UGB_INTERNAL
include version.mk
COPYRIGHT_YEAR := $(shell grep -oE "20[2-9][0-9]" LICENSE)
export VERSION
@ -284,7 +324,7 @@ endif
# Get a list of our source files and their respective object file targets
CORE_SOURCES := $(shell ls Core/*.c)
CORE_SOURCES := $(filter-out $(CORE_FILTER),$(shell ls Core/*.c))
CORE_HEADERS := $(shell ls Core/*.h)
SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) $(patsubst %,SDL/audio/%.c,$(SDL_AUDIO_DRIVERS))
TESTER_SOURCES := $(shell ls Tester/*.c)
@ -673,7 +713,7 @@ $(LIB)/libsameboy.a: $(LIB)/libsameboy.o
$(INC)/%.h: Core/%.h
-@$(MKDIR) -p $(dir $@)
-@# CPPP doesn't like multibyte characters, so we replace the single quote character before processing so it doesn't complain
sed "s/'/@SINGLE_QUOTE@/g" $^ | cppp -UGB_INTERNAL | sed "s/@SINGLE_QUOTE@/'/g" > $@
sed "s/'/@SINGLE_QUOTE@/g" $^ | cppp $(CPPP_FLAGS) | sed "s/@SINGLE_QUOTE@/'/g" > $@
lib-unsupported:
@echo Due to limitations of lld-link, compiling SameBoy as a library on Windows is not supported.

View File

@ -9,7 +9,6 @@ SOURCES_C := $(CORE_DIR)/Core/gb.c \
$(CORE_DIR)/Core/mbc.c \
$(CORE_DIR)/Core/timing.c \
$(CORE_DIR)/Core/display.c \
$(CORE_DIR)/Core/symbol_hash.c \
$(CORE_DIR)/Core/camera.c \
$(CORE_DIR)/Core/sm83_cpu.c \
$(CORE_DIR)/Core/joypad.c \