Hi geecab i managed to combine your code with my code so that my mods only get applied if airborne is loaded up in mame but all the others will use your code. I'm wondering if i should maybe add street drivin' to it because it kinda had a similar issue but not as bad. I notice if i only shift the output left by 7 bits instead of 8 the steering in airborne becomes more like the original games and you can get away with using a port_minmax of 0x000, 0x7ff with a center point of 0x400 or 0x400, 0xbff with a center point of 0x800. It applied EMA smoothing to the wheel output so that it doesn't fluctuate too wildly when turning the wheel and seems to make the wheel stay in alignment when driving for long periods but crashing and holding the wheel left or right or staying offroad until the timer runs out with the wheel held left or right will knock the centerpoint out of place even if you have the wheel only turned a little bit.
Code: [Select]
// Merge in the wheel edge latch bit
if (m_hdc68k_wheel_edge)
{
result ^= 0x4000;
printf("hdc68k_port1_r: merge latch result=%04X m_hdc68k_last_wheel=%04X\n", result, m_hdc68k_last_wheel);
m_hdc68k_wheel_edge = 0;
}
m_hdc68k_last_port1 = result;
return result;
}
uint16_t harddriv_state::hda68k_port1_r()
{
uint16_t result = m_a80000->read();
if (m_hdc68k_wheel_edge)
{
result ^= 0x4000;
printf("hda68k_port1_r: merge latch result=%04X m_hdc68k_last_wheel=%04X\n", result, m_hdc68k_last_wheel);
m_hdc68k_wheel_edge = 0;
}
return result;
}
uint16_t harddriv_state::hdc68k_wheel_r()
{
static float ema_wheel = 0.0f; // Persistent storage of EMA across calls
static const float alpha = 0.05f; // Smoothing factor for EMA, adjustable
static bool initialized = false; // To check if ema_wheel is initialized
uint16_t new_wheel = m_12badc[0].read_safe(0xffff);
// Display the wheel position when left shift is pressed
if (machine().input().code_pressed(KEYCODE_LSHIFT))
{
popmessage("wheel new=%04X", new_wheel);
}
// Determine if the current game is Hard Drivin's Airborne
bool is_hdrivair = (machine().system().name == std::string("hdrivair"));
// Separate edge detection logic for hdrivair and non-hdrivair games
if (is_hdrivair)
{
// Use a specific mask for Hard Drivin's Airborne (placeholder for future changes)
if ((m_hdc68k_last_wheel & 0x0c00) != (new_wheel & 0x0c00))
{
m_hdc68k_wheel_edge = m_hdc68k_wheel_edge == 0 ? 1 : 0;
}
}
else
{
// Use the default mask for other games
if ((m_hdc68k_last_wheel & 0x0c00) != (new_wheel & 0x0c00))
{
m_hdc68k_wheel_edge = m_hdc68k_wheel_edge == 0 ? 1 : 0;
}
}
if (is_hdrivair)
{
// EMA calculation only for Hard Drivin's Airborne
if (!initialized)
{
ema_wheel = new_wheel; // Initialize EMA with the first reading
initialized = true;
}
else
{
ema_wheel = alpha * new_wheel + (1 - alpha) * ema_wheel; // Update EMA
}
}
else
{
// For other games, use the raw wheel data without EMA
ema_wheel = new_wheel;
}
m_hdc68k_last_wheel = new_wheel;
uint16_t output;
if (is_hdrivair)
{
// Hard Drivin's Airborne specific processing
output = (static_cast<uint16_t>(ema_wheel) << 7) & 0xFFF0; // Shift and mask for hdrivair
}
else
{
// For other games, shift left by 8 and set the last hex digit to 0xFF
output = (static_cast<uint16_t>(ema_wheel) << 8) | 0xFF;
}
// Return the processed wheel value
return output;
}