diff options
author | David Guillen Fandos | 2021-03-22 21:45:52 +0100 |
---|---|---|
committer | David Guillen Fandos | 2021-03-22 21:45:52 +0100 |
commit | f6f3a910397afb769f84d1332014c4eda1fedebe (patch) | |
tree | b8885300d4e020da90d4308df2e9dba03d46fde5 | |
parent | eab44b9e0b9dcb5cf7fa7b6851fa5454041da930 (diff) | |
download | picogpsp-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.common | 2 | ||||
-rw-r--r-- | bios/README.md | 7 | ||||
-rw-r--r-- | bios/open_gba_bios.bin | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | bios_data.S | 7 | ||||
-rw-r--r-- | cpu.c | 18 | ||||
-rw-r--r-- | gba_memory.h | 1 | ||||
-rw-r--r-- | libretro.c | 100 | ||||
-rw-r--r-- | libretro_core_options.h | 23 | ||||
-rw-r--r-- | main.h | 14 |
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 Binary files differnew file mode 100644 index 0000000..802982e --- /dev/null +++ b/bios/open_gba_bios.bin 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" + @@ -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]; @@ -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.", @@ -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); |