2021-07-05 17:44:08 +00:00
/*
This file is part of Flycast .
Flycast is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
Flycast is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Flycast . If not , see < https : //www.gnu.org/licenses/>.
*/
# include <cstdio>
# include <cstdarg>
# include <math.h>
# include "types.h"
# ifndef _WIN32
# include <sys/time.h>
# endif
2021-07-12 18:14:21 +00:00
# ifdef __SWITCH__
2021-07-05 17:44:08 +00:00
# include <stdlib.h>
# include <string.h>
2021-07-15 10:19:11 +00:00
# include "nswitch.h"
2021-07-05 17:44:08 +00:00
# endif
# include <sys/stat.h>
# include <file/file_path.h>
# include <libretro.h>
# if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
# include <glsm/glsm.h>
# endif
# ifdef HAVE_VULKAN
# include "rend/vulkan/vulkan_context.h"
# include <libretro_vulkan.h>
# endif
# include "emulator.h"
# include "hw/sh4/sh4_mem.h"
# include "hw/sh4/sh4_sched.h"
# include "hw/sh4/dyna/blockmanager.h"
# include "keyboard_map.h"
# include "hw/maple/maple_cfg.h"
# include "hw/maple/maple_if.h"
# include "hw/maple/maple_cfg.h"
# include "hw/pvr/spg.h"
# include "hw/naomi/naomi_cart.h"
# include "imgread/common.h"
# include "LogManager.h"
# include "cheats.h"
# include "rend/CustomTexture.h"
# include "rend/osd.h"
# include "cfg/option.h"
# include "wsi/gl_context.h"
2021-07-13 11:45:01 +00:00
# include "version.h"
2021-07-05 17:44:08 +00:00
constexpr char slash = path_default_slash_c ( ) ;
# define RETRO_DEVICE_TWINSTICK RETRO_DEVICE_SUBCLASS( RETRO_DEVICE_JOYPAD, 1 )
# define RETRO_DEVICE_TWINSTICK_SATURN RETRO_DEVICE_SUBCLASS( RETRO_DEVICE_JOYPAD, 2 )
# define RETRO_DEVICE_ASCIISTICK RETRO_DEVICE_SUBCLASS( RETRO_DEVICE_JOYPAD, 3 )
# define RETRO_ENVIRONMENT_RETROARCH_START_BLOCK 0x800000
# define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND (2 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK)
/* bool * --
* Boolean value that tells the front end to save states in the
* background or not .
*/
# define RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB (3 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK)
/* retro_environment_t * --
* Provides the callback to the frontend method which will cancel
* all currently waiting threads . Used when coordination is needed
* between the core and the frontend to gracefully stop all threads .
*/
# define RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE (4 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK)
/* unsigned * --
* Tells the frontend to override the poll type behavior .
* Allows the frontend to influence the polling behavior of the
* frontend .
*
* Will be unset when retro_unload_game is called .
*
* 0 - Don ' t Care , no changes , frontend still determines polling type behavior .
* 1 - Early
* 2 - Normal
* 3 - Late
*/
# include "libretro_core_option_defines.h"
# include "libretro_core_options.h"
# include "vmu_xhair.h"
2021-07-20 08:06:44 +00:00
std : : string arcadeFlashPath ;
2021-07-05 17:44:08 +00:00
static bool boot_to_bios ;
static bool devices_need_refresh = false ;
static int device_type [ 4 ] = { - 1 , - 1 , - 1 , - 1 } ;
static int astick_deadzone = 0 ;
static int trigger_deadzone = 0 ;
static bool digital_triggers = false ;
static bool allow_service_buttons = false ;
static bool libretro_supports_bitmasks = false ;
u32 kcode [ 4 ] = { 0xFFFFFFFF , 0xFFFFFFFF , 0xFFFFFFFF , 0xFFFFFFFF } ;
u8 rt [ 4 ] ;
u8 lt [ 4 ] ;
u32 vks [ 4 ] ;
s8 joyx [ 4 ] , joyy [ 4 ] ;
s8 joyrx [ 4 ] , joyry [ 4 ] ;
static bool enable_purupuru = true ;
static u32 vib_stop_time [ 4 ] ;
static double vib_strength [ 4 ] ;
static double vib_delta [ 4 ] ;
unsigned per_content_vmus = 0 ;
static bool first_run = true ;
2021-07-07 07:48:10 +00:00
static bool mute_messages ;
static bool rotate_screen ;
2021-07-12 07:57:58 +00:00
static bool rotate_game ;
2021-07-08 18:09:09 +00:00
static int framebufferWidth ;
static int framebufferHeight ;
2021-07-12 07:57:58 +00:00
static int maxFramebufferWidth ;
static int maxFramebufferHeight ;
2021-07-05 17:44:08 +00:00
static retro_perf_callback perf_cb ;
static retro_get_cpu_features_t perf_get_cpu_features_cb ;
// Callbacks
static retro_log_printf_t log_cb ;
static retro_video_refresh_t video_cb ;
static retro_input_poll_t poll_cb ;
static retro_input_state_t input_cb ;
retro_audio_sample_batch_t audio_batch_cb ;
static retro_environment_t environ_cb ;
static retro_environment_t frontend_clear_thread_waits_cb ;
static retro_rumble_interface rumble ;
static void refresh_devices ( bool first_startup ) ;
static void init_disk_control_interface ( ) ;
static bool read_m3u ( const char * file ) ;
2021-09-29 08:22:58 +00:00
void UpdateInputState ( ) ;
2021-07-05 17:44:08 +00:00
2021-09-30 12:24:17 +00:00
static std : : string game_data ;
2021-07-05 17:44:08 +00:00
static char g_base_name [ 128 ] ;
static char game_dir [ 1024 ] ;
char game_dir_no_slash [ 1024 ] ;
char vmu_dir_no_slash [ PATH_MAX ] ;
char content_name [ PATH_MAX ] ;
static char g_roms_dir [ PATH_MAX ] ;
static std : : mutex mtx_serialization ;
static bool gl_ctx_resetting = false ;
2021-07-07 11:12:16 +00:00
static bool is_dupe ;
static u64 startTime ;
2021-07-05 17:44:08 +00:00
// Disk swapping
static struct retro_disk_control_callback retro_disk_control_cb ;
static struct retro_disk_control_ext_callback retro_disk_control_ext_cb ;
static unsigned disk_initial_index = 0 ;
static std : : string disk_initial_path ;
static unsigned disk_index = 0 ;
static std : : vector < std : : string > disk_paths ;
static std : : vector < std : : string > disk_labels ;
static bool disc_tray_open = false ;
void retro_set_video_refresh ( retro_video_refresh_t cb )
{
video_cb = cb ;
}
void retro_set_audio_sample ( retro_audio_sample_t cb )
{
// Nothing to do here
}
void retro_set_audio_sample_batch ( retro_audio_sample_batch_t cb )
{
audio_batch_cb = cb ;
}
void retro_set_input_poll ( retro_input_poll_t cb )
{
poll_cb = cb ;
}
void retro_set_input_state ( retro_input_state_t cb )
{
input_cb = cb ;
}
static void input_set_deadzone_stick ( int percent )
{
if ( percent > = 0 & & percent < = 100 )
astick_deadzone = ( int ) ( percent * 0.01f * 0x8000 ) ;
}
static void input_set_deadzone_trigger ( int percent )
{
if ( percent > = 0 & & percent < = 100 )
trigger_deadzone = ( int ) ( percent * 0.01f * 0x8000 ) ;
}
void retro_set_environment ( retro_environment_t cb )
{
environ_cb = cb ;
libretro_set_core_options ( environ_cb ) ;
static const struct retro_controller_description ports_default [ ] =
{
{ " Controller " , RETRO_DEVICE_JOYPAD } ,
{ " Arcade Stick " , RETRO_DEVICE_ASCIISTICK } ,
{ " Keyboard " , RETRO_DEVICE_KEYBOARD } ,
{ " Mouse " , RETRO_DEVICE_MOUSE } ,
{ " Light Gun " , RETRO_DEVICE_LIGHTGUN } ,
{ " Twin Stick " , RETRO_DEVICE_TWINSTICK } ,
{ " Saturn Twin-Stick " , RETRO_DEVICE_TWINSTICK_SATURN } ,
{ 0 } ,
} ;
static const struct retro_controller_info ports [ ] = {
{ ports_default , 7 } ,
{ ports_default , 7 } ,
{ ports_default , 7 } ,
{ ports_default , 7 } ,
{ 0 } ,
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_CONTROLLER_INFO , ( void * ) ports ) ;
}
static void retro_keyboard_event ( bool down , unsigned keycode , uint32_t character , uint16_t key_modifiers ) ;
// Now comes the interesting stuff
void retro_init ( )
{
// Logging
struct retro_log_callback log ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_LOG_INTERFACE , & log ) )
log_cb = log . log ;
else
log_cb = NULL ;
LogManager : : Init ( ( void * ) log_cb ) ;
NOTICE_LOG ( BOOT , " retro_init " ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_PERF_INTERFACE , & perf_cb ) )
perf_get_cpu_features_cb = perf_cb . get_cpu_features ;
else
perf_get_cpu_features_cb = NULL ;
// Set color mode
unsigned color_mode = RETRO_PIXEL_FORMAT_XRGB8888 ;
environ_cb ( RETRO_ENVIRONMENT_SET_PIXEL_FORMAT , & color_mode ) ;
environ_cb ( RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB , & frontend_clear_thread_waits_cb ) ;
init_kb_map ( ) ;
struct retro_keyboard_callback kb_callback = { & retro_keyboard_event } ;
environ_cb ( RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK , & kb_callback ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_INPUT_BITMASKS , NULL ) )
libretro_supports_bitmasks = true ;
init_disk_control_interface ( ) ;
if ( ! _vmem_reserve ( ) )
ERROR_LOG ( VMEM , " Cannot reserve memory space " ) ;
2021-07-20 11:06:08 +00:00
os_InstallFaultHandler ( ) ;
2021-07-05 17:44:08 +00:00
}
void retro_deinit ( )
{
2021-07-11 15:42:30 +00:00
INFO_LOG ( COMMON , " retro_deinit " ) ;
2021-07-05 17:44:08 +00:00
first_run = true ;
//When auto-save states are enabled this is needed to prevent the core from shutting down before
//any save state actions are still running - which results in partial saves
{
std : : lock_guard < std : : mutex > lock ( mtx_serialization ) ;
}
2021-07-20 11:06:08 +00:00
os_UninstallFaultHandler ( ) ;
2021-07-05 17:44:08 +00:00
libretro_supports_bitmasks = false ;
LogManager : : Shutdown ( ) ;
}
static void set_variable_visibility ( )
{
struct retro_core_option_display option_display ;
struct retro_variable var ;
2021-07-07 11:12:16 +00:00
// Show/hide NAOMI/Atomiswave options
2021-07-05 17:44:08 +00:00
option_display . visible = ( ( settings . platform . system = = DC_PLATFORM_NAOMI ) | |
( settings . platform . system = = DC_PLATFORM_ATOMISWAVE ) ) ;
option_display . key = CORE_OPTION_NAME " _allow_service_buttons " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _enable_naomi_15khz_dipswitch " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2021-07-07 11:12:16 +00:00
// Show/hide Dreamcast options
2021-07-05 17:44:08 +00:00
option_display . visible = ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) ;
option_display . key = CORE_OPTION_NAME " _boot_to_bios " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _hle_bios " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _gdrom_fast_loading " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _cable_type " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _broadcast " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _language " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _force_wince " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _enable_purupuru " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _per_content_vmus " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
option_display . key = CORE_OPTION_NAME " _show_vmu_screen_settings " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2021-07-07 11:12:16 +00:00
// Show/hide settings-dependent options
2021-07-05 17:44:08 +00:00
option_display . visible = config : : ThreadedRendering ;
2021-07-07 11:12:16 +00:00
option_display . key = CORE_OPTION_NAME " _auto_skip_frame " ;
2021-07-05 17:44:08 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
// Only for per-pixel renderers
option_display . visible = config : : RendererType = = RenderType : : OpenGL_OIT | | config : : RendererType = = RenderType : : Vulkan_OIT ;
option_display . key = CORE_OPTION_NAME " _oit_abuffer_size " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
// Only if texture upscaling is enabled
option_display . visible = config : : TextureUpscale > 1 ;
option_display . key = CORE_OPTION_NAME " _texupscale_max_filtered_texture_size " ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
2021-07-07 11:12:16 +00:00
// Show/hide VMU screen options
2021-07-05 17:44:08 +00:00
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST )
{
option_display . visible = true ;
var . key = CORE_OPTION_NAME " _show_vmu_screen_settings " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
if ( ! strcmp ( var . value , " disabled " ) )
option_display . visible = false ;
}
else
option_display . visible = false ;
for ( int i = 0 ; i < 4 ; i + + )
{
char key [ 256 ] ;
option_display . key = key ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _screen_display " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _screen_position " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _screen_size_mult " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _pixel_on_color " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _pixel_off_color " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _vmu " , i + 1 , " _screen_opacity " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
}
2021-07-07 11:12:16 +00:00
// Show/hide light gun options
2021-07-05 17:44:08 +00:00
option_display . visible = true ;
var . key = CORE_OPTION_NAME " _show_lightgun_settings " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
if ( ! strcmp ( var . value , " disabled " ) )
option_display . visible = false ;
for ( int i = 0 ; i < 4 ; i + + )
{
char key [ 256 ] ;
option_display . key = key ;
snprintf ( key , sizeof ( key ) , " %s%u%s " , CORE_OPTION_NAME " _lightgun " , i + 1 , " _crosshair " ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY , & option_display ) ;
}
}
2021-07-12 07:57:58 +00:00
static void setFramebufferSize ( )
{
framebufferHeight = config : : RenderResolution ;
if ( config : : Widescreen )
framebufferWidth = config : : RenderResolution * 16.f / 9.f ;
else if ( ! rotate_screen )
framebufferWidth = config : : RenderResolution * 4.f * config : : ScreenStretching / 3.f / 100.f ;
else
framebufferWidth = config : : RenderResolution * 4.f / 3.f ;
maxFramebufferHeight = std : : max ( maxFramebufferHeight , framebufferHeight ) ;
maxFramebufferWidth = std : : max ( maxFramebufferWidth , framebufferWidth ) ;
}
static void setGameGeometry ( retro_game_geometry & geometry )
{
geometry . aspect_ratio = ( float ) framebufferWidth / framebufferHeight ;
if ( rotate_screen )
geometry . aspect_ratio = 1 / geometry . aspect_ratio ;
geometry . max_width = std : : max ( framebufferHeight * 16 / 9 , framebufferWidth ) ;
geometry . max_height = geometry . max_width ;
2021-08-15 08:50:53 +00:00
// Avoid gigantic window size at startup
geometry . base_width = 640 ;
geometry . base_height = 480 ;
2021-07-12 07:57:58 +00:00
}
static void setAVInfo ( retro_system_av_info & avinfo )
{
setGameGeometry ( avinfo . geometry ) ;
avinfo . timing . sample_rate = 44100.0 ;
avinfo . timing . fps = SPG_CONTROL . NTSC ? 59.94 : SPG_CONTROL . PAL ? 50.0 : 60.0 ;
}
static void setRotation ( )
{
int rotation = 0 ;
if ( rotate_game )
{
if ( ! rotate_screen )
rotation = 1 ;
rotate_screen = ! rotate_screen ;
}
else
{
if ( rotate_screen )
rotation = 3 ;
}
environ_cb ( RETRO_ENVIRONMENT_SET_ROTATION , & rotation ) ;
}
2021-07-05 17:44:08 +00:00
static void update_variables ( bool first_startup )
{
2021-07-09 14:28:28 +00:00
bool wasThreadedRendering = config : : ThreadedRendering ;
2021-07-12 07:57:58 +00:00
int prevFramebufferHeight = framebufferHeight ;
int prevFramebufferWidth = framebufferWidth ;
int prevMaxFramebufferHeight = maxFramebufferHeight ;
int prevMaxFramebufferWidth = maxFramebufferWidth ;
bool prevRotateScreen = rotate_screen ;
2021-07-05 17:44:08 +00:00
config : : Settings : : instance ( ) . setRetroEnvironment ( environ_cb ) ;
config : : Settings : : instance ( ) . setOptionDefinitions ( option_defs_us ) ;
config : : Settings : : instance ( ) . load ( false ) ;
retro_variable var ;
var . key = CORE_OPTION_NAME " _per_content_vmus " ;
unsigned previous_per_content_vmus = per_content_vmus ;
per_content_vmus = 0 ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( " VMU A1 " , var . value ) )
per_content_vmus = 1 ;
else if ( ! strcmp ( " All VMUs " , var . value ) )
per_content_vmus = 2 ;
}
if ( ! first_startup & & per_content_vmus ! = previous_per_content_vmus
& & settings . platform . system = = DC_PLATFORM_DREAMCAST )
{
// Recreate the VMUs so that the save location is taken into account.
// Don't do this at startup because we don't know the system type yet
// and the VMUs haven't been created anyway
maple_ReconnectDevices ( ) ;
}
2021-07-12 07:57:58 +00:00
var . key = CORE_OPTION_NAME " _screen_rotation " ;
rotate_screen = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value & & ! strcmp ( " vertical " , var . value ) )
rotate_screen = true ;
2021-07-05 17:44:08 +00:00
var . key = CORE_OPTION_NAME " _internal_resolution " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
char str [ 100 ] ;
snprintf ( str , sizeof ( str ) , " %s " , var . value ) ;
2021-07-13 11:45:01 +00:00
char * pch = strtok ( str , " x " ) ;
2021-07-05 17:44:08 +00:00
pch = strtok ( NULL , " x " ) ;
2021-07-13 11:45:01 +00:00
if ( pch ! = nullptr )
2021-07-05 17:44:08 +00:00
config : : RenderResolution = strtoul ( pch , NULL , 0 ) ;
2021-07-13 11:45:01 +00:00
2021-07-05 17:44:08 +00:00
DEBUG_LOG ( COMMON , " Got height: %u " , ( int ) config : : RenderResolution ) ;
}
var . key = CORE_OPTION_NAME " _boot_to_bios " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " enabled " ) )
boot_to_bios = true ;
else if ( ! strcmp ( var . value , " disabled " ) )
boot_to_bios = false ;
}
else
boot_to_bios = false ;
var . key = CORE_OPTION_NAME " _alpha_sorting " ;
RenderType previous_renderer = config : : RendererType ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " per-strip (fast, least accurate) " ) )
{
if ( config : : RendererType = = RenderType : : Vulkan_OIT )
config : : RendererType = RenderType : : Vulkan ;
2021-07-08 10:47:00 +00:00
else if ( config : : RendererType ! = RenderType : : Vulkan )
2021-07-05 17:44:08 +00:00
config : : RendererType = RenderType : : OpenGL ;
config : : PerStripSorting = true ;
}
else if ( ! strcmp ( var . value , " per-triangle (normal) " ) )
{
if ( config : : RendererType = = RenderType : : Vulkan_OIT )
config : : RendererType = RenderType : : Vulkan ;
2021-07-08 10:47:00 +00:00
else if ( config : : RendererType ! = RenderType : : Vulkan )
2021-07-05 17:44:08 +00:00
config : : RendererType = RenderType : : OpenGL ;
config : : PerStripSorting = false ;
}
else if ( ! strcmp ( var . value , " per-pixel (accurate) " ) )
{
if ( config : : RendererType = = RenderType : : Vulkan )
config : : RendererType = RenderType : : Vulkan_OIT ;
2021-07-08 10:47:00 +00:00
else if ( config : : RendererType ! = RenderType : : Vulkan_OIT )
2021-07-05 17:44:08 +00:00
config : : RendererType = RenderType : : OpenGL_OIT ;
config : : PerStripSorting = false ; // Not used
}
}
else
{
if ( config : : RendererType = = RenderType : : Vulkan_OIT )
config : : RendererType = RenderType : : Vulkan ;
2021-07-08 10:47:00 +00:00
else if ( config : : RendererType ! = RenderType : : Vulkan )
2021-07-05 17:44:08 +00:00
config : : RendererType = RenderType : : OpenGL ;
config : : PerStripSorting = false ;
}
config : : RendererType . commit ( ) ;
if ( ! first_startup & & previous_renderer ! = config : : RendererType ) {
rend_term_renderer ( ) ;
rend_init_renderer ( ) ;
2021-09-27 18:29:23 +00:00
rend_resize_renderer ( ) ;
2021-07-05 17:44:08 +00:00
}
if ( first_startup )
{
# if defined(HAVE_OIT) || defined(HAVE_VULKAN)
var . key = CORE_OPTION_NAME " _oit_abuffer_size " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( var . value , " 512MB " ) )
config : : PixelBufferSize = 0x20000000u ;
else if ( ! strcmp ( var . value , " 1GB " ) )
config : : PixelBufferSize = 0x40000000u ;
else if ( ! strcmp ( var . value , " 2GB " ) )
config : : PixelBufferSize = 0x7ff00000u ;
else if ( ! strcmp ( var . value , " 4GB " ) )
config : : PixelBufferSize = 0xFFFFFFFFu ;
else
config : : PixelBufferSize = 0x20000000u ;
}
else
config : : PixelBufferSize = 0x20000000u ;
# endif
if ( config : : ThreadedRendering )
{
bool save_state_in_background = true ;
unsigned poll_type_early = 1 ; /* POLL_TYPE_EARLY */
environ_cb ( RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND , & save_state_in_background ) ;
environ_cb ( RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE , & poll_type_early ) ;
}
2021-07-16 15:41:40 +00:00
config : : Cable = 3 ;
var . key = CORE_OPTION_NAME " _cable_type " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( " VGA " , var . value ) )
config : : Cable = 0 ;
else if ( ! strcmp ( " TV (RGB) " , var . value ) )
config : : Cable = 2 ;
}
2021-07-05 17:44:08 +00:00
}
var . key = CORE_OPTION_NAME " _enable_purupuru " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( enable_purupuru ! = ( strcmp ( " enabled " , var . value ) = = 0 ) & & settings . platform . system = = DC_PLATFORM_DREAMCAST )
{
enable_purupuru = strcmp ( " enabled " , var . value ) = = 0 ;
for ( int i = 0 ; i < MAPLE_PORTS ; i + + ) {
if ( config : : MapleMainDevices [ i ] = = MDT_SegaController )
config : : MapleExpansionDevices [ i ] [ 1 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
else if ( config : : MapleMainDevices [ i ] = = MDT_LightGun | | config : : MapleMainDevices [ i ] = = MDT_TwinStick
| | config : : MapleMainDevices [ i ] = = MDT_AsciiStick )
config : : MapleExpansionDevices [ i ] [ 0 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
}
if ( ! first_startup )
maple_ReconnectDevices ( ) ;
}
}
var . key = CORE_OPTION_NAME " _analog_stick_deadzone " ;
var . value = NULL ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
input_set_deadzone_stick ( atoi ( var . value ) ) ;
var . key = CORE_OPTION_NAME " _trigger_deadzone " ;
var . value = NULL ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
input_set_deadzone_trigger ( atoi ( var . value ) ) ;
var . key = CORE_OPTION_NAME " _digital_triggers " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( " enabled " , var . value ) )
digital_triggers = true ;
else
digital_triggers = false ;
}
else
digital_triggers = false ;
var . key = CORE_OPTION_NAME " _allow_service_buttons " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( " enabled " , var . value ) )
allow_service_buttons = true ;
else
allow_service_buttons = false ;
}
else
allow_service_buttons = false ;
char key [ 256 ] ;
key [ 0 ] = ' \0 ' ;
var . key = key ;
for ( int i = 0 ; i < 4 ; i + + )
{
lightgun_params [ i ] . offscreen = true ;
lightgun_params [ i ] . x = 0 ;
lightgun_params [ i ] . y = 0 ;
lightgun_params [ i ] . dirty = true ;
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_OFF ;
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _lightgun%d_crosshair " , i + 1 ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
if ( ! strcmp ( " disabled " , var . value ) )
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_OFF ;
else if ( ! strcmp ( " White " , var . value ) )
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_WHITE ;
else if ( ! strcmp ( " Red " , var . value ) )
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_RED ;
else if ( ! strcmp ( " Green " , var . value ) )
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_GREEN ;
else if ( ! strcmp ( " Blue " , var . value ) )
lightgun_params [ i ] . colour = LIGHTGUN_COLOR_BLUE ;
}
2021-07-09 16:17:14 +00:00
if ( lightgun_params [ i ] . colour = = LIGHTGUN_COLOR_OFF )
config : : CrosshairColor [ i ] = 0 ;
else
config : : CrosshairColor [ i ] = lightgun_palette [ lightgun_params [ i ] . colour * 3 ]
| ( lightgun_palette [ lightgun_params [ i ] . colour * 3 + 1 ] < < 8 )
| ( lightgun_palette [ lightgun_params [ i ] . colour * 3 + 2 ] < < 16 )
| 0xff000000 ;
2021-07-05 17:44:08 +00:00
2021-07-10 15:39:16 +00:00
vmu_lcd_status [ i * 2 ] = false ;
vmu_lcd_changed [ i * 2 ] = true ;
2021-07-08 18:09:09 +00:00
vmu_screen_params [ i ] . vmu_screen_position = UPPER_LEFT ;
vmu_screen_params [ i ] . vmu_screen_size_mult = 1 ;
vmu_screen_params [ i ] . vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_ON ] . r ;
vmu_screen_params [ i ] . vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_ON ] . g ;
vmu_screen_params [ i ] . vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_ON ] . b ;
vmu_screen_params [ i ] . vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_OFF ] . r ;
vmu_screen_params [ i ] . vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_OFF ] . g ;
vmu_screen_params [ i ] . vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP [ VMU_DEFAULT_OFF ] . b ;
vmu_screen_params [ i ] . vmu_screen_opacity = 0xFF ;
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_screen_display " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value & & ! strcmp ( " enabled " , var . value ) )
2021-07-10 15:39:16 +00:00
vmu_lcd_status [ i * 2 ] = true ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_screen_position " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2021-07-05 17:44:08 +00:00
{
if ( ! strcmp ( " Upper Left " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_position = UPPER_LEFT ;
else if ( ! strcmp ( " Upper Right " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_position = UPPER_RIGHT ;
else if ( ! strcmp ( " Lower Left " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_position = LOWER_LEFT ;
else if ( ! strcmp ( " Lower Right " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_position = LOWER_RIGHT ;
}
2021-07-08 18:09:09 +00:00
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_screen_size_mult " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2021-07-05 17:44:08 +00:00
{
if ( ! strcmp ( " 1x " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_size_mult = 1 ;
else if ( ! strcmp ( " 2x " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_size_mult = 2 ;
else if ( ! strcmp ( " 3x " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_size_mult = 3 ;
else if ( ! strcmp ( " 4x " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_size_mult = 4 ;
else if ( ! strcmp ( " 5x " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_size_mult = 5 ;
}
2021-07-08 18:09:09 +00:00
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_screen_opacity " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2021-07-05 17:44:08 +00:00
{
if ( ! strcmp ( " 100% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 255 ;
else if ( ! strcmp ( " 90% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 9 * 25.5 ;
else if ( ! strcmp ( " 80% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 8 * 25.5 ;
else if ( ! strcmp ( " 70% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 7 * 25.5 ;
else if ( ! strcmp ( " 60% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 6 * 25.5 ;
else if ( ! strcmp ( " 50% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 5 * 25.5 ;
else if ( ! strcmp ( " 40% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 4 * 25.5 ;
else if ( ! strcmp ( " 30% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 3 * 25.5 ;
else if ( ! strcmp ( " 20% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 2 * 25.5 ;
else if ( ! strcmp ( " 10% " , var . value ) )
vmu_screen_params [ i ] . vmu_screen_opacity = 1 * 25.5 ;
}
2021-07-08 18:09:09 +00:00
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_pixel_on_color " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value & & strlen ( var . value ) > 1 )
2021-07-05 17:44:08 +00:00
{
2021-07-08 18:09:09 +00:00
int color_idx = atoi ( var . value + ( strlen ( var . value ) - 2 ) ) ;
vmu_screen_params [ i ] . vmu_pixel_on_R = VMU_SCREEN_COLOR_MAP [ color_idx ] . r ;
vmu_screen_params [ i ] . vmu_pixel_on_G = VMU_SCREEN_COLOR_MAP [ color_idx ] . g ;
vmu_screen_params [ i ] . vmu_pixel_on_B = VMU_SCREEN_COLOR_MAP [ color_idx ] . b ;
2021-07-05 17:44:08 +00:00
}
2021-07-08 18:09:09 +00:00
snprintf ( key , sizeof ( key ) , CORE_OPTION_NAME " _vmu%d_pixel_off_color " , i + 1 ) ;
2021-07-05 17:44:08 +00:00
2021-07-08 18:09:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value & & strlen ( var . value ) > 1 )
2021-07-05 17:44:08 +00:00
{
2021-07-08 18:09:09 +00:00
int color_idx = atoi ( var . value + ( strlen ( var . value ) - 2 ) ) ;
vmu_screen_params [ i ] . vmu_pixel_off_R = VMU_SCREEN_COLOR_MAP [ color_idx ] . r ;
vmu_screen_params [ i ] . vmu_pixel_off_G = VMU_SCREEN_COLOR_MAP [ color_idx ] . g ;
vmu_screen_params [ i ] . vmu_pixel_off_B = VMU_SCREEN_COLOR_MAP [ color_idx ] . b ;
2021-07-05 17:44:08 +00:00
}
}
set_variable_visibility ( ) ;
2021-07-09 14:28:28 +00:00
2021-07-12 07:57:58 +00:00
if ( ! first_startup )
2021-07-09 14:28:28 +00:00
{
2021-07-12 07:57:58 +00:00
if ( wasThreadedRendering ! = config : : ThreadedRendering )
2021-07-09 14:28:28 +00:00
{
2021-09-29 08:22:58 +00:00
config : : ThreadedRendering = wasThreadedRendering ;
emu . stop ( ) ;
config : : ThreadedRendering = ! wasThreadedRendering ;
emu . start ( ) ;
2021-07-12 07:57:58 +00:00
}
bool geometryChanged = false ;
if ( rotate_screen ! = ( prevRotateScreen ^ rotate_game ) )
{
setRotation ( ) ;
geometryChanged = true ;
}
2021-07-13 11:45:01 +00:00
else
rotate_screen ^ = rotate_game ;
if ( rotate_game )
config : : Widescreen . override ( false ) ;
2021-07-12 07:57:58 +00:00
setFramebufferSize ( ) ;
if ( prevMaxFramebufferWidth < maxFramebufferWidth | | prevMaxFramebufferHeight < maxFramebufferHeight )
{
retro_system_av_info avinfo ;
setAVInfo ( avinfo ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO , & avinfo ) ;
2021-09-27 18:29:23 +00:00
rend_resize_renderer ( ) ;
2021-07-12 07:57:58 +00:00
}
else if ( prevFramebufferWidth ! = framebufferWidth | | prevFramebufferHeight ! = framebufferHeight | | geometryChanged )
{
retro_game_geometry geometry ;
setGameGeometry ( geometry ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_GEOMETRY , & geometry ) ;
2021-09-27 18:29:23 +00:00
rend_resize_renderer ( ) ;
2021-07-09 14:28:28 +00:00
}
}
2021-07-05 17:44:08 +00:00
}
void retro_run ( )
{
bool updated = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE , & updated ) & & updated )
update_variables ( false ) ;
if ( devices_need_refresh )
refresh_devices ( false ) ;
2021-07-13 16:51:40 +00:00
if ( config : : RendererType . isOpenGL ( ) )
glsm_ctl ( GLSM_CTL_STATE_BIND , nullptr ) ;
2021-09-29 08:22:58 +00:00
// On the first call, we start the emulator
if ( first_run )
2021-07-05 17:44:08 +00:00
{
2021-09-29 08:22:58 +00:00
emu . start ( ) ;
first_run = false ;
}
2021-07-05 17:44:08 +00:00
2021-09-29 08:22:58 +00:00
poll_cb ( ) ;
UpdateInputState ( ) ;
bool fastforward = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_FASTFORWARDING , & fastforward ) )
settings . input . fastForwardMode = fastforward ;
2021-07-05 17:44:08 +00:00
2021-09-29 08:22:58 +00:00
try {
if ( config : : ThreadedRendering )
2021-08-23 09:29:17 +00:00
{
2021-09-29 08:22:58 +00:00
// Render
is_dupe = true ;
for ( int i = 0 ; i < 5 & & is_dupe ; i + + )
is_dupe = ! emu . render ( ) ;
2021-08-03 08:05:09 +00:00
}
2021-09-29 08:22:58 +00:00
else
{
startTime = sh4_sched_now64 ( ) ;
emu . render ( ) ;
2021-08-03 08:05:09 +00:00
}
2021-09-29 08:22:58 +00:00
} catch ( const FlycastException & e ) {
ERROR_LOG ( COMMON , " %s " , e . what ( ) ) ;
gui_display_notification ( e . what ( ) , 5000 ) ;
environ_cb ( RETRO_ENVIRONMENT_SHUTDOWN , NULL ) ;
2021-07-05 17:44:08 +00:00
}
2021-07-13 16:51:40 +00:00
if ( config : : RendererType . isOpenGL ( ) )
glsm_ctl ( GLSM_CTL_STATE_UNBIND , nullptr ) ;
2021-07-08 18:09:09 +00:00
video_cb ( is_dupe ? 0 : RETRO_HW_FRAME_BUFFER_VALID , framebufferWidth , framebufferHeight , 0 ) ;
2021-07-13 16:51:40 +00:00
2021-07-05 17:44:08 +00:00
if ( ! config : : ThreadedRendering )
is_dupe = true ;
}
2021-09-30 12:24:17 +00:00
static bool loadGame ( )
2021-07-21 14:19:57 +00:00
{
mute_messages = true ;
try {
2021-09-30 12:24:17 +00:00
emu . loadGame ( game_data . c_str ( ) ) ;
2021-07-21 14:19:57 +00:00
} catch ( const FlycastException & e ) {
ERROR_LOG ( BOOT , " %s " , e . what ( ) ) ;
mute_messages = false ;
2021-08-03 08:05:09 +00:00
gui_display_notification ( e . what ( ) , 5000 ) ;
2021-07-21 14:19:57 +00:00
return false ;
}
mute_messages = false ;
return true ;
}
2021-07-05 17:44:08 +00:00
void retro_reset ( )
{
std : : lock_guard < std : : mutex > lock ( mtx_serialization ) ;
2021-09-29 08:22:58 +00:00
emu . unloadGame ( ) ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
config : : ScreenStretching = 100 ;
2021-09-30 12:24:17 +00:00
loadGame ( ) ;
2021-07-21 14:19:57 +00:00
if ( rotate_game )
config : : Widescreen . override ( false ) ;
config : : Rotate90 = false ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
setFramebufferSize ( ) ;
retro_game_geometry geometry ;
setGameGeometry ( geometry ) ;
environ_cb ( RETRO_ENVIRONMENT_SET_GEOMETRY , & geometry ) ;
2021-07-15 13:43:10 +00:00
blankVmus ( ) ;
2021-07-12 07:57:58 +00:00
2021-09-29 08:22:58 +00:00
emu . start ( ) ;
2021-07-05 17:44:08 +00:00
}
# if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
static void context_reset ( )
{
INFO_LOG ( RENDERER , " context_reset. " ) ;
gl_ctx_resetting = false ;
glsm_ctl ( GLSM_CTL_STATE_CONTEXT_RESET , NULL ) ;
glsm_ctl ( GLSM_CTL_STATE_SETUP , NULL ) ;
rend_term_renderer ( ) ;
theGLContext . Init ( ) ;
rend_init_renderer ( ) ;
2021-09-27 18:29:23 +00:00
rend_resize_renderer ( ) ;
2021-07-05 17:44:08 +00:00
}
static void context_destroy ( )
{
gl_ctx_resetting = true ;
rend_term_renderer ( ) ;
glsm_ctl ( GLSM_CTL_STATE_CONTEXT_DESTROY , NULL ) ;
}
# endif
static void extract_directory ( char * buf , const char * path , size_t size )
{
strncpy ( buf , path , size - 1 ) ;
buf [ size - 1 ] = ' \0 ' ;
char * base = strrchr ( buf , ' / ' ) ;
if ( ! base )
base = strrchr ( buf , ' \\ ' ) ;
if ( base )
* base = ' \0 ' ;
else
buf [ 0 ] = ' \0 ' ;
}
static uint32_t map_gamepad_button ( unsigned device , unsigned id )
{
static const uint32_t dc_joymap [ ] =
{
/* JOYPAD_B */ DC_BTN_A ,
/* JOYPAD_Y */ DC_BTN_X ,
/* JOYPAD_SELECT */ 0 ,
/* JOYPAD_START */ DC_BTN_START ,
/* JOYPAD_UP */ DC_DPAD_UP ,
/* JOYPAD_DOWN */ DC_DPAD_DOWN ,
/* JOYPAD_LEFT */ DC_DPAD_LEFT ,
/* JOYPAD_RIGHT */ DC_DPAD_RIGHT ,
/* JOYPAD_A */ DC_BTN_B ,
/* JOYPAD_X */ DC_BTN_Y ,
} ;
static const uint32_t dc_lg_joymap [ ] =
{
/* deprecated */ 0 ,
/* deprecated */ 0 ,
/* LIGHTGUN_TRIGGER */ DC_BTN_A ,
/* LIGHTGUN_AUX_A */ DC_BTN_B ,
/* LIGHTGUN_AUX_B */ 0 ,
/* deprecated */ 0 ,
/* LIGHTGUN_START */ DC_BTN_START ,
/* LIGHTGUN_SELECT */ 0 ,
/* LIGHTGUN_AUX_C */ 0 ,
/* LIGHTGUN_UP */ DC_DPAD_UP ,
/* LIGHTGUN_DOWN */ DC_DPAD_DOWN ,
/* LIGHTGUN_LEFT */ DC_DPAD_LEFT ,
/* LIGHTGUN_RIGHT */ DC_DPAD_RIGHT ,
} ;
static const uint32_t aw_joymap [ ] =
{
/* JOYPAD_B */ AWAVE_BTN0_KEY , /* BTN1 */
/* JOYPAD_Y */ AWAVE_BTN2_KEY , /* BTN3 */
/* JOYPAD_SELECT */ AWAVE_COIN_KEY ,
/* JOYPAD_START */ AWAVE_START_KEY ,
/* JOYPAD_UP */ AWAVE_UP_KEY ,
/* JOYPAD_DOWN */ AWAVE_DOWN_KEY ,
/* JOYPAD_LEFT */ AWAVE_LEFT_KEY ,
/* JOYPAD_RIGHT */ AWAVE_RIGHT_KEY ,
/* JOYPAD_A */ AWAVE_BTN1_KEY , /* BTN2 */
/* JOYPAD_X */ AWAVE_BTN3_KEY , /* BTN4 */
/* JOYPAD_L */ 0 ,
/* JOYPAD_R */ AWAVE_BTN4_KEY , /* BTN5 */
/* JOYPAD_L2 */ 0 ,
/* JOYPAD_R2 */ 0 ,
/* JOYPAD_L3 */ AWAVE_TEST_KEY ,
/* JOYPAD_R3 */ AWAVE_SERVICE_KEY ,
} ;
static const uint32_t aw_lg_joymap [ ] =
{
/* deprecated */ 0 ,
/* deprecated */ 0 ,
/* LIGHTGUN_TRIGGER */ AWAVE_TRIGGER_KEY ,
/* LIGHTGUN_AUX_A */ AWAVE_BTN0_KEY ,
/* LIGHTGUN_AUX_B */ AWAVE_BTN1_KEY ,
/* deprecated */ 0 ,
/* LIGHTGUN_START */ AWAVE_START_KEY ,
/* LIGHTGUN_SELECT */ AWAVE_COIN_KEY ,
/* LIGHTGUN_AUX_C */ AWAVE_BTN2_KEY ,
/* LIGHTGUN_UP */ AWAVE_UP_KEY ,
/* LIGHTGUN_DOWN */ AWAVE_DOWN_KEY ,
/* LIGHTGUN_LEFT */ AWAVE_LEFT_KEY ,
/* LIGHTGUN_RIGHT */ AWAVE_RIGHT_KEY ,
} ;
static const uint32_t nao_joymap [ ] =
{
/* JOYPAD_B */ NAOMI_BTN0_KEY , /* BTN1 */
/* JOYPAD_Y */ NAOMI_BTN2_KEY , /* BTN3 */
/* JOYPAD_SELECT */ NAOMI_COIN_KEY ,
/* JOYPAD_START */ NAOMI_START_KEY ,
/* JOYPAD_UP */ NAOMI_UP_KEY ,
/* JOYPAD_DOWN */ NAOMI_DOWN_KEY ,
/* JOYPAD_LEFT */ NAOMI_LEFT_KEY ,
/* JOYPAD_RIGHT */ NAOMI_RIGHT_KEY ,
/* JOYPAD_A */ NAOMI_BTN1_KEY , /* BTN2 */
/* JOYPAD_X */ NAOMI_BTN3_KEY , /* BTN4 */
/* JOYPAD_L */ NAOMI_BTN5_KEY , /* BTN6 */
/* JOYPAD_R */ NAOMI_BTN4_KEY , /* BTN5 */
/* JOYPAD_L2 */ NAOMI_BTN7_KEY , /* BTN8 */
/* JOYPAD_R2 */ NAOMI_BTN6_KEY , /* BTN7 */
/* JOYPAD_L3 */ NAOMI_TEST_KEY ,
/* JOYPAD_R3 */ NAOMI_SERVICE_KEY ,
} ;
static const uint32_t nao_lg_joymap [ ] =
{
/* deprecated */ 0 ,
/* deprecated */ 0 ,
/* LIGHTGUN_TRIGGER */ NAOMI_BTN0_KEY ,
/* LIGHTGUN_AUX_A */ NAOMI_BTN1_KEY ,
/* LIGHTGUN_AUX_B */ NAOMI_BTN2_KEY ,
/* deprecated */ 0 ,
/* LIGHTGUN_START */ NAOMI_START_KEY ,
/* LIGHTGUN_SELECT */ NAOMI_COIN_KEY ,
/* LIGHTGUN_AUX_C */ NAOMI_BTN3_KEY ,
/* LIGHTGUN_UP */ NAOMI_UP_KEY ,
/* LIGHTGUN_DOWN */ NAOMI_DOWN_KEY ,
/* LIGHTGUN_LEFT */ NAOMI_LEFT_KEY ,
/* LIGHTGUN_RIGHT */ NAOMI_RIGHT_KEY ,
} ;
const uint32_t * joymap ;
size_t joymap_size ;
switch ( settings . platform . system )
{
case DC_PLATFORM_DREAMCAST :
case DC_PLATFORM_DEV_UNIT :
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
joymap = dc_joymap ;
joymap_size = ARRAY_SIZE ( dc_joymap ) ;
break ;
case RETRO_DEVICE_LIGHTGUN :
joymap = dc_lg_joymap ;
joymap_size = ARRAY_SIZE ( dc_lg_joymap ) ;
break ;
default :
return 0 ;
}
break ;
case DC_PLATFORM_NAOMI :
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
joymap = nao_joymap ;
joymap_size = ARRAY_SIZE ( nao_joymap ) ;
break ;
case RETRO_DEVICE_LIGHTGUN :
joymap = nao_lg_joymap ;
joymap_size = ARRAY_SIZE ( nao_lg_joymap ) ;
break ;
default :
return 0 ;
}
break ;
case DC_PLATFORM_ATOMISWAVE :
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
joymap = aw_joymap ;
joymap_size = ARRAY_SIZE ( aw_joymap ) ;
break ;
case RETRO_DEVICE_LIGHTGUN :
joymap = aw_lg_joymap ;
joymap_size = ARRAY_SIZE ( aw_lg_joymap ) ;
break ;
default :
return 0 ;
}
break ;
default :
return 0 ;
}
if ( id > = joymap_size )
return 0 ;
uint32_t mapped = joymap [ id ] ;
// Hack to bind Button 9 instead of Service when not used
if ( id = = RETRO_DEVICE_ID_JOYPAD_R3 & & device = = RETRO_DEVICE_JOYPAD & & settings . platform . system = = DC_PLATFORM_NAOMI & & ! allow_service_buttons )
mapped = NAOMI_BTN8_KEY ;
return mapped ;
}
static const char * get_button_name ( unsigned device , unsigned id , const char * default_name )
{
if ( NaomiGameInputs = = NULL )
return default_name ;
uint32_t mask = map_gamepad_button ( device , id ) ;
if ( mask = = 0 )
return NULL ;
for ( int i = 0 ; NaomiGameInputs - > buttons [ i ] . source ! = 0 ; i + + )
if ( NaomiGameInputs - > buttons [ i ] . source = = mask )
return NaomiGameInputs - > buttons [ i ] . name ;
return NULL ;
}
static const char * get_axis_name ( unsigned index , const char * default_name )
{
if ( NaomiGameInputs = = NULL )
return default_name ;
for ( int i = 0 ; NaomiGameInputs - > axes [ i ] . name ! = NULL ; i + + )
if ( NaomiGameInputs - > axes [ i ] . axis = = index )
return NaomiGameInputs - > axes [ i ] . name ;
return NULL ;
}
static void set_input_descriptors ( )
{
struct retro_input_descriptor desc [ 22 * 4 + 1 ] ;
int descriptor_index = 0 ;
if ( settings . platform . system = = DC_PLATFORM_NAOMI | | settings . platform . system = = DC_PLATFORM_ATOMISWAVE )
{
const char * name ;
for ( unsigned i = 0 ; i < MAPLE_PORTS ; i + + )
{
switch ( config : : MapleMainDevices [ i ] )
{
case MDT_LightGun :
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT , " D-Pad Left " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP , " D-Pad Up " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN , " D-Pad Down " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT , " D-Pad Right " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER , " Trigger " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_A , " Button 1 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_AUX_A , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_B , " Button 2 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_AUX_B , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_C , " Button 3 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_AUX_C , name } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_RELOAD , " Reload " } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_SELECT , " Coin " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_SELECT , name } ;
name = get_button_name ( RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_START , " Start " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_START , name } ;
break ;
case MDT_SegaController :
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_B , " Button 1 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_A , " Button 2 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_Y , " Button 3 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_X , " Button 4 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_R , " Button 5 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_L , " Button 6 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_R2 , " Button 7 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R2 , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_L2 , " Button 8 " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L2 , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_START , " Start " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_SELECT , " Coin " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_L3 , " Test " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L3 , name } ;
name = get_button_name ( RETRO_DEVICE_JOYPAD , RETRO_DEVICE_ID_JOYPAD_R3 , " Service " ) ;
if ( name ! = NULL )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R3 , name } ;
name = get_axis_name ( 0 , " Axis 1 " ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_X , name } ;
name = get_axis_name ( 1 , " Axis 2 " ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_Y , name } ;
name = get_axis_name ( 2 , " Axis 3 " ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_RIGHT , RETRO_DEVICE_ID_ANALOG_X , name } ;
name = get_axis_name ( 3 , " Axis 4 " ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_RIGHT , RETRO_DEVICE_ID_ANALOG_Y , name } ;
name = get_axis_name ( 4 , NULL ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R2 , name } ;
name = get_axis_name ( 5 , NULL ) ;
if ( name ! = NULL & & name [ 0 ] ! = ' \0 ' )
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L2 , name } ;
break ;
2021-07-20 17:21:11 +00:00
default :
break ;
2021-07-05 17:44:08 +00:00
}
}
}
else
{
for ( unsigned i = 0 ; i < MAPLE_PORTS ; i + + )
{
switch ( config : : MapleMainDevices [ i ] )
{
case MDT_SegaController :
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " D-Pad Left " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " D-Pad Up " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " D-Pad Down " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " D-Pad Right " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_B , " A " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_A , " B " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_X , " Y " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " X " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_L2 , " L Trigger " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_R2 , " R Trigger " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_X , " Analog X " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_Y , " Analog Y " } ;
break ;
case MDT_TwinStick :
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " L-Stick Left " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " L-Stick Up " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " L-Stick Down " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " L-Stick Right " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_B , " R-Stick Down " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_A , " R-Stick Right " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_X , " R-Stick Up " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " R-Stick Left " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_L , " L Turbo " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_R , " R Turbo " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_L2 , " L Trigger " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_R2 , " R Trigger " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_SELECT , " Special " } ;
break ;
case MDT_AsciiStick :
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_LEFT , " Stick Left " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_UP , " Stick Up " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_DOWN , " Stick Down " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_RIGHT , " Stick Right " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_B , " A " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_A , " B " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_X , " Y " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_Y , " X " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_L , " C " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_R , " Z " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_START , " Start " } ;
break ;
case MDT_LightGun :
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT , " D-Pad Left " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP , " D-Pad Up " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN , " D-Pad Down " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT , " D-Pad Right " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER , " A " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_START , " Start " } ;
desc [ descriptor_index + + ] = { i , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_AUX_A , " B " } ;
break ;
2021-07-20 17:21:11 +00:00
default :
break ;
2021-07-05 17:44:08 +00:00
}
}
}
desc [ descriptor_index + + ] = { 0 } ;
environ_cb ( RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS , desc ) ;
}
static void extract_basename ( char * buf , const char * path , size_t size )
{
const char * base = strrchr ( path , slash ) ;
if ( ! base )
base = path ;
if ( * base = = slash )
base + + ;
strncpy ( buf , base , size - 1 ) ;
buf [ size - 1 ] = ' \0 ' ;
}
static void remove_extension ( char * buf , const char * path , size_t size )
{
char * base ;
strncpy ( buf , path , size - 1 ) ;
buf [ size - 1 ] = ' \0 ' ;
base = strrchr ( buf , ' . ' ) ;
if ( base )
* base = ' \0 ' ;
}
# ifdef HAVE_VULKAN
static VulkanContext theVulkanContext ;
static void retro_vk_context_reset ( )
{
retro_hw_render_interface * vulkan ;
if ( ! environ_cb ( RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE , ( void * * ) & vulkan ) | | ! vulkan )
{
ERROR_LOG ( RENDERER , " Get Vulkan HW interface failed " ) ;
return ;
}
theVulkanContext . Init ( ( retro_hw_render_interface_vulkan * ) vulkan ) ;
2021-07-08 10:47:00 +00:00
rend_term_renderer ( ) ;
rend_init_renderer ( ) ;
2021-09-27 18:29:23 +00:00
rend_resize_renderer ( ) ;
2021-07-05 17:44:08 +00:00
}
static void retro_vk_context_destroy ( )
{
rend_term_renderer ( ) ;
theVulkanContext . Term ( ) ;
}
static bool set_vulkan_hw_render ( )
{
2021-09-10 13:32:13 +00:00
retro_hw_render_callback hw_render { } ;
2021-07-05 17:44:08 +00:00
hw_render . context_type = RETRO_HW_CONTEXT_VULKAN ;
hw_render . version_major = VK_API_VERSION_1_0 ;
hw_render . version_minor = 0 ;
hw_render . context_reset = retro_vk_context_reset ;
hw_render . context_destroy = retro_vk_context_destroy ;
hw_render . debug_context = false ;
if ( ! environ_cb ( RETRO_ENVIRONMENT_SET_HW_RENDER , & hw_render ) )
return false ;
static const struct retro_hw_render_context_negotiation_interface_vulkan negotiation_interface = {
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN ,
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION ,
VkGetApplicationInfo ,
VkCreateDevice ,
nullptr ,
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE , ( void * ) & negotiation_interface ) ;
if ( config : : RendererType = = RenderType : : OpenGL )
config : : RendererType = RenderType : : Vulkan ;
else if ( config : : RendererType = = RenderType : : OpenGL_OIT )
config : : RendererType = RenderType : : Vulkan_OIT ;
config : : RendererType . commit ( ) ;
return true ;
}
# else
static bool set_vulkan_hw_render ( )
{
return false ;
}
# endif
static bool set_opengl_hw_render ( u32 preferred )
{
# if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
glsm_ctx_params_t params = { 0 } ;
params . context_reset = context_reset ;
params . context_destroy = context_destroy ;
params . environ_cb = environ_cb ;
# ifdef TARGET_NO_STENCIL
params . stencil = false ;
# else
params . stencil = true ;
# endif
params . imm_vbo_draw = NULL ;
params . imm_vbo_disable = NULL ;
2021-08-15 08:50:53 +00:00
# if defined(__APPLE__) && defined(HAVE_OPENGL)
preferred = RETRO_HW_CONTEXT_OPENGL_CORE ;
# endif
2021-07-05 17:44:08 +00:00
# ifdef HAVE_OIT
if ( config : : RendererType = = RenderType : : OpenGL_OIT )
{
params . context_type = ( retro_hw_context_type ) preferred ;
if ( preferred = = RETRO_HW_CONTEXT_OPENGL )
{
// There are some weirdness with RA's gl context's versioning :
// - any value above 3.0 won't provide a valid context, while the GLSM_CTL_STATE_CONTEXT_INIT call returns true...
// - the only way to overwrite previously set version with zero values is to set them directly in hw_render, otherwise they are ignored (see glsm_state_ctx_init logic)
2021-07-09 11:10:30 +00:00
// FIXME what's the point of this?
2021-07-05 17:44:08 +00:00
retro_hw_render_callback hw_render ;
hw_render . version_major = 3 ;
hw_render . version_minor = 0 ;
}
else
{
params . major = 4 ;
params . minor = 3 ;
}
}
else
2021-07-09 11:10:30 +00:00
# endif
2021-07-05 17:44:08 +00:00
{
params . context_type = ( retro_hw_context_type ) preferred ;
params . major = 3 ;
2021-07-09 11:10:30 +00:00
params . minor = preferred = = RETRO_HW_CONTEXT_OPENGL_CORE ? 2 : 0 ;
2021-07-06 11:22:54 +00:00
config : : RendererType = RenderType : : OpenGL ;
2021-07-09 11:10:30 +00:00
config : : RendererType . commit ( ) ;
2021-07-05 17:44:08 +00:00
}
if ( glsm_ctl ( GLSM_CTL_STATE_CONTEXT_INIT , & params ) )
return true ;
# if defined(HAVE_GL3)
params . context_type = ( retro_hw_context_type ) preferred ;
params . major = 3 ;
params . minor = 0 ;
# else
params . context_type = ( retro_hw_context_type ) preferred ;
params . major = 0 ;
params . minor = 0 ;
# endif
2021-07-06 11:22:54 +00:00
config : : RendererType = RenderType : : OpenGL ;
config : : RendererType . commit ( ) ;
2021-07-05 17:44:08 +00:00
return glsm_ctl ( GLSM_CTL_STATE_CONTEXT_INIT , & params ) ;
# else
return false ;
# endif
}
// Loading/unloading games
bool retro_load_game ( const struct retro_game_info * game )
{
NOTICE_LOG ( BOOT , " retro_load_game: %s " , game - > path ) ;
extract_basename ( g_base_name , game - > path , sizeof ( g_base_name ) ) ;
extract_directory ( game_dir , game - > path , sizeof ( game_dir ) ) ;
// Storing rom dir for later use
snprintf ( g_roms_dir , sizeof ( g_roms_dir ) , " %s%c " , game_dir , slash ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE , & rumble ) & & log_cb )
log_cb ( RETRO_LOG_DEBUG , " Rumble interface supported! \n " ) ;
const char * dir = NULL ;
if ( ! ( environ_cb ( RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY , & dir ) & & dir ) )
dir = game_dir ;
snprintf ( game_dir , sizeof ( game_dir ) , " %s%cdc%c " , dir , slash , slash ) ;
snprintf ( game_dir_no_slash , sizeof ( game_dir_no_slash ) , " %s%cdc " , dir , slash ) ;
// Per-content VMU additions START
// > Get save directory
const char * vmu_dir = NULL ;
if ( ! ( environ_cb ( RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY , & vmu_dir ) & & vmu_dir ) )
vmu_dir = game_dir ;
snprintf ( vmu_dir_no_slash , sizeof ( vmu_dir_no_slash ) , " %s " , vmu_dir ) ;
// > Get content name
remove_extension ( content_name , g_base_name , sizeof ( content_name ) ) ;
if ( content_name [ 0 ] = = ' \0 ' )
snprintf ( content_name , sizeof ( content_name ) , " vmu_save " ) ;
// Per-content VMU additions END
update_variables ( true ) ;
char * ext = strrchr ( g_base_name , ' . ' ) ;
{
/* Check for extension .lst, .bin, .dat or .zip. If found, we will set the system type
* automatically to Naomi or AtomisWave . */
if ( ext )
{
log_cb ( RETRO_LOG_INFO , " File extension is: %s \n " , ext ) ;
if ( ! strcmp ( " .lst " , ext )
| | ! strcmp ( " .bin " , ext ) | | ! strcmp ( " .BIN " , ext )
| | ! strcmp ( " .dat " , ext ) | | ! strcmp ( " .DAT " , ext )
| | ! strcmp ( " .zip " , ext ) | | ! strcmp ( " .ZIP " , ext )
| | ! strcmp ( " .7z " , ext ) | | ! strcmp ( " .7Z " , ext ) )
{
settings . platform . system = naomi_cart_GetPlatform ( game - > path ) ;
// Users should use the superior format instead, let's warn them
if ( ! strcmp ( " .lst " , ext )
| | ! strcmp ( " .bin " , ext ) | | ! strcmp ( " .BIN " , ext )
| | ! strcmp ( " .dat " , ext ) | | ! strcmp ( " .DAT " , ext ) )
{
struct retro_message msg ;
// Sadly, this callback is only able to display short messages, so we can't give proper explanations...
msg . msg = " Please upgrade to MAME romsets or expect issues " ;
msg . frames = 1200 ;
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE , & msg ) ;
}
}
// If m3u playlist found load the paths into array
else if ( ! strcmp ( " .m3u " , ext ) | | ! strcmp ( " .M3U " , ext ) )
{
if ( ! read_m3u ( game - > path ) )
{
if ( log_cb )
log_cb ( RETRO_LOG_ERROR , " %s \n " , " [libretro]: failed to read m3u file ... \n " ) ;
return false ;
}
}
}
}
2021-07-16 15:41:40 +00:00
// System may have changed - have to update hidden core options
set_variable_visibility ( ) ;
2021-07-05 17:44:08 +00:00
if ( game - > path [ 0 ] = = ' \0 ' )
{
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST )
boot_to_bios = true ;
else
return false ;
}
if ( settings . platform . system ! = DC_PLATFORM_DREAMCAST )
boot_to_bios = false ;
2021-07-10 16:00:21 +00:00
if ( boot_to_bios )
2021-09-30 12:24:17 +00:00
game_data . clear ( ) ;
2021-07-12 07:57:58 +00:00
// if an m3u file was loaded, disk_paths will already be populated so load the game from there
else if ( disk_paths . size ( ) > 0 )
2021-07-05 17:44:08 +00:00
{
2021-07-12 07:57:58 +00:00
disk_index = 0 ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
// Attempt to set initial disk index
if ( disk_paths . size ( ) > 1
& & disk_initial_index > 0
& & disk_initial_index < disk_paths . size ( )
& & disk_paths [ disk_initial_index ] . compare ( disk_initial_path ) = = 0 )
disk_index = disk_initial_index ;
2021-07-05 17:44:08 +00:00
2021-09-30 12:24:17 +00:00
game_data = disk_paths [ disk_index ] ;
2021-07-12 07:57:58 +00:00
}
else
{
char disk_label [ PATH_MAX ] ;
disk_label [ 0 ] = ' \0 ' ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
disk_paths . push_back ( game - > path ) ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
fill_short_pathname_representation ( disk_label , game - > path , sizeof ( disk_label ) ) ;
disk_labels . push_back ( disk_label ) ;
2021-07-05 17:44:08 +00:00
2021-09-30 12:24:17 +00:00
game_data = game - > path ;
2021-07-05 17:44:08 +00:00
}
{
char data_dir [ 1024 ] ;
snprintf ( data_dir , sizeof ( data_dir ) , " %s%s " , game_dir , " data " ) ;
INFO_LOG ( COMMON , " Creating dir: %s " , data_dir ) ;
struct stat buf ;
if ( stat ( data_dir , & buf ) < 0 )
{
path_mkdir ( data_dir ) ;
}
}
u32 preferred ;
if ( ! environ_cb ( RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER , & preferred ) )
preferred = RETRO_HW_CONTEXT_DUMMY ;
bool foundRenderApi = false ;
if ( preferred = = RETRO_HW_CONTEXT_OPENGL | | preferred = = RETRO_HW_CONTEXT_OPENGL_CORE
| | preferred = = RETRO_HW_CONTEXT_OPENGLES2 | | preferred = = RETRO_HW_CONTEXT_OPENGLES3
| | preferred = = RETRO_HW_CONTEXT_OPENGLES_VERSION )
{
foundRenderApi = set_opengl_hw_render ( preferred ) ;
}
else if ( preferred = = RETRO_HW_CONTEXT_VULKAN )
{
foundRenderApi = set_vulkan_hw_render ( ) ;
}
else
{
// fallback when not supported (or auto-switching disabled), let's try all supported drivers
foundRenderApi = set_vulkan_hw_render ( ) ;
# if defined(HAVE_OPENGLES)
if ( ! foundRenderApi )
foundRenderApi = set_opengl_hw_render ( RETRO_HW_CONTEXT_OPENGLES3 ) ;
if ( ! foundRenderApi )
foundRenderApi = set_opengl_hw_render ( RETRO_HW_CONTEXT_OPENGLES2 ) ;
# else
if ( ! foundRenderApi )
foundRenderApi = set_opengl_hw_render ( RETRO_HW_CONTEXT_OPENGL_CORE ) ;
if ( ! foundRenderApi )
foundRenderApi = set_opengl_hw_render ( RETRO_HW_CONTEXT_OPENGL ) ;
# endif
}
if ( ! foundRenderApi )
return false ;
if ( settings . platform . system ! = DC_PLATFORM_DREAMCAST )
{
2021-07-20 08:06:44 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY , & dir )
& & dir ! = nullptr
& & strcmp ( dir , g_roms_dir ) ! = 0 )
{
static char save_dir [ PATH_MAX ] ;
snprintf ( save_dir , sizeof ( save_dir ) , " %s%creicast%c " , dir , slash , slash ) ;
2021-07-05 17:44:08 +00:00
struct stat buf ;
if ( stat ( save_dir , & buf ) < 0 )
{
DEBUG_LOG ( BOOT , " Creating dir: %s " , save_dir ) ;
path_mkdir ( save_dir ) ;
}
2021-07-20 08:06:44 +00:00
arcadeFlashPath = std : : string ( save_dir ) + g_base_name ;
2021-07-05 17:44:08 +00:00
} else {
2021-07-20 08:06:44 +00:00
arcadeFlashPath = std : : string ( g_roms_dir ) + g_base_name ;
2021-07-05 17:44:08 +00:00
}
2021-07-20 08:06:44 +00:00
INFO_LOG ( BOOT , " Setting flash base path to %s " , arcadeFlashPath . c_str ( ) ) ;
2021-07-05 17:44:08 +00:00
}
2021-07-12 07:57:58 +00:00
config : : ScreenStretching = 100 ;
2021-09-30 12:24:17 +00:00
if ( ! loadGame ( ) )
2021-07-21 14:19:57 +00:00
return false ;
2021-07-05 17:44:08 +00:00
2021-07-12 07:57:58 +00:00
rotate_game = config : : Rotate90 ;
if ( rotate_game )
2021-07-07 07:48:10 +00:00
config : : Widescreen . override ( false ) ;
2021-07-12 07:57:58 +00:00
config : : Rotate90 = false ; // actual framebuffer rotation is done by frontend
setRotation ( ) ;
setFramebufferSize ( ) ;
2021-07-07 07:48:10 +00:00
2021-07-05 17:44:08 +00:00
if ( devices_need_refresh )
refresh_devices ( true ) ;
return true ;
}
bool retro_load_game_special ( unsigned game_type , const struct retro_game_info * info , size_t num_info )
{
return false ;
}
void retro_unload_game ( )
{
INFO_LOG ( COMMON , " Flycast unloading game " ) ;
2021-07-20 08:06:44 +00:00
frontend_clear_thread_waits_cb ( 1 , nullptr ) ;
2021-09-29 08:22:58 +00:00
emu . stop ( ) ;
2021-07-20 08:06:44 +00:00
frontend_clear_thread_waits_cb ( 0 , nullptr ) ;
2021-09-30 12:24:17 +00:00
game_data . clear ( ) ;
2021-07-12 07:57:58 +00:00
disk_paths . clear ( ) ;
disk_labels . clear ( ) ;
2021-07-15 13:43:10 +00:00
blankVmus ( ) ;
2021-07-05 17:44:08 +00:00
2021-09-29 08:22:58 +00:00
emu . term ( ) ;
2021-07-05 17:44:08 +00:00
}
// Memory/Serialization
void * retro_get_memory_data ( unsigned type )
{
if ( type = = RETRO_MEMORY_SYSTEM_RAM )
return mem_b . data ;
return nullptr ;
}
size_t retro_get_memory_size ( unsigned type )
{
if ( type = = RETRO_MEMORY_SYSTEM_RAM )
return mem_b . size ;
return 0 ;
}
2021-07-11 15:42:30 +00:00
size_t retro_serialize_size ( )
{
DEBUG_LOG ( SAVESTATE , " retro_serialize_size " ) ;
std : : lock_guard < std : : mutex > lock ( mtx_serialization ) ;
2021-09-29 08:22:58 +00:00
emu . stop ( ) ;
2021-07-11 15:42:30 +00:00
unsigned int total_size = 0 ;
void * data = nullptr ;
dc_serialize ( & data , & total_size ) ;
2021-09-29 08:22:58 +00:00
emu . start ( ) ;
2021-07-11 15:42:30 +00:00
return total_size ;
}
2021-07-05 17:44:08 +00:00
bool retro_serialize ( void * data , size_t size )
{
2021-07-11 15:42:30 +00:00
DEBUG_LOG ( SAVESTATE , " retro_serialize %d bytes " , ( int ) size ) ;
2021-07-05 17:44:08 +00:00
std : : lock_guard < std : : mutex > lock ( mtx_serialization ) ;
2021-09-29 08:22:58 +00:00
emu . stop ( ) ;
2021-07-05 17:44:08 +00:00
unsigned int total_size = 0 ;
bool result = dc_serialize ( & data , & total_size ) ;
2021-09-29 08:22:58 +00:00
emu . start ( ) ;
2021-07-05 17:44:08 +00:00
return result ;
}
bool retro_unserialize ( const void * data , size_t size )
{
2021-07-11 15:42:30 +00:00
DEBUG_LOG ( SAVESTATE , " retro_unserialize " ) ;
2021-09-29 08:22:58 +00:00
std : : lock_guard < std : : mutex > lock ( mtx_serialization ) ;
emu . stop ( ) ;
2021-07-05 17:44:08 +00:00
2021-07-10 15:39:16 +00:00
bool result = dc_loadstate ( & data , size ) ;
2021-07-05 17:44:08 +00:00
2021-09-29 08:22:58 +00:00
emu . start ( ) ;
2021-07-05 17:44:08 +00:00
return result ;
}
// Cheats
void retro_cheat_reset ( )
{
// Nothing to do here
}
void retro_cheat_set ( unsigned unused , bool unused1 , const char * unused2 )
{
// Nothing to do here
}
// Get info
const char * retro_get_system_directory ( )
{
const char * dir ;
environ_cb ( RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY , & dir ) ;
return dir ? dir : " . " ;
}
void retro_get_system_info ( struct retro_system_info * info )
{
info - > library_name = " Flycast " ;
# ifndef GIT_VERSION
2021-07-13 11:45:01 +00:00
# define GIT_VERSION "undefined"
2021-07-05 17:44:08 +00:00
# endif
2021-07-13 11:45:01 +00:00
info - > library_version = GIT_VERSION ;
info - > valid_extensions = " chd|cdi|elf|cue|gdi|lst|bin|dat|zip|7z|m3u " ;
2021-07-05 17:44:08 +00:00
info - > need_fullpath = true ;
info - > block_extract = true ;
}
2021-07-12 07:57:58 +00:00
void retro_get_system_av_info ( retro_system_av_info * info )
2021-07-05 17:44:08 +00:00
{
NOTICE_LOG ( RENDERER , " retro_get_system_av_info: Res=%d " , ( int ) config : : RenderResolution ) ;
2021-07-07 07:48:10 +00:00
if ( cheatManager . isWidescreen ( ) )
{
2021-07-12 07:57:58 +00:00
retro_message msg ;
2021-07-05 17:44:08 +00:00
msg . msg = " Widescreen cheat activated " ;
msg . frames = 120 ;
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE , & msg ) ;
2021-07-07 07:48:10 +00:00
}
2021-07-12 07:57:58 +00:00
setAVInfo ( * info ) ;
2021-07-05 17:44:08 +00:00
}
unsigned retro_get_region ( )
{
return config : : Broadcast = = 0 ? RETRO_REGION_NTSC : RETRO_REGION_PAL ;
}
// Controller
void retro_set_controller_port_device ( unsigned in_port , unsigned device )
{
2021-07-20 17:21:11 +00:00
if ( device_type [ in_port ] ! = ( int ) device & & in_port < MAPLE_PORTS )
2021-07-05 17:44:08 +00:00
{
devices_need_refresh = true ;
device_type [ in_port ] = device ;
switch ( device )
{
case RETRO_DEVICE_JOYPAD :
config : : MapleMainDevices [ in_port ] = MDT_SegaController ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = MDT_SegaVMU ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
}
break ;
case RETRO_DEVICE_TWINSTICK :
case RETRO_DEVICE_TWINSTICK_SATURN :
config : : MapleMainDevices [ in_port ] = MDT_TwinStick ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
case RETRO_DEVICE_ASCIISTICK :
config : : MapleMainDevices [ in_port ] = MDT_AsciiStick ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
case RETRO_DEVICE_KEYBOARD :
config : : MapleMainDevices [ in_port ] = MDT_Keyboard ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = MDT_None ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
case RETRO_DEVICE_MOUSE :
config : : MapleMainDevices [ in_port ] = MDT_Mouse ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = MDT_None ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
case RETRO_DEVICE_LIGHTGUN :
config : : MapleMainDevices [ in_port ] = MDT_LightGun ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = enable_purupuru ? MDT_PurupuruPack : MDT_SegaVMU ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
default :
config : : MapleMainDevices [ in_port ] = MDT_None ;
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST ) {
config : : MapleExpansionDevices [ in_port ] [ 0 ] = MDT_None ;
config : : MapleExpansionDevices [ in_port ] [ 1 ] = MDT_None ;
}
break ;
}
}
}
static void refresh_devices ( bool first_startup )
{
devices_need_refresh = false ;
set_input_descriptors ( ) ;
if ( ! first_startup )
{
if ( settings . platform . system = = DC_PLATFORM_DREAMCAST )
maple_ReconnectDevices ( ) ;
if ( rumble . set_rumble_state )
{
for ( int i = 0 ; i < MAPLE_PORTS ; i + + )
{
rumble . set_rumble_state ( i , RETRO_RUMBLE_STRONG , 0 ) ;
rumble . set_rumble_state ( i , RETRO_RUMBLE_WEAK , 0 ) ;
}
}
}
else
{
mcfg_DestroyDevices ( ) ;
mcfg_CreateDevices ( ) ;
}
}
// API version (to detect version mismatch)
unsigned retro_api_version ( )
{
return RETRO_API_VERSION ;
}
2021-07-07 11:12:16 +00:00
void retro_rend_present ( )
2021-07-05 17:44:08 +00:00
{
if ( ! config : : ThreadedRendering )
{
is_dupe = false ;
2021-07-07 11:12:16 +00:00
sh4_cpu . Stop ( ) ;
2021-07-05 17:44:08 +00:00
}
}
2021-07-07 11:12:16 +00:00
2021-07-05 17:44:08 +00:00
static uint32_t get_time_ms ( )
{
return ( uint32_t ) ( os_GetSeconds ( ) * 1000.0 ) ;
}
static void get_analog_stick ( retro_input_state_t input_state_cb ,
int player_index ,
int stick ,
s8 * p_analog_x ,
s8 * p_analog_y )
{
int analog_x , analog_y ;
analog_x = input_state_cb ( player_index , RETRO_DEVICE_ANALOG , stick , RETRO_DEVICE_ID_ANALOG_X ) ;
analog_y = input_state_cb ( player_index , RETRO_DEVICE_ANALOG , stick , RETRO_DEVICE_ID_ANALOG_Y ) ;
// Analog stick deadzone (borrowed code from parallel-n64 core)
if ( astick_deadzone > 0 )
{
static const int ASTICK_MAX = 0x8000 ;
// Convert cartesian coordinate analog stick to polar coordinates
double radius = sqrt ( analog_x * analog_x + analog_y * analog_y ) ;
double angle = atan2 ( analog_y , analog_x ) ;
if ( radius > astick_deadzone )
{
// Re-scale analog stick range to negate deadzone (makes slow movements possible)
radius = ( radius - astick_deadzone ) * ( ( float ) ASTICK_MAX / ( ASTICK_MAX - astick_deadzone ) ) ;
// Convert back to cartesian coordinates
analog_x = ( int ) round ( radius * cos ( angle ) ) ;
analog_y = ( int ) round ( radius * sin ( angle ) ) ;
// Clamp to correct range
if ( analog_x > + 32767 ) analog_x = + 32767 ;
if ( analog_x < - 32767 ) analog_x = - 32767 ;
if ( analog_y > + 32767 ) analog_y = + 32767 ;
if ( analog_y < - 32767 ) analog_y = - 32767 ;
}
else
{
analog_x = 0 ;
analog_y = 0 ;
}
}
// output
* p_analog_x = ( s8 ) ( analog_x > > 8 ) ;
* p_analog_y = ( s8 ) ( analog_y > > 8 ) ;
}
static uint16_t apply_trigger_deadzone ( uint16_t input )
{
if ( trigger_deadzone > 0 )
{
if ( input > trigger_deadzone )
{
// Re-scale analog range
static const int TRIGGER_MAX = 0x8000 ;
const float scale = ( ( float ) TRIGGER_MAX / ( float ) ( TRIGGER_MAX - trigger_deadzone ) ) ;
float scaled = ( input - trigger_deadzone ) * scale ;
input = ( int ) round ( scaled ) ;
if ( input > + 32767 )
input = + 32767 ;
}
else
input = 0 ;
}
return input ;
}
static uint16_t get_analog_trigger (
int16_t ret ,
retro_input_state_t input_state_cb ,
int player_index ,
int id )
{
// NOTE: Analog triggers were added Nov 2017. Not all front-ends support this
// feature (or pre-date it) so we need to handle this in a graceful way.
// First, try and get an analog value using the new libretro API constant
uint16_t trigger = input_state_cb ( player_index ,
RETRO_DEVICE_ANALOG ,
RETRO_DEVICE_INDEX_ANALOG_BUTTON ,
id ) ;
if ( trigger = = 0 )
{
// If we got exactly zero, we're either not pressing the button, or the front-end
// is not reporting analog values. We need to do a second check using the classic
// digital API method, to at least get some response - better than nothing.
// NOTE: If we're really just not holding the trigger, we're still going to get zero.
trigger = ( ret & ( 1 < < id ) ) ? 0x7FFF : 0 ;
}
else
{
// We got something, which means the front-end can handle analog buttons.
// So we apply a deadzone to the input and use it.
trigger = apply_trigger_deadzone ( trigger ) ;
}
return trigger ;
}
static void setDeviceButtonState ( u32 port , int deviceType , int btnId )
{
uint32_t dc_key = map_gamepad_button ( deviceType , btnId ) ;
bool is_down = input_cb ( port , deviceType , 0 , btnId ) ;
if ( is_down )
kcode [ port ] & = ~ dc_key ;
else
kcode [ port ] | = dc_key ;
}
static void setDeviceButtonStateFromBitmap ( u32 bitmap , u32 port , int deviceType , int btnId )
{
uint32_t dc_key = map_gamepad_button ( deviceType , btnId ) ;
bool is_down = bitmap & ( 1 < < btnId ) ;
if ( is_down )
kcode [ port ] & = ~ dc_key ;
else
kcode [ port ] | = dc_key ;
}
// don't call map_gamepad_button, we supply the DC bit directly.
static void setDeviceButtonStateDirect ( u32 bitmap , u32 port , int deviceType , int btnId , int dc_bit )
{
uint32_t dc_key = 1 < < dc_bit ;
bool is_down = bitmap & ( 1 < < btnId ) ;
if ( is_down )
kcode [ port ] & = ~ dc_key ;
else
kcode [ port ] | = dc_key ;
}
static void updateMouseState ( u32 port )
{
mo_x_delta [ port ] = input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_X ) ;
mo_y_delta [ port ] = input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_Y ) ;
bool btn_state = input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_LEFT ) ;
if ( btn_state )
mo_buttons [ port ] & = ~ ( 1 < < 2 ) ;
else
mo_buttons [ port ] | = 1 < < 2 ;
btn_state = input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_RIGHT ) ;
if ( btn_state )
mo_buttons [ port ] & = ~ ( 1 < < 1 ) ;
else
mo_buttons [ port ] | = 1 < < 1 ;
btn_state = input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_MIDDLE ) ;
if ( btn_state )
2021-09-15 15:07:36 +00:00
mo_buttons [ port ] & = ~ ( 1 < < 3 ) ;
2021-07-05 17:44:08 +00:00
else
2021-09-15 15:07:36 +00:00
mo_buttons [ port ] | = 1 < < 3 ;
2021-07-05 17:44:08 +00:00
if ( input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_WHEELDOWN ) )
mo_wheel_delta [ port ] - = 10 ;
else if ( input_cb ( port , RETRO_DEVICE_MOUSE , 0 , RETRO_DEVICE_ID_MOUSE_WHEELUP ) )
mo_wheel_delta [ port ] + = 10 ;
}
2021-07-08 18:09:09 +00:00
static void updateLightgunCoordinates ( u32 port )
{
int x = input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X ) ;
int y = input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y ) ;
if ( config : : Widescreen & & config : : ScreenStretching = = 100 )
mo_x_abs [ port ] = 640.f * ( ( x + 0x8000 ) * 4.f / 3.f / 0x10000 - ( 4.f / 3.f - 1.f ) / 2.f ) ;
else
mo_x_abs [ port ] = ( x + 0x8000 ) * 640.f / 0x10000 ;
mo_y_abs [ port ] = ( y + 0x8000 ) * 480.f / 0x10000 ;
lightgun_params [ port ] . offscreen = false ;
lightgun_params [ port ] . x = mo_x_abs [ port ] ;
lightgun_params [ port ] . y = mo_y_abs [ port ] ;
}
2021-07-05 17:44:08 +00:00
static void UpdateInputStateNaomi ( u32 port )
{
switch ( config : : MapleMainDevices [ port ] )
{
case MDT_LightGun :
{
//
// -- buttons
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_A ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_B ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_C ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_START ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_SELECT ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT ) ;
bool force_offscreen = false ;
if ( input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_RELOAD ) )
{
force_offscreen = true ;
if ( settings . platform . system = = DC_PLATFORM_NAOMI )
kcode [ port ] & = ~ NAOMI_BTN0_KEY ;
else
kcode [ port ] & = ~ AWAVE_TRIGGER_KEY ;
}
if ( force_offscreen | | input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN ) )
{
mo_x_abs [ port ] = 0 ;
mo_y_abs [ port ] = 0 ;
lightgun_params [ port ] . offscreen = true ;
if ( input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER ) | | input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_RELOAD ) )
{
if ( settings . platform . system = = DC_PLATFORM_NAOMI )
kcode [ port ] & = ~ NAOMI_BTN1_KEY ;
}
}
else
{
2021-07-08 18:09:09 +00:00
updateLightgunCoordinates ( port ) ;
2021-07-05 17:44:08 +00:00
}
}
break ;
default :
{
//
// -- buttons
int16_t ret = 0 ;
if ( libretro_supports_bitmasks )
ret = input_cb ( port , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_MASK ) ;
else
{
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
if ( input_cb ( port , RETRO_DEVICE_JOYPAD , 0 , id ) )
ret | = ( 1 < < id ) ;
}
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
{
switch ( id )
{
case RETRO_DEVICE_ID_JOYPAD_L3 :
if ( allow_service_buttons )
setDeviceButtonStateFromBitmap ( ret , port , RETRO_DEVICE_JOYPAD , id ) ;
break ;
case RETRO_DEVICE_ID_JOYPAD_R3 :
if ( settings . platform . system = = DC_PLATFORM_NAOMI | | allow_service_buttons )
setDeviceButtonStateFromBitmap ( ret , port , RETRO_DEVICE_JOYPAD , id ) ;
break ;
default :
setDeviceButtonStateFromBitmap ( ret , port , RETRO_DEVICE_JOYPAD , id ) ;
break ;
}
}
//
// -- analog stick
get_analog_stick ( input_cb , port , RETRO_DEVICE_INDEX_ANALOG_LEFT , & joyx [ port ] , & joyy [ port ] ) ;
get_analog_stick ( input_cb , port , RETRO_DEVICE_INDEX_ANALOG_RIGHT , & joyrx [ port ] , & joyry [ port ] ) ;
lt [ port ] = get_analog_trigger ( ret , input_cb , port , RETRO_DEVICE_ID_JOYPAD_L2 ) / 128 ;
rt [ port ] = get_analog_trigger ( ret , input_cb , port , RETRO_DEVICE_ID_JOYPAD_R2 ) / 128 ;
if ( NaomiGameInputs ! = NULL )
{
for ( int i = 0 ; NaomiGameInputs - > axes [ i ] . name ! = NULL ; i + + )
{
if ( NaomiGameInputs - > axes [ i ] . type = = Half )
{
/* Note:
* - Analog stick axes have a range of [ - 128 , 127 ]
* - Analog triggers have a range of [ 0 , 255 ] */
switch ( NaomiGameInputs - > axes [ i ] . axis )
{
case 0 :
/* Left stick X: [-128, 127] */
joyx [ port ] = std : : max ( ( int ) joyx [ port ] , 0 ) * 2 ;
break ;
case 1 :
/* Left stick Y: [-128, 127] */
joyy [ port ] = std : : max ( ( int ) joyy [ port ] , 0 ) * 2 ;
break ;
case 2 :
/* Right stick X: [-128, 127] */
joyrx [ port ] = std : : max ( ( int ) joyrx [ port ] , 0 ) * 2 ;
break ;
case 3 :
/* Right stick Y: [-128, 127] */
joyry [ port ] = std : : max ( ( int ) joyry [ port ] , 0 ) * 2 ;
break ;
/* Case 4/5 correspond to right/left trigger.
* These inputs are always classified as ' Half ' ,
* and already have the correct range - so no
* further action is required */
}
}
}
}
// -- mouse, for rotary encoders
updateMouseState ( port ) ;
}
break ;
}
// Avoid Left+Right or Up+Down buttons being pressed together as this crashes some games
if ( settings . platform . system = = DC_PLATFORM_NAOMI )
{
if ( ( kcode [ port ] & ( NAOMI_UP_KEY | NAOMI_DOWN_KEY ) ) = = 0 )
kcode [ port ] | = NAOMI_UP_KEY | NAOMI_DOWN_KEY ;
if ( ( kcode [ port ] & ( NAOMI_LEFT_KEY | NAOMI_RIGHT_KEY ) ) = = 0 )
kcode [ port ] | = NAOMI_LEFT_KEY | NAOMI_RIGHT_KEY ;
}
else
{
if ( ( kcode [ port ] & ( AWAVE_UP_KEY | AWAVE_DOWN_KEY ) ) = = 0 )
kcode [ port ] | = AWAVE_UP_KEY | AWAVE_DOWN_KEY ;
if ( ( kcode [ port ] & ( AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY ) ) = = 0 )
kcode [ port ] | = AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY ;
}
}
static void UpdateInputState ( u32 port )
{
if ( gl_ctx_resetting )
return ;
if ( settings . platform . system = = DC_PLATFORM_NAOMI | | settings . platform . system = = DC_PLATFORM_ATOMISWAVE )
{
UpdateInputStateNaomi ( port ) ;
return ;
}
if ( rumble . set_rumble_state ! = NULL & & vib_stop_time [ port ] > 0 )
{
if ( get_time_ms ( ) > = vib_stop_time [ port ] )
{
vib_stop_time [ port ] = 0 ;
rumble . set_rumble_state ( port , RETRO_RUMBLE_STRONG , 0 ) ;
}
else if ( vib_delta [ port ] > 0.0 )
{
u32 rem_time = vib_stop_time [ port ] - get_time_ms ( ) ;
rumble . set_rumble_state ( port , RETRO_RUMBLE_STRONG , 65535 * vib_strength [ port ] * rem_time * vib_delta [ port ] ) ;
}
}
lightgun_params [ port ] . offscreen = true ;
switch ( config : : MapleMainDevices [ port ] )
{
case MDT_SegaController :
{
int16_t ret = 0 ;
//
// -- buttons
if ( libretro_supports_bitmasks )
ret = input_cb ( port , RETRO_DEVICE_JOYPAD , 0 , RETRO_DEVICE_ID_JOYPAD_MASK ) ;
else
{
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
if ( input_cb ( port , RETRO_DEVICE_JOYPAD , 0 , id ) )
ret | = ( 1 < < id ) ;
}
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_X ; + + id )
setDeviceButtonStateFromBitmap ( ret , port , RETRO_DEVICE_JOYPAD , id ) ;
//
// -- analog stick
get_analog_stick ( input_cb , port , RETRO_DEVICE_INDEX_ANALOG_LEFT , & ( joyx [ port ] ) , & ( joyy [ port ] ) ) ;
//
// -- triggers
if ( digital_triggers )
{
// -- digital left trigger
if ( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_L2 ) )
lt [ port ] = 0xFF ;
else
lt [ port ] = 0 ;
// -- digital right trigger
if ( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_R2 ) )
rt [ port ] = 0xFF ;
else
rt [ port ] = 0 ;
}
else
{
// -- analog triggers
lt [ port ] = get_analog_trigger ( ret , input_cb , port , RETRO_DEVICE_ID_JOYPAD_L2 ) / 128 ;
rt [ port ] = get_analog_trigger ( ret , input_cb , port , RETRO_DEVICE_ID_JOYPAD_R2 ) / 128 ;
}
}
break ;
case MDT_AsciiStick :
{
int16_t ret = 0 ;
if ( libretro_supports_bitmasks )
ret = input_cb ( port , RETRO_DEVICE_ASCIISTICK , 0 , RETRO_DEVICE_ID_JOYPAD_MASK ) ;
else
{
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
if ( input_cb ( port , RETRO_DEVICE_ASCIISTICK , 0 , id ) )
ret | = ( 1 < < id ) ;
}
kcode [ port ] = 0xFFFF ; // active-low
// stick
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_UP , 4 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_DOWN , 5 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_LEFT , 6 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_RIGHT , 7 ) ;
// buttons
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_B , 2 ) ; // A
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_A , 1 ) ; // B
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_Y , 10 ) ; // X
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_X , 9 ) ; // Y
// Z
{
uint32_t dc_key = 1 < < 8 ; // Z
bool is_down = ( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_L ) ) | |
( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_L2 ) ) ;
if ( is_down )
kcode [ port ] & = ~ dc_key ;
else
kcode [ port ] | = dc_key ;
}
// C
{
uint32_t dc_key = 1 < < 0 ; // C
bool is_down = ( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_R ) ) | |
( ret & ( 1 < < RETRO_DEVICE_ID_JOYPAD_R2 ) ) ;
if ( is_down )
kcode [ port ] & = ~ dc_key ;
else
kcode [ port ] | = dc_key ;
}
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_ASCIISTICK , RETRO_DEVICE_ID_JOYPAD_START , 3 ) ; // Start
// unused inputs
lt [ port ] = 0 ;
rt [ port ] = 0 ;
joyx [ port ] = 0 ;
joyy [ port ] = 0 ;
}
break ;
case MDT_TwinStick :
{
int16_t ret = 0 ;
kcode [ port ] = 0xFFFF ; // active-low
if ( device_type [ port ] = = RETRO_DEVICE_TWINSTICK_SATURN )
{
// NOTE: This is a remapping of the RetroPad layout in the block below to make using a real
// Saturn Twin-Stick controller (via a USB adapter) less effort.
// The Saturn Twin-Stick identifies as a regular Saturn controller internally but with its controls
// wired to the two sticks without much rhyme or reason. The mapping below untangles that layout
// into DC compatible inputs, without requiring a change for the Reicast and Beetle Saturn cores.
// Hope that makes sense!!
// NOTE: the dc_bits below are the same, only the retro id values have been rearranged.
if ( libretro_supports_bitmasks )
ret = input_cb ( port , RETRO_DEVICE_TWINSTICK_SATURN , 0 , RETRO_DEVICE_ID_JOYPAD_MASK ) ;
else
{
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
if ( input_cb ( port , RETRO_DEVICE_TWINSTICK_SATURN , 0 , id ) )
ret | = ( 1 < < id ) ;
}
// left-stick
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_UP , 4 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_DOWN , 5 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_LEFT , 6 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_RIGHT , 7 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_L2 , 10 ) ; // left-trigger
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_R2 , 9 ) ; // left-turbo
// right-stick
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_X , 12 ) ; // up
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_L , 15 ) ; // right
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_A , 13 ) ; // down
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_Y , 14 ) ; // left
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_B , 2 ) ; // right-trigger
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_R , 1 ) ; // right-turbo
// misc control
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_START , 3 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK_SATURN , RETRO_DEVICE_ID_JOYPAD_SELECT , 11 ) ; //D
}
else
{
int analog ;
const int thresh = 11000 ; // about 33%, allows for 8-way movement
if ( libretro_supports_bitmasks )
ret = input_cb ( port , RETRO_DEVICE_TWINSTICK , 0 , RETRO_DEVICE_ID_JOYPAD_MASK ) ;
else
{
for ( int id = RETRO_DEVICE_ID_JOYPAD_B ; id < = RETRO_DEVICE_ID_JOYPAD_R3 ; + + id )
if ( input_cb ( port , RETRO_DEVICE_TWINSTICK , 0 , id ) )
ret | = ( 1 < < id ) ;
}
// LX
analog = input_cb ( port , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_X ) ;
if ( analog < - thresh )
kcode [ port ] & = ~ ( 1 < < 6 ) ; // L
else if ( analog > thresh )
kcode [ port ] & = ~ ( 1 < < 7 ) ; // R
else
{
// digital
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_LEFT , 6 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_RIGHT , 7 ) ;
}
// LY
analog = input_cb ( port , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_LEFT , RETRO_DEVICE_ID_ANALOG_Y ) ;
if ( analog < - thresh )
kcode [ port ] & = ~ ( 1 < < 4 ) ; // U
else if ( analog > thresh )
kcode [ port ] & = ~ ( 1 < < 5 ) ; // D
else
{
// digital
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_UP , 4 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_DOWN , 5 ) ;
}
// RX
analog = input_cb ( port , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_RIGHT , RETRO_DEVICE_ID_ANALOG_X ) ;
if ( analog < - thresh )
kcode [ port ] & = ~ ( 1 < < 14 ) ; // L
else if ( analog > thresh )
kcode [ port ] & = ~ ( 1 < < 15 ) ; // R
else
{
// digital
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_Y , 14 ) ; // left
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_A , 15 ) ; // right
}
// RY
analog = input_cb ( port , RETRO_DEVICE_ANALOG , RETRO_DEVICE_INDEX_ANALOG_RIGHT , RETRO_DEVICE_ID_ANALOG_Y ) ;
if ( analog < - thresh )
kcode [ port ] & = ~ ( 1 < < 12 ) ; // U
else if ( analog > thresh )
kcode [ port ] & = ~ ( 1 < < 13 ) ; // D
else
{
// digital
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_X , 12 ) ; // up
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_B , 13 ) ; // down
}
// left-stick buttons
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_L2 , 10 ) ; // left-trigger
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_L , 9 ) ; // left-turbo
// right-stick buttons
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_R2 , 2 ) ; // right-trigger
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_R , 1 ) ; // right-turbo
// misc control
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_START , 3 ) ;
setDeviceButtonStateDirect ( ret , port , RETRO_DEVICE_TWINSTICK , RETRO_DEVICE_ID_JOYPAD_SELECT , 11 ) ; //D
}
// unused inputs
lt [ port ] = 0 ;
rt [ port ] = 0 ;
joyx [ port ] = 0 ;
joyy [ port ] = 0 ;
}
break ;
case MDT_LightGun :
{
//
// -- buttons
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_TRIGGER ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_AUX_A ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_START ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT ) ;
setDeviceButtonState ( port , RETRO_DEVICE_LIGHTGUN , RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT ) ;
bool force_offscreen = false ;
if ( input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_RELOAD ) )
{
force_offscreen = true ;
kcode [ port ] & = ~ DC_BTN_A ;
}
if ( force_offscreen | | input_cb ( port , RETRO_DEVICE_LIGHTGUN , 0 , RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN ) )
{
mo_x_abs [ port ] = - 1000 ;
mo_y_abs [ port ] = - 1000 ;
lightgun_params [ port ] . offscreen = true ;
lightgun_params [ port ] . x = mo_x_abs [ port ] ;
lightgun_params [ port ] . y = mo_y_abs [ port ] ;
}
else
{
2021-07-08 18:09:09 +00:00
updateLightgunCoordinates ( port ) ;
2021-07-05 17:44:08 +00:00
}
}
break ;
case MDT_Mouse :
updateMouseState ( port ) ;
break ;
2021-07-20 17:21:11 +00:00
default :
break ;
2021-07-05 17:44:08 +00:00
}
}
void UpdateInputState ( )
{
UpdateInputState ( 0 ) ;
UpdateInputState ( 1 ) ;
UpdateInputState ( 2 ) ;
UpdateInputState ( 3 ) ;
}
void UpdateVibration ( u32 port , float power , float inclination , u32 durationMs )
{
if ( ! rumble . set_rumble_state )
return ;
vib_strength [ port ] = power ;
rumble . set_rumble_state ( port , RETRO_RUMBLE_STRONG , ( u16 ) ( 65535 * power ) ) ;
vib_stop_time [ port ] = get_time_ms ( ) + durationMs ;
vib_delta [ port ] = inclination ;
}
2021-07-15 16:44:57 +00:00
extern u8 kb_key [ 4 ] [ 6 ] ; // normal keys pressed
extern u8 kb_shift [ 4 ] ; // modifier keys pressed (bitmask)
2021-07-05 17:44:08 +00:00
static int kb_used ;
static void release_key ( unsigned dc_keycode )
{
if ( dc_keycode = = 0 )
return ;
if ( kb_used > 0 )
{
for ( int i = 0 ; i < 6 ; i + + )
{
2021-07-15 16:44:57 +00:00
if ( kb_key [ 0 ] [ i ] = = dc_keycode )
2021-07-05 17:44:08 +00:00
{
kb_used - - ;
for ( int j = i ; j < 5 ; j + + )
2021-07-15 16:44:57 +00:00
kb_key [ 0 ] [ j ] = kb_key [ 0 ] [ j + 1 ] ;
kb_key [ 0 ] [ 5 ] = 0 ;
2021-07-05 17:44:08 +00:00
}
}
}
}
static void retro_keyboard_event ( bool down , unsigned keycode , uint32_t character , uint16_t key_modifiers )
{
// Dreamcast keyboard emulation
if ( keycode = = RETROK_LSHIFT | | keycode = = RETROK_RSHIFT )
2021-07-20 17:21:11 +00:00
{
2021-07-05 17:44:08 +00:00
if ( ! down )
2021-07-15 16:44:57 +00:00
kb_shift [ 0 ] & = ~ ( 0x02 | 0x20 ) ;
2021-07-05 17:44:08 +00:00
else
2021-07-15 16:44:57 +00:00
kb_shift [ 0 ] | = ( 0x02 | 0x20 ) ;
2021-07-20 17:21:11 +00:00
}
2021-07-05 17:44:08 +00:00
if ( keycode = = RETROK_LCTRL | | keycode = = RETROK_RCTRL )
2021-07-20 17:21:11 +00:00
{
2021-07-05 17:44:08 +00:00
if ( ! down )
2021-07-15 16:44:57 +00:00
kb_shift [ 0 ] & = ~ ( 0x01 | 0x10 ) ;
2021-07-05 17:44:08 +00:00
else
2021-07-15 16:44:57 +00:00
kb_shift [ 0 ] | = ( 0x01 | 0x10 ) ;
2021-07-20 17:21:11 +00:00
}
2021-07-05 17:44:08 +00:00
// Make sure modifier keys are released
if ( ( key_modifiers & RETROKMOD_SHIFT ) = = 0 )
{
release_key ( kb_map [ RETROK_LSHIFT ] ) ;
release_key ( kb_map [ RETROK_LSHIFT ] ) ;
}
if ( ( key_modifiers & RETROKMOD_CTRL ) = = 0 )
{
release_key ( kb_map [ RETROK_LCTRL ] ) ;
release_key ( kb_map [ RETROK_RCTRL ] ) ;
}
u8 dc_keycode = kb_map [ keycode ] ;
if ( dc_keycode ! = 0 )
{
if ( down )
{
if ( kb_used < 6 )
{
bool found = false ;
for ( int i = 0 ; ! found & & i < 6 ; i + + )
{
2021-07-15 16:44:57 +00:00
if ( kb_key [ 0 ] [ i ] = = dc_keycode )
2021-07-05 17:44:08 +00:00
found = true ;
}
if ( ! found )
{
2021-07-15 16:44:57 +00:00
kb_key [ 0 ] [ kb_used ] = dc_keycode ;
2021-07-05 17:44:08 +00:00
kb_used + + ;
}
}
}
else
{
release_key ( dc_keycode ) ;
}
}
}
int msgboxf ( const char * text , unsigned int type , . . . )
{
if ( log_cb )
{
va_list args ;
char temp [ 2048 ] ;
switch ( type )
{
case MBX_ICONERROR :
va_start ( args , type ) ;
vsprintf ( temp , text , args ) ;
va_end ( args ) ;
strcat ( temp , " \n " ) ;
log_cb ( RETRO_LOG_ERROR , temp ) ;
break ;
default :
break ;
}
}
return 0 ;
}
2021-07-15 10:19:11 +00:00
void os_DebugBreak ( )
2021-07-05 17:44:08 +00:00
{
ERROR_LOG ( COMMON , " DEBUGBREAK! " ) ;
//exit(-1);
2021-07-12 18:14:21 +00:00
# ifdef __SWITCH__
2021-07-05 17:44:08 +00:00
svcExitProcess ( ) ;
# else
__builtin_trap ( ) ;
# endif
}
static bool retro_set_eject_state ( bool ejected )
{
disc_tray_open = ejected ;
if ( ejected )
{
DiscOpenLid ( ) ;
return true ;
}
else
{
2021-08-03 08:05:09 +00:00
try {
2021-09-30 12:24:17 +00:00
return DiscSwap ( disk_paths [ disk_index ] ) ;
2021-08-03 08:05:09 +00:00
} catch ( const FlycastException & e ) {
ERROR_LOG ( GDROM , " %s " , e . what ( ) ) ;
return false ;
}
2021-07-05 17:44:08 +00:00
}
}
static bool retro_get_eject_state ( )
{
return disc_tray_open ;
}
static unsigned retro_get_image_index ( )
{
return disk_index ;
}
static bool retro_set_image_index ( unsigned index )
{
disk_index = index ;
if ( disk_index > = disk_paths . size ( ) )
{
// No disk in drive
2021-09-30 12:24:17 +00:00
settings . content . path . clear ( ) ;
2021-07-05 17:44:08 +00:00
return true ;
}
2021-09-30 12:24:17 +00:00
settings . content . path = disk_paths [ index ] ;
2021-07-05 17:44:08 +00:00
if ( disc_tray_open )
return true ;
2021-08-03 08:05:09 +00:00
try {
2021-09-30 12:24:17 +00:00
return DiscSwap ( settings . content . path ) ;
2021-08-03 08:05:09 +00:00
} catch ( const FlycastException & e ) {
ERROR_LOG ( GDROM , " %s " , e . what ( ) ) ;
return false ;
}
2021-07-05 17:44:08 +00:00
}
static unsigned retro_get_num_images ( )
{
return disk_paths . size ( ) ;
}
static bool retro_add_image_index ( )
{
disk_paths . push_back ( " " ) ;
disk_labels . push_back ( " " ) ;
return true ;
}
static bool retro_replace_image_index ( unsigned index , const struct retro_game_info * info )
{
if ( index > = disk_paths . size ( ) | | index > = disk_labels . size ( ) )
return false ;
if ( info = = nullptr )
{
disk_paths . erase ( disk_paths . begin ( ) + index ) ;
disk_labels . erase ( disk_labels . begin ( ) + index ) ;
if ( disk_index > = index & & disk_index > 0 )
disk_index - - ;
}
else
{
char disk_label [ PATH_MAX ] ;
disk_label [ 0 ] = ' \0 ' ;
disk_paths [ index ] = info - > path ;
fill_short_pathname_representation ( disk_label , info - > path , sizeof ( disk_label ) ) ;
disk_labels [ index ] = disk_label ;
}
return true ;
}
static bool retro_set_initial_image ( unsigned index , const char * path )
{
if ( ! path | | * path = = ' \0 ' )
return false ;
disk_initial_index = index ;
disk_initial_path = path ;
return true ;
}
static bool retro_get_image_path ( unsigned index , char * path , size_t len )
{
if ( len < 1 )
return false ;
if ( index > = disk_paths . size ( ) )
return false ;
if ( disk_paths [ index ] . empty ( ) )
return false ;
strncpy ( path , disk_paths [ index ] . c_str ( ) , len - 1 ) ;
path [ len - 1 ] = ' \0 ' ;
return true ;
}
static bool retro_get_image_label ( unsigned index , char * label , size_t len )
{
if ( len < 1 )
return false ;
if ( index > = disk_paths . size ( ) | | index > = disk_labels . size ( ) )
return false ;
if ( disk_labels [ index ] . empty ( ) )
return false ;
strncpy ( label , disk_labels [ index ] . c_str ( ) , len - 1 ) ;
label [ len - 1 ] = ' \0 ' ;
return true ;
}
static void init_disk_control_interface ( )
{
unsigned dci_version = 0 ;
retro_disk_control_cb . set_eject_state = retro_set_eject_state ;
retro_disk_control_cb . get_eject_state = retro_get_eject_state ;
retro_disk_control_cb . set_image_index = retro_set_image_index ;
retro_disk_control_cb . get_image_index = retro_get_image_index ;
retro_disk_control_cb . get_num_images = retro_get_num_images ;
retro_disk_control_cb . add_image_index = retro_add_image_index ;
retro_disk_control_cb . replace_image_index = retro_replace_image_index ;
retro_disk_control_ext_cb . set_eject_state = retro_set_eject_state ;
retro_disk_control_ext_cb . get_eject_state = retro_get_eject_state ;
retro_disk_control_ext_cb . set_image_index = retro_set_image_index ;
retro_disk_control_ext_cb . get_image_index = retro_get_image_index ;
retro_disk_control_ext_cb . get_num_images = retro_get_num_images ;
retro_disk_control_ext_cb . add_image_index = retro_add_image_index ;
retro_disk_control_ext_cb . replace_image_index = retro_replace_image_index ;
retro_disk_control_ext_cb . set_initial_image = retro_set_initial_image ;
retro_disk_control_ext_cb . get_image_path = retro_get_image_path ;
retro_disk_control_ext_cb . get_image_label = retro_get_image_label ;
disk_initial_index = 0 ;
disk_initial_path . clear ( ) ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION , & dci_version ) & & ( dci_version > = 1 ) )
environ_cb ( RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE , & retro_disk_control_ext_cb ) ;
else
environ_cb ( RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE , & retro_disk_control_cb ) ;
}
static bool read_m3u ( const char * file )
{
char line [ PATH_MAX ] ;
char name [ PATH_MAX ] ;
FILE * f = fopen ( file , " r " ) ;
if ( ! f )
{
log_cb ( RETRO_LOG_ERROR , " Could not read file \n " ) ;
return false ;
}
while ( fgets ( line , sizeof ( line ) , f ) & & disk_index < = disk_paths . size ( ) )
{
if ( line [ 0 ] = = ' # ' )
continue ;
char * carriage_return = strchr ( line , ' \r ' ) ;
if ( carriage_return )
* carriage_return = ' \0 ' ;
char * newline = strchr ( line , ' \n ' ) ;
if ( newline )
* newline = ' \0 ' ;
// Remove any beginning and ending quotes as these can cause issues when feeding the paths into command line later
if ( line [ 0 ] = = ' " ' )
memmove ( line , line + 1 , strlen ( line ) ) ;
if ( line [ strlen ( line ) - 1 ] = = ' " ' )
line [ strlen ( line ) - 1 ] = ' \0 ' ;
if ( line [ 0 ] ! = ' \0 ' )
{
char disk_label [ PATH_MAX ] ;
disk_label [ 0 ] = ' \0 ' ;
if ( path_is_absolute ( line ) )
snprintf ( name , sizeof ( name ) , " %s " , line ) ;
else
snprintf ( name , sizeof ( name ) , " %s%s " , g_roms_dir , line ) ;
disk_paths . push_back ( name ) ;
fill_short_pathname_representation ( disk_label , name , sizeof ( disk_label ) ) ;
disk_labels . push_back ( disk_label ) ;
disk_index + + ;
}
}
fclose ( f ) ;
return disk_index ! = 0 ;
}
void gui_display_notification ( const char * msg , int duration )
{
2021-07-07 07:48:10 +00:00
if ( mute_messages )
return ;
2021-07-05 17:44:08 +00:00
retro_message retromsg ;
retromsg . msg = msg ;
retromsg . frames = duration / 17 ;
2021-07-20 17:21:11 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE , & retromsg ) ;
2021-07-05 17:44:08 +00:00
}
void gui_init ( ) {
}
void gui_term ( ) {
}