Adding Normmatt's BIOS as a built-in BIOS

Add options to select whether to boot from BIOS (default is no, as it is
now) and whether to use the original bios or the builtin one (default is
auto, which tries to use the official but falls back to the builtin if
not found).
This commit is contained in:
David Guillen Fandos 2021-03-22 21:45:52 +01:00
parent eab44b9e0b
commit f6f3a91039
9 changed files with 147 additions and 25 deletions

View File

@ -1,6 +1,6 @@
INCFLAGS := -I$(CORE_DIR)/libretro -I$(CORE_DIR)/src
SOURCES_ASM :=
SOURCES_ASM := $(CORE_DIR)/bios_data.S
ifeq ($(HAVE_GRIFFIN), 1)
SOURCES_C := $(CORE_DIR)/gpsp_griffin.c

7
bios/README.md Normal file
View File

@ -0,0 +1,7 @@
This BIOS is an open source replacement for Nintendo's official BIOS.
It was written originally by Normmatt and the VBA/VBA-M team, and its source
code can be found at https://github.com/Nebuleon/ReGBA/tree/master/bios
It is distributed under the GPL2 license (see repo)

BIN
bios/open_gba_bios.bin Normal file

Binary file not shown.

7
bios_data.S Normal file
View File

@ -0,0 +1,7 @@
.globl open_gba_bios_rom
.data
open_gba_bios_rom:
.incbin "bios/open_gba_bios.bin"

18
cpu.c
View File

@ -4297,13 +4297,23 @@ void init_cpu(void)
for(i = 0; i < 16; i++)
reg[i] = 0;
reg[REG_SP] = 0x03007F00;
reg[REG_PC] = 0x08000000;
reg[REG_CPSR] = 0x0000001F;
reg[CPU_HALT_STATE] = CPU_ACTIVE;
reg[CPU_MODE] = MODE_USER;
reg[CHANGED_PC_STATUS] = 0;
if (selected_boot_mode == boot_game) {
reg[REG_SP] = 0x03007F00;
reg[REG_PC] = 0x08000000;
reg[REG_CPSR] = 0x0000001F; // system mode
reg[CPU_MODE] = MODE_USER;
} else {
reg[REG_SP] = 0x03007F00;
reg[REG_PC] = 0x00000000;
reg[REG_CPSR] = 0x00000013 | 0xC0; // supervisor
reg[CPU_MODE] = MODE_SUPERVISOR;
}
// Stack pointers are set by BIOS, we set them
// nevertheless, should we not boot from BIOS
reg_mode[MODE_USER][5] = 0x03007F00;
reg_mode[MODE_IRQ][5] = 0x03007FA0;
reg_mode[MODE_FIQ][5] = 0x03007FA0;

View File

@ -201,6 +201,7 @@ extern u32 gbc_sound_update;
extern u32 gbc_sound_wave_update;
extern dma_transfer_type dma[4];
extern u8 open_gba_bios_rom[1024*16];
extern u32 bios_read_protect;
extern u16 palette_ram[512];
extern u16 oam_ram[512];

View File

@ -65,6 +65,7 @@ static unsigned audio_buff_occupancy = 0;
static bool audio_buff_underrun = false;
static unsigned audio_latency = 0;
static bool update_audio_latency = false;
static bios_type selected_bios = auto_detect;
static retro_log_printf_t log_cb;
static retro_video_refresh_t video_cb;
@ -75,6 +76,7 @@ struct retro_perf_callback perf_cb;
int dynarec_enable;
int use_libretro_save_method = 0;
boot_mode selected_boot_mode = boot_game;
u32 idle_loop_target_pc = 0xFFFFFFFF;
u32 iwram_stack_optimize = 1;
@ -114,6 +116,25 @@ static void info_msg(const char* text)
log_cb(RETRO_LOG_INFO, "[gpSP]: %s\n", text);
}
static void show_warning_message(const char* text, unsigned durationms) {
unsigned ifversion = 0;
if (!environ_cb(RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION, &ifversion) || ifversion >= 1) {
/* Use the new API to display messages */
struct retro_message_ext msg = {
.msg = text, .duration = durationms,
.priority = 2, .level = RETRO_LOG_WARN,
.target = RETRO_MESSAGE_TARGET_ALL,
.type = RETRO_MESSAGE_TYPE_NOTIFICATION,
.progress = -1,
};
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE_EXT, &msg);
}
else {
struct retro_message msg = {.msg = text, .frames = durationms / 17};
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
}
}
/* Frameskip START */
static void audio_buff_status_cb(
@ -484,6 +505,8 @@ void retro_init(void)
audio_buff_underrun = false;
audio_latency = 0;
update_audio_latency = false;
selected_bios = auto_detect;
selected_boot_mode = boot_game;
}
void retro_deinit(void)
@ -660,6 +683,32 @@ static void check_variables(int started_from_load)
dynarec_enable = 0;
#endif
if (started_from_load) {
var.key = "gpsp_bios";
var.value = 0;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "auto"))
selected_bios = auto_detect;
else if (!strcmp(var.value, "builtin"))
selected_bios = builtin_bios;
else if (!strcmp(var.value, "official"))
selected_bios = official_bios;
}
var.key = "gpsp_boot_mode";
var.value = 0;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "game"))
selected_boot_mode = boot_game;
else if (!strcmp(var.value, "bios"))
selected_boot_mode = boot_bios;
}
}
var.key = "gpsp_frameskip";
var.value = 0;
frameskip_type_prev = current_frameskip_type;
@ -795,30 +844,41 @@ bool retro_load_game(const struct retro_game_info* info)
extract_directory(main_path, info->path, sizeof(main_path));
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
strcpy(filename_bios, dir);
else
strcpy(filename_bios, main_path);
strcat(filename_bios, "/gba_bios.bin");
if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir)
strcpy(save_path, dir);
else
strcpy(save_path, main_path);
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
strcpy(filename_bios, dir);
else
strcpy(filename_bios, main_path);
bool bios_loaded = false;
printf("USE %d\n", (int)selected_bios);
if (selected_bios == auto_detect || selected_bios == official_bios)
{
bios_loaded = true;
strcat(filename_bios, "/gba_bios.bin");
if (load_bios(filename_bios) != 0)
{
error_msg("Could not load BIOS image file.");
return false;
if (selected_bios == official_bios)
show_warning_message("Could not load BIOS image file, using built-in BIOS", 2500);
bios_loaded = false;
}
if (bios_rom[0] != 0x18)
if (bios_loaded && bios_rom[0] != 0x18)
{
info_msg("You have an incorrect BIOS image.");
info_msg("While many games will work fine, some will not.");
info_msg("It is strongly recommended that you obtain the correct BIOS file.");
if (selected_bios == official_bios)
show_warning_message("BIOS image seems incorrect, using built-in BIOS", 2500);
bios_loaded = false;
}
}
if (!bios_loaded) {
/* Load the built-in BIOS */
memcpy(bios_rom, open_gba_bios_rom, sizeof(bios_rom));
}
memset(gamepak_backup, -1, sizeof(gamepak_backup));

View File

@ -53,6 +53,29 @@ extern "C" {
* frontend language definition */
struct retro_core_option_definition option_defs_us[] = {
{
"gpsp_bios",
"BIOS",
"Choose the BIOS image to use. The official BIOS must be provided by the user. Using a non-official (or builtin) BIOS might result in incompatibility problems with some games. Best results are to be achieved with the official Nintendo BIOS.",
{
{ "auto", "Auto select" },
{ "builtin", "Builtin BIOS" },
{ "official", "Original BIOS" },
{ NULL, NULL },
},
"auto"
},
{
"gpsp_boot_mode",
"Boot mode",
"Choose whether to boot the BIOS before the game or not. There's not much difference in either modes.",
{
{ "game", "Boot to game" },
{ "bios", "Boot to BIOS" },
{ NULL, NULL },
},
"game"
},
{
"gpsp_frameskip",
"Frameskip",

14
main.h
View File

@ -64,6 +64,19 @@ typedef enum
fixed_interval_frameskip
} frameskip_type;
typedef enum
{
auto_detect = 0,
builtin_bios,
official_bios
} bios_type;
typedef enum
{
boot_game = 0,
boot_bios
} boot_mode;
extern u32 cpu_ticks;
extern u32 execute_cycles;
extern u32 global_cycles_per_instruction;
@ -98,6 +111,7 @@ u32 file_length(FILE *fp);
extern u32 num_skipped_frames;
extern int dynarec_enable;
extern boot_mode selected_boot_mode;
void change_ext(const char *src, char *buffer, const char *extension);