+//Percentage distance of screen to adjust
+static int GunconAdjustX = 0;
+static int GunconAdjustY = 0;
+
+//Used when out by a percentage
+static float GunconAdjustRatioX = 1;
+static float GunconAdjustRatioY = 1;
+
+static void update_variables(bool in_flight)
+{
+ struct retro_variable var;
+ int i;
+#ifdef GPU_PEOPS
+ int gpu_peops_fix = 0;
+#endif
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_frameskip";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ pl_rearmed_cbs.frameskip = atoi(var.value);
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_region";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ Config.PsxAuto = 0;
+ if (strcmp(var.value, "auto") == 0)
+ Config.PsxAuto = 1;
+ else if (strcmp(var.value, "NTSC") == 0)
+ Config.PsxType = 0;
+ else if (strcmp(var.value, "PAL") == 0)
+ Config.PsxType = 1;
+ }
+
+ for (i = 0; i < PORTS_NUMBER; i++)
+ update_controller_port_variable(i);
+
+ update_multitap();
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_negcon_deadzone";
+ negcon_deadzone = 0;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ negcon_deadzone = (int)(atoi(var.value) * 0.01f * NEGCON_RANGE);
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_negcon_response";
+ negcon_linearity = 1;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "quadratic") == 0)
+ {
+ negcon_linearity = 2;
+ }
+ else if (strcmp(var.value, "cubic") == 0)
+ {
+ negcon_linearity = 3;
+ }
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_analog_axis_modifier";
+ axis_bounds_modifier = true;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "square") == 0)
+ {
+ axis_bounds_modifier = true;
+ }
+ else if (strcmp(var.value, "circle") == 0)
+ {
+ axis_bounds_modifier = false;
+ }
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_vibration";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ in_enable_vibration = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ in_enable_vibration = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_dithering";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ {
+ pl_rearmed_cbs.gpu_peops.iUseDither = 0;
+ pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 0;
+ pl_rearmed_cbs.gpu_unai.dithering = 0;
+#ifdef __ARM_NEON__
+ pl_rearmed_cbs.gpu_neon.allow_dithering = 0;
+#endif
+ }
+ else if (strcmp(var.value, "enabled") == 0)
+ {
+ pl_rearmed_cbs.gpu_peops.iUseDither = 1;
+ pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 1;
+ pl_rearmed_cbs.gpu_unai.dithering = 1;
+#ifdef __ARM_NEON__
+ pl_rearmed_cbs.gpu_neon.allow_dithering = 1;
+#endif
+ }
+ }
+
+#ifdef GPU_NEON
+ var.value = NULL;
+ var.key = "pcsx_rearmed_neon_interlace_enable";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_neon.allow_interlace = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_neon.allow_interlace = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_neon_enhancement_enable";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_neon.enhancement_enable = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_neon.enhancement_enable = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_neon_enhancement_no_main";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_neon.enhancement_no_main = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_neon.enhancement_no_main = 1;
+ }
+#endif
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_duping_enable";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ duping_enable = false;
+ else if (strcmp(var.value, "enabled") == 0)
+ duping_enable = true;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_display_internal_fps";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ display_internal_fps = false;
+ else if (strcmp(var.value, "enabled") == 0)
+ display_internal_fps = true;
+ }
+
+#if defined(LIGHTREC) || defined(NEW_DYNAREC)
+ var.value = NULL;
+ var.key = "pcsx_rearmed_drc";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ R3000Acpu *prev_cpu = psxCpu;
+#if defined(LIGHTREC)
+ bool can_use_dynarec = found_bios;
+#else
+ bool can_use_dynarec = 1;
+#endif
+
+#ifdef _3DS
+ if (!__ctr_svchax)
+ Config.Cpu = CPU_INTERPRETER;
+ else
+#endif
+ if (strcmp(var.value, "disabled") == 0 || !can_use_dynarec)
+ Config.Cpu = CPU_INTERPRETER;
+ else if (strcmp(var.value, "enabled") == 0)
+ Config.Cpu = CPU_DYNAREC;
+
+ psxCpu = (Config.Cpu == CPU_INTERPRETER) ? &psxInt : &psxRec;
+ if (psxCpu != prev_cpu)
+ {
+ prev_cpu->Shutdown();
+ psxCpu->Init();
+ psxCpu->Reset(); // not really a reset..
+ }
+ }
+#endif /* LIGHTREC || NEW_DYNAREC */
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_spu_reverb";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ spu_config.iUseReverb = false;
+ else if (strcmp(var.value, "enabled") == 0)
+ spu_config.iUseReverb = true;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_spu_interpolation";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "simple") == 0)
+ spu_config.iUseInterpolation = 1;
+ else if (strcmp(var.value, "gaussian") == 0)
+ spu_config.iUseInterpolation = 2;
+ else if (strcmp(var.value, "cubic") == 0)
+ spu_config.iUseInterpolation = 3;
+ else if (strcmp(var.value, "off") == 0)
+ spu_config.iUseInterpolation = 0;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_pe2_fix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.RCntFix = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ Config.RCntFix = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_idiablofix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ spu_config.idiablofix = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ spu_config.idiablofix = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_inuyasha_fix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.VSyncWA = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ Config.VSyncWA = 1;
+ }
+
+#ifndef _WIN32
+ var.value = NULL;
+ var.key = "pcsx_rearmed_async_cd";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "async") == 0)
+ Config.AsyncCD = 1;
+ else
+ Config.AsyncCD = 0;
+ }
+#endif
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_noxadecoding";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.Xa = 1;
+ else
+ Config.Xa = 0;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nocdaudio";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.Cdda = 1;
+ else
+ Config.Cdda = 0;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_spuirq";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.SpuIrq = 0;
+ else
+ Config.SpuIrq = 1;
+ }
+
+#ifdef THREAD_RENDERING
+ var.key = "pcsx_rearmed_gpu_thread_rendering";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_OFF;
+ else if (strcmp(var.value, "sync") == 0)
+ pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_SYNC;
+ else if (strcmp(var.value, "async") == 0)
+ pl_rearmed_cbs.thread_rendering = THREAD_RENDERING_ASYNC;
+ }
+#endif
+
+#ifdef GPU_PEOPS
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_odd_even_bit";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_ODD_EVEN_BIT;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_expand_screen_width";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_EXPAND_SCREEN_WIDTH;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_ignore_brightness";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_IGNORE_BRIGHTNESS;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_disable_coord_check";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_DISABLE_COORD_CHECK;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_lazy_screen_update";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_LAZY_SCREEN_UPDATE;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_old_frame_skip";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_OLD_FRAME_SKIP;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_repeated_triangles";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_REPEATED_TRIANGLES;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_quads_with_triangles";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_QUADS_WITH_TRIANGLES;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gpu_peops_fake_busy_state";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ gpu_peops_fix |= GPU_PEOPS_FAKE_BUSY_STATE;
+ }
+
+ if (pl_rearmed_cbs.gpu_peops.dwActFixes != gpu_peops_fix)
+ pl_rearmed_cbs.gpu_peops.dwActFixes = gpu_peops_fix;
+
+ /* Show/hide core options */
+
+ var.key = "pcsx_rearmed_show_gpu_peops_settings";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ int show_advanced_gpu_peops_settings_prev = show_advanced_gpu_peops_settings;
+
+ show_advanced_gpu_peops_settings = 1;
+ if (strcmp(var.value, "disabled") == 0)
+ show_advanced_gpu_peops_settings = 0;
+
+ if (show_advanced_gpu_peops_settings != show_advanced_gpu_peops_settings_prev)
+ {
+ unsigned i;
+ struct retro_core_option_display option_display;
+ char gpu_peops_option[9][45] = {
+ "pcsx_rearmed_gpu_peops_odd_even_bit",
+ "pcsx_rearmed_gpu_peops_expand_screen_width",
+ "pcsx_rearmed_gpu_peops_ignore_brightness",
+ "pcsx_rearmed_gpu_peops_disable_coord_check",
+ "pcsx_rearmed_gpu_peops_lazy_screen_update",
+ "pcsx_rearmed_gpu_peops_old_frame_skip",
+ "pcsx_rearmed_gpu_peops_repeated_triangles",
+ "pcsx_rearmed_gpu_peops_quads_with_triangles",
+ "pcsx_rearmed_gpu_peops_fake_busy_state"
+ };
+
+ option_display.visible = show_advanced_gpu_peops_settings;
+
+ for (i = 0; i < 9; i++)
+ {
+ option_display.key = gpu_peops_option[i];
+ environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
+ }
+ }
+ }
+#endif
+
+#ifdef GPU_UNAI
+ var.key = "pcsx_rearmed_gpu_unai_ilace_force";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.ilace_force = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.ilace_force = 1;
+ }
+
+ var.key = "pcsx_rearmed_gpu_unai_pixel_skip";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.pixel_skip = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.pixel_skip = 1;
+ }
+
+ var.key = "pcsx_rearmed_gpu_unai_lighting";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.lighting = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.lighting = 1;
+ }
+
+ var.key = "pcsx_rearmed_gpu_unai_fast_lighting";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.fast_lighting = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.fast_lighting = 1;
+ }
+
+ var.key = "pcsx_rearmed_gpu_unai_blending";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.blending = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.blending = 1;
+ }
+
+ var.key = "pcsx_rearmed_gpu_unai_scale_hires";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.scale_hires = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.scale_hires = 1;
+ }
+
+ var.key = "pcsx_rearmed_show_gpu_unai_settings";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ int show_advanced_gpu_unai_settings_prev = show_advanced_gpu_unai_settings;
+
+ show_advanced_gpu_unai_settings = 1;
+ if (strcmp(var.value, "disabled") == 0)
+ show_advanced_gpu_unai_settings = 0;
+
+ if (show_advanced_gpu_unai_settings != show_advanced_gpu_unai_settings_prev)
+ {
+ unsigned i;
+ struct retro_core_option_display option_display;
+ char gpu_unai_option[6][40] = {
+ "pcsx_rearmed_gpu_unai_blending",
+ "pcsx_rearmed_gpu_unai_lighting",
+ "pcsx_rearmed_gpu_unai_fast_lighting",
+ "pcsx_rearmed_gpu_unai_ilace_force",
+ "pcsx_rearmed_gpu_unai_pixel_skip",
+ "pcsx_rearmed_gpu_unai_scale_hires",
+ };
+
+ option_display.visible = show_advanced_gpu_unai_settings;
+
+ for (i = 0; i < 6; i++)
+ {
+ option_display.key = gpu_unai_option[i];
+ environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
+ }
+ }
+ }
+#endif // GPU_UNAI
+
+ //This adjustment process gives the user the ability to manually align the mouse up better
+ //with where the shots are in the emulator.
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gunconadjustx";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ GunconAdjustX = atoi(var.value);
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gunconadjusty";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ GunconAdjustY = atoi(var.value);
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gunconadjustratiox";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ GunconAdjustRatioX = atof(var.value);
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gunconadjustratioy";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ GunconAdjustRatioY = atof(var.value);
+ }
+
+#ifdef NEW_DYNAREC
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nosmccheck";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_NO_SMC_CHECK;
+ else
+ new_dynarec_hacks &= ~NDHACK_NO_SMC_CHECK;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gteregsunneeded";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_GTE_UNNEEDED;
+ else
+ new_dynarec_hacks &= ~NDHACK_GTE_UNNEEDED;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nogteflags";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_GTE_NO_FLAGS;
+ else
+ new_dynarec_hacks &= ~NDHACK_GTE_NO_FLAGS;
+ }
+
+ /* this probably is safe to change in real-time */
+ var.value = NULL;
+ var.key = "pcsx_rearmed_psxclock";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ int psxclock = atoi(var.value);
+ cycle_multiplier = 10000 / psxclock;
+ }
+#endif /* NEW_DYNAREC */
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_input_sensitivity";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ mouse_sensitivity = atof(var.value);
+ }
+
+ var.key = "pcsx_rearmed_show_other_input_settings";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ int previous_settings = show_other_input_settings;
+
+ show_other_input_settings = 1;
+ if (strcmp(var.value, "disabled") == 0)
+ show_other_input_settings = 0;
+
+ if (show_other_input_settings != previous_settings)
+ {
+ unsigned i;
+ struct retro_core_option_display option_display;
+ char gpu_peops_option[][50] = {
+ "pcsx_rearmed_multitap1",
+ "pcsx_rearmed_multitap2",
+ "pcsx_rearmed_pad3type",
+ "pcsx_rearmed_pad4type",
+ "pcsx_rearmed_pad5type",
+ "pcsx_rearmed_pad6type",
+ "pcsx_rearmed_pad7type",
+ "pcsx_rearmed_pad8type",
+ "pcsx_rearmed_negcon_deadzone",
+ "pcsx_rearmed_negcon_response",
+ "pcsx_rearmed_analog_axis_modifier",
+ "pcsx_rearmed_gunconadjustx",
+ "pcsx_rearmed_gunconadjusty",
+ "pcsx_rearmed_gunconadjustratiox",
+ "pcsx_rearmed_gunconadjustratioy"
+ };
+ #define INPUT_LIST (sizeof(gpu_peops_option) / sizeof(gpu_peops_option[0]))
+
+ option_display.visible = show_other_input_settings;
+
+ for (i = 0; i < INPUT_LIST; i++)
+ {
+ option_display.key = gpu_peops_option[i];
+ environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
+ }
+ }
+ }
+
+ if (in_flight)
+ {
+ // inform core things about possible config changes
+ plugin_call_rearmed_cbs();
+
+ if (GPU_open != NULL && GPU_close != NULL)
+ {
+ GPU_close();
+ GPU_open(&gpuDisp, "PCSX", NULL);
+ }
+
+ dfinput_activate();
+ }
+ else
+ {
+ //not yet running
+
+ //bootlogo display hack
+ if (found_bios)
+ {
+ var.value = NULL;
+ var.key = "pcsx_rearmed_show_bios_bootlogo";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ Config.SlowBoot = 0;
+ rebootemu = 0;
+ if (strcmp(var.value, "enabled") == 0)
+ {
+ Config.SlowBoot = 1;
+ rebootemu = 1;
+ }
+ }
+ }
+ }
+}
+
+// Taken from beetle-psx-libretro
+static uint16_t get_analog_button(int16_t ret, retro_input_state_t input_state_cb, int player_index, int id)
+{
+ // NOTE: Analog buttons 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 button = input_state_cb(player_index,
+ RETRO_DEVICE_ANALOG,
+ RETRO_DEVICE_INDEX_ANALOG_BUTTON,
+ id);
+ button = MIN(button / 128, 255);
+
+ if (button == 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 button, we're still going to get zero.
+
+ button = (ret & (1 << id)) ? 255 : 0;
+ }
+
+ return button;
+}
+
+unsigned char axis_range_modifier(int16_t axis_value, bool is_square)
+{
+ float modifier_axis_range = 0;
+
+ if (is_square)
+ {
+ modifier_axis_range = round((axis_value >> 8) / 0.785) + 128;
+ if (modifier_axis_range < 0)
+ {
+ modifier_axis_range = 0;
+ }
+ else if (modifier_axis_range > 255)
+ {
+ modifier_axis_range = 255;
+ }
+ }
+ else
+ {
+ modifier_axis_range = MIN(((axis_value >> 8) + 128), 255);
+ }
+
+ return modifier_axis_range;
+}
+
+static void update_input_guncon(int port, int ret)
+{
+ //ToDo move across to:
+ //RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X
+ //RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y
+ //RETRO_DEVICE_ID_LIGHTGUN_TRIGGER
+ //RETRO_DEVICE_ID_LIGHTGUN_RELOAD
+ //RETRO_DEVICE_ID_LIGHTGUN_AUX_A
+ //RETRO_DEVICE_ID_LIGHTGUN_AUX_B
+ //Though not sure these are hooked up properly on the Pi
+
+ //GUNCON has 3 controls, Trigger,A,B which equal Circle,Start,Cross
+
+ // Trigger
+ //The 1 is hardcoded instead of port to prevent the overlay mouse button libretro crash bug
+ if (input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT))
+ {
+ in_keystate[port] |= (1 << DKEY_CIRCLE);
+ }
+
+ // A
+ if (input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT))
+ {
+ in_keystate[port] |= (1 << DKEY_START);
+ }
+
+ // B
+ if (input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE))
+ {
+ in_keystate[port] |= (1 << DKEY_CROSS);
+ }
+
+ int gunx = input_state_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
+ int guny = input_state_cb(port, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
+
+ //Mouse range is -32767 -> 32767
+ //1% is about 655
+ //Use the left analog stick field to store the absolute coordinates
+ in_analog_left[port][0] = (gunx * GunconAdjustRatioX) + (GunconAdjustX * 655);
+ in_analog_left[port][1] = (guny * GunconAdjustRatioY) + (GunconAdjustY * 655);
+}
+
+static void update_input_negcon(int port, int ret)
+{
+ int lsx;
+ int rsy;
+ int negcon_i_rs;
+ int negcon_ii_rs;
+ float negcon_twist_amplitude;
+
+ // Query digital inputs
+ //
+ // > Pad-Up
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_UP))
+ in_keystate[port] |= (1 << DKEY_UP);
+ // > Pad-Right
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))
+ in_keystate[port] |= (1 << DKEY_RIGHT);
+ // > Pad-Down
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN))
+ in_keystate[port] |= (1 << DKEY_DOWN);
+ // > Pad-Left
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT))
+ in_keystate[port] |= (1 << DKEY_LEFT);
+ // > Start
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_START))
+ in_keystate[port] |= (1 << DKEY_START);
+ // > neGcon A
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_A))
+ in_keystate[port] |= (1 << DKEY_CIRCLE);
+ // > neGcon B
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_X))
+ in_keystate[port] |= (1 << DKEY_TRIANGLE);
+ // > neGcon R shoulder (digital)
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_R))
+ in_keystate[port] |= (1 << DKEY_R1);
+ // Query analog inputs
+ //
+ // From studying 'libpcsxcore/plugins.c' and 'frontend/plugin.c':
+ // >> pad->leftJoyX == in_analog_left[port][0] == NeGcon II
+ // >> pad->leftJoyY == in_analog_left[port][1] == NeGcon L
+ // >> pad->rightJoyX == in_analog_right[port][0] == NeGcon twist
+ // >> pad->rightJoyY == in_analog_right[port][1] == NeGcon I
+ // So we just have to map in_analog_left/right to more
+ // appropriate inputs...
+ //
+ // > NeGcon twist
+ // >> Get raw analog stick value and account for deadzone
+ lsx = input_state_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
+ if (lsx > negcon_deadzone)
+ lsx = lsx - negcon_deadzone;
+ else if (lsx < -negcon_deadzone)
+ lsx = lsx + negcon_deadzone;
+ else
+ lsx = 0;
+ // >> Convert to an 'amplitude' [-1.0,1.0] and adjust response
+ negcon_twist_amplitude = (float)lsx / (float)(NEGCON_RANGE - negcon_deadzone);
+ if (negcon_linearity == 2)
+ {
+ if (negcon_twist_amplitude < 0.0)
+ negcon_twist_amplitude = -(negcon_twist_amplitude * negcon_twist_amplitude);
+ else
+ negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude;
+ }
+ else if (negcon_linearity == 3)
+ negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude * negcon_twist_amplitude;
+ // >> Convert to final 'in_analog' integer value [0,255]
+ in_analog_right[port][0] = MAX(MIN((int)(negcon_twist_amplitude * 128.0f) + 128, 255), 0);
+ // > NeGcon I + II
+ // >> Handle right analog stick vertical axis mapping...
+ // - Up (-Y) == accelerate == neGcon I
+ // - Down (+Y) == brake == neGcon II
+ negcon_i_rs = 0;
+ negcon_ii_rs = 0;
+ rsy = input_state_cb(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
+ if (rsy >= 0)
+ {
+ // Account for deadzone
+ // (Note: have never encountered a gamepad with significant differences
+ // in deadzone between left/right analog sticks, so use the regular 'twist'
+ // deadzone here)
+ if (rsy > negcon_deadzone)
+ rsy = rsy - negcon_deadzone;
+ else
+ rsy = 0;
+ // Convert to 'in_analog' integer value [0,255]
+ negcon_ii_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
+ }
+ else
+ {
+ if (rsy < -negcon_deadzone)
+ rsy = -1 * (rsy + negcon_deadzone);
+ else
+ rsy = 0;
+ negcon_i_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
+ }
+ // >> NeGcon I
+ in_analog_right[port][1] = MAX(
+ MAX(
+ get_analog_button(ret, input_state_cb, port, RETRO_DEVICE_ID_JOYPAD_R2),
+ get_analog_button(ret, input_state_cb, port, RETRO_DEVICE_ID_JOYPAD_B)),
+ negcon_i_rs);
+ // >> NeGcon II
+ in_analog_left[port][0] = MAX(
+ MAX(
+ get_analog_button(ret, input_state_cb, port, RETRO_DEVICE_ID_JOYPAD_L2),
+ get_analog_button(ret, input_state_cb, port, RETRO_DEVICE_ID_JOYPAD_Y)),
+ negcon_ii_rs);
+ // > NeGcon L
+ in_analog_left[port][1] = get_analog_button(ret, input_state_cb, port, RETRO_DEVICE_ID_JOYPAD_L);
+}
+
+static void update_input_mouse(int port, int ret)
+{
+ float raw_x = input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
+ float raw_y = input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
+
+ int x = (int)roundf(raw_x * mouse_sensitivity);
+ int y = (int)roundf(raw_y * mouse_sensitivity);
+
+ if (x > 127) x = 127;
+ else if (x < -128) x = -128;
+
+ if (y > 127) y = 127;
+ else if (y < -128) y = -128;
+
+ in_mouse[port][0] = x; /* -128..+128 left/right movement, 0 = no movement */
+ in_mouse[port][1] = y; /* -128..+128 down/up movement, 0 = no movement */
+
+ /* left mouse button state */
+ if (input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT))
+ in_keystate[port] |= 1 << 11;
+
+ /* right mouse button state */
+ if (input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT))
+ in_keystate[port] |= 1 << 10;
+}
+
+static void update_input(void)
+{
+ // reset all keystate, query libretro for keystate
+ int i;
+ int j;
+
+ for (i = 0; i < PORTS_NUMBER; i++)
+ {
+ int16_t ret = 0;
+ int type = in_type[i];
+
+ in_keystate[i] = 0;
+
+ if (type == PSE_PAD_TYPE_NONE)
+ continue;
+
+ if (libretro_supports_bitmasks)
+ ret = input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
+ else
+ {
+ for (j = 0; j < (RETRO_DEVICE_ID_JOYPAD_R3 + 1); j++)
+ {
+ if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, j))
+ ret |= (1 << j);
+ }
+ }
+
+ switch (type)
+ {
+ case PSE_PAD_TYPE_GUNCON:
+ update_input_guncon(i, ret);
+ break;
+ case PSE_PAD_TYPE_NEGCON:
+ update_input_negcon(i, ret);
+ break;
+ case PSE_PAD_TYPE_MOUSE:
+ update_input_mouse(i, ret);
+ break;
+ default:
+ // Query digital inputs
+ for (j = 0; j < RETRO_PSX_MAP_LEN; j++)
+ if (ret & (1 << j))
+ in_keystate[i] |= retro_psx_map[j];
+
+ // Query analog inputs
+ if (type == PSE_PAD_TYPE_ANALOGJOY || type == PSE_PAD_TYPE_ANALOGPAD)
+ {
+ in_analog_left[i][0] = axis_range_modifier(input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X), axis_bounds_modifier);
+ in_analog_left[i][1] = axis_range_modifier(input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y), axis_bounds_modifier);
+ in_analog_right[i][0] = axis_range_modifier(input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X), axis_bounds_modifier);
+ in_analog_right[i][1] = axis_range_modifier(input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y), axis_bounds_modifier);
+ }
+ }
+ }
+}
+
+static void print_internal_fps(void)
+{
+ if (display_internal_fps)
+ {
+ frame_count++;
+
+ if (frame_count % INTERNAL_FPS_SAMPLE_PERIOD == 0)
+ {
+ unsigned internal_fps = pl_rearmed_cbs.flip_cnt * (is_pal_mode ? 50 : 60) / INTERNAL_FPS_SAMPLE_PERIOD;
+ char str[64];
+ const char *strc = (const char *)str;
+
+ str[0] = '\0';
+
+ snprintf(str, sizeof(str), "Internal FPS: %2d", internal_fps);
+
+ pl_rearmed_cbs.flip_cnt = 0;
+
+ if (msg_interface_version >= 1)
+ {
+ struct retro_message_ext msg = {
+ strc,
+ 3000,
+ 1,
+ RETRO_LOG_INFO,
+ RETRO_MESSAGE_TARGET_OSD,
+ RETRO_MESSAGE_TYPE_STATUS,
+ -1
+ };
+ environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE_EXT, &msg);
+ }
+ else
+ {
+ struct retro_message msg = {
+ strc,
+ 180
+ };
+ environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
+ }
+ }
+ }
+ else
+ frame_count = 0;
+}
+
+void retro_run(void)
+{
+ //SysReset must be run while core is running,Not in menu (Locks up Retroarch)
+ if (rebootemu != 0)
+ {
+ rebootemu = 0;
+ SysReset();
+ if (!Config.HLE && !Config.SlowBoot)
+ {
+ // skip BIOS logos
+ psxRegs.pc = psxRegs.GPR.n.ra;
+ }
+ }
+
+ print_internal_fps();
+
+ input_poll_cb();
+
+ update_input();
+
+ bool updated = false;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
+ update_variables(true);
+
+ stop = 0;
+ psxCpu->Execute();
+
+ video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf_ptr : NULL,
+ vout_width, vout_height, vout_width * 2);
+ vout_fb_dirty = 0;
+
+ set_vout_fb();
+}
+
+static bool try_use_bios(const char *path)