X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=frontend%2Flibretro.c;h=7fa63cbf34afd3ec895ce08bad99e52cebf60c9d;hb=28ea3e2d87c4e239d8853b10c4496f82feb9d982;hp=59bb4f0ddf1a9d1e9dee8bc04f68e49b85ebc28d;hpb=71245736b067901d7202cc5825350608fc7de3bb;p=pcsx_rearmed.git diff --git a/frontend/libretro.c b/frontend/libretro.c index 59bb4f0d..7fa63cbf 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -89,6 +89,25 @@ int multitap1 = 0; int multitap2 = 0; int in_enable_vibration = 1; +// NegCon adjustment parameters +// > The NegCon 'twist' action is somewhat awkward when mapped +// to a standard analog stick -> user should be able to tweak +// response/deadzone for comfort +// > When response is linear, 'additional' deadzone (set here) +// may be left at zero, since this is normally handled via in-game +// options menus +// > When response is non-linear, deadzone should be set to match the +// controller being used (otherwise precision may be lost) +// > negcon_linearity: +// - 1: Response is linear - recommended when using racing wheel +// peripherals, not recommended for standard gamepads +// - 2: Response is quadratic - optimal setting for gamepads +// - 3: Response is cubic - enables precise fine control, but +// difficult to use... +#define NEGCON_RANGE 0x7FFF +static int negcon_deadzone = 0; +static int negcon_linearity = 1; + /* PSX max resolution is 640x512, but with enhancement it's 1024x512 */ #define VOUT_MAX_WIDTH 1024 #define VOUT_MAX_HEIGHT 512 @@ -444,16 +463,19 @@ void retro_set_environment(retro_environment_t cb) static const struct retro_variable vars[] = { { "pcsx_rearmed_frameskip", "Frameskip; 0|1|2|3" }, { "pcsx_rearmed_region", "Region; auto|NTSC|PAL" }, - { "pcsx_rearmed_pad1type", "Pad 1 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad2type", "Pad 2 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad3type", "Pad 3 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad4type", "Pad 4 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad5type", "Pad 5 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad6type", "Pad 6 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad7type", "Pad 7 Type; default|none|standard|analog|negcon" }, - { "pcsx_rearmed_pad8type", "Pad 8 Type; default|none|standard|analog|negcon" }, + { "pcsx_rearmed_memcard2", "Enable second memory card; disabled|enabled" }, + { "pcsx_rearmed_pad1type", "Pad 1 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad2type", "Pad 2 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad3type", "Pad 3 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad4type", "Pad 4 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad5type", "Pad 5 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad6type", "Pad 6 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad7type", "Pad 7 Type; default|none|standard|analog|dualshock|negcon" }, + { "pcsx_rearmed_pad8type", "Pad 8 Type; default|none|standard|analog|dualshock|negcon" }, { "pcsx_rearmed_multitap1", "Multitap 1; auto|disabled|enabled" }, { "pcsx_rearmed_multitap2", "Multitap 2; auto|disabled|enabled" }, + { "pcsx_rearmed_negcon_deadzone", "NegCon Twist Deadzone (percent); 0|5|10|15|20|25|30" }, + { "pcsx_rearmed_negcon_response", "NegCon Twist Response; linear|quadratic|cubic" }, { "pcsx_rearmed_vibration", "Enable Vibration; enabled|disabled" }, { "pcsx_rearmed_dithering", "Enable Dithering; enabled|disabled" }, #ifndef DRC_DISABLE @@ -543,6 +565,8 @@ static void update_controller_port_variable(unsigned port) if (strcmp(var.value, "standard") == 0) in_type[port] = PSE_PAD_TYPE_STANDARD; else if (strcmp(var.value, "analog") == 0) + in_type[port] = PSE_PAD_TYPE_ANALOGJOY; + else if (strcmp(var.value, "dualshock") == 0) in_type[port] = PSE_PAD_TYPE_ANALOGPAD; else if (strcmp(var.value, "negcon") == 0) in_type[port] = PSE_PAD_TYPE_NEGCON; @@ -1358,6 +1382,26 @@ static void update_variables(bool in_flight) 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_vibration"; @@ -1587,6 +1631,11 @@ void retro_run(void) // reset all keystate, query libretro for keystate int j; + int lsx; + int rsy; + float negcon_twist_amplitude; + int negcon_i_rs; + int negcon_ii_rs; for(i = 0; i < PORTS_NUMBER; i++) { in_keystate[i] = 0; @@ -1640,16 +1689,70 @@ void retro_run(void) // appropriate inputs... // // > NeGcon twist - in_analog_right[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255); - // > NeGcon I + // >> Get raw analog stick value and account for deadzone + lsx = input_state_cb(i, 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[i][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(i, 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[i][1] = MAX( - get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2), - get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B) + MAX( + get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2), + get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B) + ), + negcon_i_rs ); - // > NeGcon II + // >> NeGcon II in_analog_left[i][0] = MAX( - get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2), - get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y) + MAX( + get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2), + get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y) + ), + negcon_ii_rs ); // > NeGcon L in_analog_left[i][1] = get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L); @@ -1663,7 +1766,7 @@ void retro_run(void) } } // Query analog inputs - if (in_type[i] == PSE_PAD_TYPE_ANALOGPAD) + if (in_type[i] == PSE_PAD_TYPE_ANALOGJOY || in_type[i] == PSE_PAD_TYPE_ANALOGPAD) { in_analog_left[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255); in_analog_left[i][1] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 255) + 128, 255); @@ -1743,6 +1846,41 @@ static void check_system_specs(void) environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); } +static int init_memcards(void) +{ + int ret = 0; + const char *dir; + struct retro_variable var = { .key="pcsx_rearmed_memcard2", .value=NULL }; + static const char CARD2_FILE[] = "pcsx-card2.mcd"; + + McdDisable[0] = 0; + // Disable memcard 2 by default + McdDisable[1] = 1; + init_memcard(Mcd1Data); + // Memcard 2 is managed by the emulator on the filesystem, + // There is no need to initialize Mcd2Data like Mcd1Data. + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + SysPrintf("Memcard 2: %s\n", var.value); + if (memcmp(var.value, "enabled", 7) == 0) { + if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir) { + if (strlen(dir) + strlen(CARD2_FILE) + 2 > sizeof(Config.Mcd2)) { + SysPrintf("Path '%s' is too long. Cannot use memcard 2. Use a shorter path.\n", dir); + ret = -1; + } else { + McdDisable[1] = 0; + snprintf(Config.Mcd2, sizeof(Config.Mcd2), "%s/%s", dir, CARD2_FILE); + SysPrintf("Use memcard 2: %s\n", Config.Mcd2); + } + } else { + SysPrintf("Could not get save directory! Could not create memcard 2."); + ret = -1; + } + } + } + return ret; +} + void retro_init(void) { const char *bios[] = { @@ -1776,6 +1914,7 @@ void retro_init(void) if(!__ctr_svchax) Config.Cpu = CPU_INTERPRETER; #endif + ret |= init_memcards(); ret |= emu_core_init(); if (ret != 0) { @@ -1835,11 +1974,6 @@ void retro_init(void) pl_rearmed_cbs.gpu_peops.iUseDither = 1; spu_config.iUseFixedUpdates = 1; - McdDisable[0] = 0; - McdDisable[1] = 1; - init_memcard(Mcd1Data); - init_memcard(Mcd2Data); - SaveFuncs.open = save_open; SaveFuncs.read = save_read; SaveFuncs.write = save_write;