Skip to content

Instantly share code, notes, and snippets.

@vlumi
Forked from wesalvaro/denshadego_zuiki_ps.gpc
Last active September 1, 2024 03:01
Show Gist options
  • Save vlumi/906a68ae04c9e880a2354c9448b40f69 to your computer and use it in GitHub Desktop.
Save vlumi/906a68ae04c9e880a2354c9448b40f69 to your computer and use it in GitHub Desktop.
Use the Zuiki Densha-de-GO! controller for the Nintendo Switch on the PlayStation. Out of the box, it functions but the mascon values do not map correctly. This script translates the Nintendo Switch accepted values into values accepted by the PlayStation.
#pragma METAINFO("Zuiki Densha-de-GO! for PS4", 2, 0, "Ville Misaki")
// Original by Wes Alvaro
// Converts NS Zuiki Densha-de-GO! controller mascon values for PS4.
// Mascon values need conversion or else mascon positions are skipped.
// No changes are needed for other controls (including EB).
// Controls should be set to 「スタンダード」"Standard" + 「ダイレクト」"Direct".
#include <switch.gph>
// The mascon is controlled with the left analog stick's y-axis.
// Values are negative for braking, positive for powering, 0 when neutral.
#define MASCON SWITCH_LY
// The following values were from my controller and Titan 2.
// It's possible that these values are not consistent across all controllers.
// To account for differences, an epsilon of 5 (which is equal to half of the
// smallest range 10) is added when making comparisons. Sadly, the input values
// can't be easily recognized by a function due to their curious value jumps.
// Power Corrections:
// Input values to Titan 2 from NS Zuiki:
#define NS_B8 -96.08
#define NS_B7 -85.10
#define NS_B6 -74.90
#define NS_B5 -63.92
#define NS_B4 -52.94
#define NS_B3 -42.75
#define NS_B2 -31.76
#define NS_B1 -20.78
#define NS_N 00.39
#define NS_P1 24.71
#define NS_P2 43.53
#define NS_P3 61.57
#define NS_P4 80.39
#define NS_P5 100.0
// Output values from Titan 2 to PS4:
// The following values are accepted by the PS4 for Standard + Direct controls.
// These values don't need any adjustment as they are unrelated to hardware.
// The positions map 1-to-1 with the NS_ values above.
// Neutral position
#define PS_N 00.00
// Left stick y-axis values: Pushing the L stick down
// Brake on most trains
#define PS_B8 -100.0
#define PS_B7 -90.00
#define PS_B6 -75.00
#define PS_B5 -65.00
#define PS_B4 -60.00
#define PS_B3 -50.00
#define PS_B2 -40.00
#define PS_B1 -30.00
// Right stick x-axis values: pushing the R stick right
// Braking on Yamanote 103 & 205
// Yamanote 103 only has 4 steps, so there are gaps
#define PS_RB8 100.0
#define PS_RB7 90.00
#define PS_RB6 75.00
#define PS_RB5 65.00
#define PS_RB4 60.00
#define PS_RB3 50.00
#define PS_RB2 40.00
#define PS_RB1 30.00
// Left stick y-axis values: pushing the L stick up
// Power on most trains
#define PS_P1 40.00
#define PS_P2 50.00
#define PS_P3 60.00
#define PS_P4 80.00
#define PS_P5 100.0
// Left stick x-axis values: pushing the L stick left
// Power on Yamanote 103, which only has 4 steps
#define PS_LP1 -40.00
#define PS_LP2 -60.00
#define PS_LP3 -80.00
#define PS_LP4 -100.0
#define PS_LP5 -100.0
// Epsilon for NS input value differences between hardware:
#define E 5.0
#define NEAR(NS) mascon < NS + E
main {
fix32 mascon = get_val(MASCON);
fix32 leftY = PS_N;
fix32 leftX = PS_N;
fix32 rightX = PS_N;
if (NEAR(NS_B8)) {
leftY = PS_B8;
rightX = PS_RB8;
} else if (NEAR(NS_B7)) {
leftY = PS_B7;
rightX = PS_RB7;
} else if (NEAR(NS_B6)) {
leftY = PS_B6;
rightX = PS_RB6;
} else if (NEAR(NS_B5)) {
leftY = PS_B5;
rightX = PS_RB5;
} else if (NEAR(NS_B4)) {
leftY = PS_B4;
rightX = PS_RB4;
} else if (NEAR(NS_B3)) {
leftY = PS_B3;
rightX = PS_RB3;
} else if (NEAR(NS_B2)) {
leftY = PS_B2;
rightX = PS_RB2;
} else if (NEAR(NS_B1)) {
leftY = PS_B1;
rightX = PS_RB1;
} else if (NEAR(NS_N)) {
} else if (NEAR(NS_P1)) {
leftX = PS_LP1;
leftY = PS_P1;
} else if (NEAR(NS_P2)) {
leftX = PS_LP2;
leftY = PS_P2;
} else if (NEAR(NS_P3)) {
leftX = PS_LP3;
leftY = PS_P3;
} else if (NEAR(NS_P4)) {
leftX = PS_LP4;
leftY = PS_P4;
} else if (NEAR(NS_P5)) {
leftX = PS_LP5;
leftY = PS_P5;
}
// Set adjusted mascon position values:
// The axis not used to control the current train is ignored by the game
set_val(SWITCH_RY, NS_N); // Not used
set_val(SWITCH_RX, rightX); // Brake on Yamanote 103 & 205
set_val(SWITCH_LX, leftX); // Power on Yamanote 103
set_val(SWITCH_LY, leftY); // Power & brake on all other trains
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment