summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Guillen Fandos2021-03-22 21:45:52 +0100
committerDavid Guillen Fandos2021-03-22 21:45:52 +0100
commitf6f3a910397afb769f84d1332014c4eda1fedebe (patch)
treeb8885300d4e020da90d4308df2e9dba03d46fde5
parenteab44b9e0b9dcb5cf7fa7b6851fa5454041da930 (diff)
downloadpicogpsp-f6f3a910397afb769f84d1332014c4eda1fedebe.tar.gz
picogpsp-f6f3a910397afb769f84d1332014c4eda1fedebe.tar.bz2
picogpsp-f6f3a910397afb769f84d1332014c4eda1fedebe.zip
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).
-rw-r--r--Makefile.common2
-rw-r--r--bios/README.md7
-rw-r--r--bios/open_gba_bios.binbin0 -> 16384 bytes
-rw-r--r--bios_data.S7
-rw-r--r--cpu.c18
-rw-r--r--gba_memory.h1
-rw-r--r--libretro.c100
-rw-r--r--libretro_core_options.h23
-rw-r--r--main.h14
9 files changed, 147 insertions, 25 deletions
diff --git a/Makefile.common b/Makefile.common
index 7e70627..0dcbedc 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -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
diff --git a/bios/README.md b/bios/README.md
new file mode 100644
index 0000000..64d6679
--- /dev/null
+++ b/bios/README.md
@@ -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)
+
diff --git a/bios/open_gba_bios.bin b/bios/open_gba_bios.bin
new file mode 100644
index 0000000..802982e
--- /dev/null
+++ b/bios/open_gba_bios.bin
Binary files differ
diff --git a/bios_data.S b/bios_data.S
new file mode 100644
index 0000000..9de9d8a
--- /dev/null
+++ b/bios_data.S
@@ -0,0 +1,7 @@
+
+.globl open_gba_bios_rom
+
+.data
+open_gba_bios_rom:
+ .incbin "bios/open_gba_bios.bin"
+
diff --git a/cpu.c b/cpu.c
index 2c93f38..11c947f 100644
--- a/cpu.c
+++ b/cpu.c
@@ -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;
diff --git a/gba_memory.h b/gba_memory.h
index 9352e88..eaa5bab 100644
--- a/gba_memory.h
+++ b/gba_memory.h
@@ -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];
diff --git a/libretro.c b/libretro.c
index bc61977..334864c 100644
--- a/libretro.c
+++ b/libretro.c
@@ -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(
@@ -348,8 +369,8 @@ static void video_run(void)
sceGuTexMode(GU_PSM_5650, 0, 0, GU_FALSE);
sceGuCopyImage(GU_PSM_5650, 0, 0, GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT, GBA_SCREEN_WIDTH,
gba_screen_pixels_buf, 0, 0, GBA_SCREEN_WIDTH, texture_vram_p);
- sceGuTexImage(0, next_pow2(GBA_SCREEN_WIDTH), next_pow2(GBA_SCREEN_HEIGHT), GBA_SCREEN_WIDTH, texture_vram_p);
- sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
+ sceGuTexImage(0, next_pow2(GBA_SCREEN_WIDTH), next_pow2(GBA_SCREEN_HEIGHT), GBA_SCREEN_WIDTH, texture_vram_p);
+ sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
sceGuDisable(GU_BLEND);
sceGuFinish();
@@ -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 (load_bios(filename_bios) != 0)
+ 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)
{
- error_msg("Could not load BIOS image file.");
- return false;
+ bios_loaded = true;
+ strcat(filename_bios, "/gba_bios.bin");
+
+ if (load_bios(filename_bios) != 0)
+ {
+ if (selected_bios == official_bios)
+ show_warning_message("Could not load BIOS image file, using built-in BIOS", 2500);
+ bios_loaded = false;
+ }
+
+ if (bios_loaded && bios_rom[0] != 0x18)
+ {
+ if (selected_bios == official_bios)
+ show_warning_message("BIOS image seems incorrect, using built-in BIOS", 2500);
+ bios_loaded = false;
+ }
}
- if (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 (!bios_loaded) {
+ /* Load the built-in BIOS */
+ memcpy(bios_rom, open_gba_bios_rom, sizeof(bios_rom));
}
memset(gamepak_backup, -1, sizeof(gamepak_backup));
@@ -921,8 +981,8 @@ void retro_run(void)
input_poll_cb();
- /* Check whether current frame should
- * be skipped */
+ /* Check whether current frame should
+ * be skipped */
skip_next_frame = 0;
if (current_frameskip_type != no_frameskip)
diff --git a/libretro_core_options.h b/libretro_core_options.h
index b5b138d..d2b95fa 100644
--- a/libretro_core_options.h
+++ b/libretro_core_options.h
@@ -54,6 +54,29 @@ extern "C" {
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",
"Skip frames to avoid audio buffer under-run (crackling). Improves performance at the expense of visual smoothness. 'Auto' skips frames when advised by the frontend. 'Auto (Threshold)' utilises the 'Frameskip Threshold (%)' setting. 'Fixed Interval' utilises the 'Frameskip Interval' setting.",
diff --git a/main.h b/main.h
index dbb839f..bdb29e3 100644
--- a/main.h
+++ b/main.h
@@ -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);