Main Restorations Software Audio/Jukebox/MP3 Everything Else Buy/Sell/Trade
Project Announcements Monitor/Video GroovyMAME Merit/JVL Touchscreen Meet Up Retail Vendors
Driving & Racing Woodworking Software Support Forums Consoles Project Arcade Reviews
Automated Projects Artwork Frontend Support Forums Pinball Forum Discussion Old Boards
Raspberry Pi & Dev Board controls.dat Linux Miscellaneous Arcade Wiki Discussion Old Archives
Lightguns Arcade1Up Try the site in https mode Site News

Unread posts | New Replies | Recent posts | Rules | Chatroom | Wiki | File Repository | RSS | Submit news

  

Author Topic: Mame hacks that make driving games play better with mouse/spinner/360wheel  (Read 22138 times)

0 Members and 1 Guest are viewing this topic.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Hi there!

Not sure if this is of interest to anyone, I hacked a ps2 mouse and built a mame driving cab recently. For games that used 360 wheels (pole position, change lanes, super sprint etc) it was great. For games that limited the turning circle of the wheel (outrun, wec le mans) it wasn't so good. I found that if I over steered, the wheel's central position would wander. I've kind of got used to it, but I notice when my friends have a go its takes them a while to adjust.

So I decided to see if I could hack the mame source code a bit. My hack works so that the position of the wheel when the game starts up will always be its central position (players car will travel in a straight forward direction). If you then spin the wheel, say, 3 spins clockwise (hard right), you'll be required to spin the wheel back anti-clockwise 3 times in order to get the car going straight again. Spinning your mouse/spinner/360wheel beyond the limits of what the actual arcade game wheel would allow just means the game's maximum left turn or right turn value is applied.

Hope that make sense, here's a youtube clip of me trying to show that working...



I'll post my mame source code changes shortly incase someone else is thinking of doing the same thing!
« Last Edit: March 10, 2013, 09:36:35 am by geecab »

BadMouth

  • Moderator
  • Trade Count: (+6)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9226
  • Last login:Yesterday at 09:54:06 am
  • ...
Sounds good for those with 360 degree wheels.

Does each driver in MAME have to be modified, or will this work with with all the driving games?

On Hard Drivin', does the wheel do as many turns as the original arcade one before hitting the virtual end?
(it had a 10 turn pot, but IIRC the wheel turned 7+ times lock to lock)



FYI, years ago, bkenobi had a fix using glovepie.
http://forum.arcadecontrols.com/index.php/topic,92363.0.html

BadMouth

  • Moderator
  • Trade Count: (+6)
  • Full Member
  • *****
  • Offline Offline
  • Posts: 9226
  • Last login:Yesterday at 09:54:06 am
  • ...
I hadn't thought about this before (since I don't have a 360 degree wheel), but this is an option it would be nice to see in the official MAME source along with proper shifter support.

If you have the skills to make it optional, and in a way that MAMEDev finds acceptable, consider submitting it.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Thanks for your replies Badmouth, really great 'Driving Cab Information' thread by the way. Really helped me out a lot when I was putting my cab together. I think I have read about that glovepie fix you mentioned, but I just fancied modifying the mame source rather than having other stuff running in the background. I think I will submit something to MAMEDev at some point, but to be honest, these are pretty nasty hacks at the moment, am just enjoying messing around with the source code. I haven't even made my modifications command line configurable either so while it will make outrun etc play better, it could well break other games. 

Getting hard drivin' going was tricky, I don't think that multiple turning pot thing (with some strange latching bit when the wheel turns 360 degrees past the central point) has ever been emulated correctly. My hack for hard drivin is different to my outrun/hang-on/weclemans hack, I shall post the hack I made specifically for hard drivin in another post a little later on.

So regarding the outrun/hang-on/weclemans change, you don't have to change all the individual game driver files, just one file (found in src/emu/ioport.c). Also, I'm editing mame source version 0145. You are looking for a function called "apply_analog_min_max", below is what the function looked like originally (before my hack):-


Code: [Select]
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
{
/* take the analog minimum and maximum values and apply the inverse of the */
/* sensitivity so that we can clamp against them before applying sensitivity */
INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);

/* for absolute devices, clamp to the bounds absolutely */
if (!analog->wraps)
{
if (value > adjmax)
value = adjmax;
else if (value < adjmin)
value = adjmin;
}

/* for relative devices, wrap around when we go past the edge */
else
{
INT32 range = adjmax - adjmin;
/* rolls to other end when 1 position past end. */
value = (value - adjmin) % range;
if (value < 0)
value += range;
value += adjmin;
}

return value;
}


Now, outrun/hang-on/weclemans used an absolute device for steering. 'value' is passed into the function as the position of where your mouse x axis is. 'value' is limited to adjmax or adjmin if you moved your mouse further than the arcade game allowed.

So now onto my fix, basically, if 'value' is limited by adjmax or adjmin, I make a note of the difference (I called it "spin_history" for some reason). Then the next time I'm in the apply_analog_min_max, I add the spin_history (which maybe positive or negative depending on which way the wheel was turned) to the 'value' passed in, which then may be limited again, which I then save the spin_history again, etc.. etc...  Finally, I only want this to happen for the IPT_PADDLE type because that is the steering wheel device, other devices also go through this function too (IPT_PEDALS for example) which I don't want to alter:-


Code: [Select]
INT32 spin_history = 0;
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
{
/* take the analog minimum and maximum values and apply the inverse of the */
/* sensitivity so that we can clamp against them before applying sensitivity */
INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);

/* for absolute devices, clamp to the bounds absolutely */
if (!analog->wraps)
{
if(analog->field->type == IPT_PADDLE)
{
value = value + spin_history;

spin_history = 0;

if(value > adjmax)
{
spin_history = value - adjmax;
value = adjmax;
}
else if(value < adjmin)
{
spin_history = value - adjmin;
value = adjmin;
}
}
else
{
if (value > adjmax)
value = adjmax;
else if (value < adjmin)
value = adjmin;
}
}
/* for relative devices, wrap around when we go past the edge */
else
{
INT32 range = adjmax - adjmin;

/* rolls to other end when 1 position past end. */
value = (value - adjmin) % range;
if (value < 0)
value += range;
value += adjmin;
}

return value;
}


There is an obvious bug with this, like if you span your wheel enough (moved you mouse in one direction enough) spin_history would get so large (or so small) that it too would wrap around. I could sort this out at some point though.

Anyways, I think that's it for now as I think I'm going on a bit, hope some of this made sense  ;)
« Last Edit: March 10, 2013, 09:31:15 am by geecab »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Here is my hard drivin' / race drivin hack. By the way, its the Compact British version of hard drivin' (harddrivcb) I am currently using (because it runs much faster than the cockpit version). Important to note though as the wheel does not use a Potentiometer in the compact version, so I'm not sure my hack would work on the cockpit version. I'm using the 0145 mame sources to build from. This has all been pretty much a case of trial an error but it does appear to work really nicely now. Be good to hear from anyone who knows anything about hard drivin's bit latching setting (set when the wheel passes 360 degrees) as I'm probably barking up the wrong tree!

Ok so first off, I modified the apply_analog_min_max function in src/emu/ioport.c agian. The big comment should hopefully explain what I'm up to...
Code: [Select]
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
{
/* take the analog minimum and maximum values and apply the inverse of the */
/* sensitivity so that we can clamp against them before applying sensitivity */
INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);

/* for absolute devices, clamp to the bounds absolutely */
if (!analog->wraps)
{
if(analog->field->type == IPT_PADDLE)
{
//Limit the turning circle so that you can not turn the wheel more than 270 degrees to
//the left or 270 degrees to the right. I limited the turning circle because things
//seemed to mess up if I turned more that 360 degress left or right. The values I've
//hardcoded adjmax/admin may need to be altered depending on your analogue PADDLE settings.
//Press the Left Shift key in game and a small debug window appears for a few seconds
//(one of the mame developers must have added this), it shows you what position mame thinks the
//arcade wheel is in. It should be the same value as reported by the game if you Press F2
//(invoke the service menu), then pressing 5/6, and turning key (1) on CONTROL SIGNALS.
//From what I can work out, the value 0x800 in the debug window should be
//dead center, 0xC00 is about 270 degress to the right of the central position, 0x400 is
//about 270 degrees to the left of the central position. If you use a different
//PADDLE SENSITIVITY, the values shown in the debug window may exceed the 0x400 to 0x800
//limit in which case you probably what to a adjust the hard coded limits of adjmax/adjmix
//(by trial and error, holding the left shift key down in game and see how things look/play).
//
//This is what worked for me with my analogue settings set to:
//    PADDLE DIGITAL SPEED = 0
//    PADDLE AUTOCENTER SPEED = 0
//    PADDLE SENSITIVITY = 25
adjmax = 150016; //Stop the steering going over 0x0C00, before the latch bit is set
//Central position seems to be 0x0800
adjmin = -150016; //Stops the steering going under 0x0400, before the latch bit is set


value = value + spin_history;

spin_history = 0;

if(value > adjmax)
{
spin_history = value - adjmax;
value = adjmax;
}
else if(value < adjmin)
{
spin_history = value - adjmin;
value = adjmin;
}
}
else
{
if (value > adjmax)
value = adjmax;
else if (value < adjmin)
value = adjmin;
}
}

/* for relative devices, wrap around when we go past the edge */
else
{
INT32 range = adjmax - adjmin;
/* rolls to other end when 1 position past end. */
value = (value - adjmin) % range;
if (value < 0)
value += range;
value += adjmin;
}

return value;
}


With the hack above, things worked quite well, but I found the steering would occasionally wander away from dead center after doing a few erratic turns. I guessed it might be something to do with the wheel edge/latching processing which I don't really understand. So I found in src/mame/machine/harddriv.c a function which appears to do something with this latching bit each time the wheel goes past its central position and I modified it and it fixed the wandering problem.

This is what the function originally looked like...
Code: [Select]
READ16_HANDLER( hdc68k_wheel_r )
{
harddriv_state *state = space->machine().driver_data<harddriv_state>();

/* grab the new wheel value and upconvert to 12 bits */
UINT16 new_wheel = input_port_read(space->machine(), "12BADC0") << 4;

/* hack to display the wheel position */
if (space->machine().input().code_pressed(KEYCODE_LSHIFT))
{
popmessage("%04X", new_wheel);
}

/* if we crossed the center line, latch the edge bit */
if ((state->m_hdc68k_last_wheel / 0xf0) != (new_wheel / 0xf0))
state->m_hdc68k_wheel_edge = 1;

/* remember the last value and return the low 8 bits */
state->m_hdc68k_last_wheel = new_wheel;
return (new_wheel << 8) | 0xff;
}

And this is what it looked like after my modification (Once again big comment should hopefully explain what I'm up to)...
Code: [Select]
UINT16 g_latchpoint = 0x860; //Ajust this g_latchpoint by trial and error. You want it so that
//when your wheel is dead center and you press left shift key in game, the value reported is 0x800.
//Setting the latchpoint as 0x860 was dead center for me (not sure why this is, I had calibrated
//everything correctly in the F2 service/configuration menu).
READ16_HANDLER( hdc68k_wheel_r )
{
harddriv_state *state = space->machine().driver_data<harddriv_state>();

/* grab the new wheel value and upconvert to 12 bits */
UINT16 new_wheel = input_port_read(space->machine(), "12BADC0") << 4;

/* hack to display the wheel position */
if (space->machine().input().code_pressed(KEYCODE_LSHIFT))
{
popmessage("%04X", new_wheel);
}

if(new_wheel == g_latchpoint)
{
if(state->m_hdc68k_last_wheel != g_latchpoint)
{
state->m_hdc68k_wheel_edge = 1;
}
}
else
{
//I noticed after many harsh turns of the wheel, mame's perception of where
//the arcade wheel is (shows by pressing the left shift key in game) would
//wander from what was actually reported in the hard drivin' serivce menu
//(Pressing F2 in-game and view the CONTROL SIGNALS page). I guessed this was
//something to do with the edge/latching bit stuff that should get set when
//the wheel passes the central position. My modification is to make sure the
//m_hdc68k_wheel_edge thing is set when we pass the central position, even
//if we don't hit the value exactly.
if(new_wheel > g_latchpoint)
{
if(state->m_hdc68k_last_wheel < g_latchpoint)
{
state->m_hdc68k_wheel_edge = 1;
}
}
else if (new_wheel < g_latchpoint)
{
if(state->m_hdc68k_last_wheel > g_latchpoint)
{
state->m_hdc68k_wheel_edge = 1;
}
}
}

/* remember the last value and return the low 8 bits */
state->m_hdc68k_last_wheel = new_wheel;
return (new_wheel << 8) | 0xff;
}


Finally, I only have a high/low shifter and wanted to use the 4 speed manual gear option. As I've got shift up and shift down firebuttons on my CP I decided to try and use them. So this is my shifter hack (I've done similar hacks for games like night driver, Sprint 1), let me know if you're interested in seeing them.

Once again, in src/mame/machine/harddriv.c I found the function that takes care of the gears, this is what it originally looked like...
Code: [Select]
READ16_HANDLER( hdc68k_port1_r )
{
harddriv_state *state = space->machine().driver_data<harddriv_state>();
UINT16 result = input_port_read(space->machine(), "a80000");
UINT16 diff = result ^ state->m_hdc68k_last_port1;

/* if a new shifter position is selected, use it */
/* if it's the same shifter position as last time, go back to neutral */
if ((diff & 0x0100) && !(result & 0x0100))
state->m_hdc68k_shifter_state = (state->m_hdc68k_shifter_state == 1) ? 0 : 1;
if ((diff & 0x0200) && !(result & 0x0200))
state->m_hdc68k_shifter_state = (state->m_hdc68k_shifter_state == 2) ? 0 : 2;
if ((diff & 0x0400) && !(result & 0x0400))
state->m_hdc68k_shifter_state = (state->m_hdc68k_shifter_state == 4) ? 0 : 4;
if ((diff & 0x0800) && !(result & 0x0800))
state->m_hdc68k_shifter_state = (state->m_hdc68k_shifter_state == 8) ? 0 : 8;

/* merge in the new shifter value */
result = (result | 0x0f00) ^ (state->m_hdc68k_shifter_state << 8);

/* merge in the wheel edge latch bit */
if (state->m_hdc68k_wheel_edge)
result ^= 0x4000;

state->m_hdc68k_last_port1 = result;
return result;
}


And this is what it looked like after my modification...
Code: [Select]
int g_gear = 1;
int g_have_seen_shift = 0;
READ16_HANDLER( hdc68k_port1_r )
{
harddriv_state *state = space->machine().driver_data<harddriv_state>();
UINT16 result = input_port_read(space->machine(), "a80000");
int has_changed = 0;

if(!g_have_seen_shift)
{
if(result != 0xFFFF)
{
if (result & 0x0100) //SHIFT UP
{
//printf("shift up\n");
g_have_seen_shift = 1;
g_gear++;
if(g_gear > 4) g_gear = 4;

has_changed = 1;
}
if (result & 0x0200) //SHIFT DOWN
{
//printf("shift down\n");
g_have_seen_shift = 1;
g_gear--;
if(g_gear < 1) g_gear = 1;

has_changed = 1;
}
}
}
else
{
if ((result != 0xFEFF) && (result != 0xFDFF))
{
//printf("shift OFF result=0x%X\n", result);
g_have_seen_shift = 0;
}
else
{
//printf("shift STILL ON! result=0x%X\n", result);
}
}


if(has_changed)
{
if (g_gear == 1)
{
//printf("gear1\n");
state->m_hdc68k_shifter_state = 1;
}
if (g_gear == 2)
{
//printf("gear2\n");
state->m_hdc68k_shifter_state = 2;
}
if (g_gear == 3)
{
//printf("gear3\n");
state->m_hdc68k_shifter_state = 4;
}
if (g_gear == 4)
{
//printf("gear4\n");
state->m_hdc68k_shifter_state = 8;
}
}

/* merge in the new shifter value */
result = (result | 0x0f00) ^ (state->m_hdc68k_shifter_state << 8);

/* merge in the wheel edge latch bit */
if (state->m_hdc68k_wheel_edge)
result ^= 0x4000;

state->m_hdc68k_last_port1 = result;
return result;
}

Then in mame the Key you define for '2nd gear' will act like a shift up, and the key that you define for '1st gear' will act like a shift down. Also, while your defining keys in mame, define the clutch key as the same keys as you chose for the '1st gear', '2nd gear' and 'turn key'. That way you should be able to make really quick smooth shift changes whilst automatically pressing the clutch down.

I think that is everything  :)

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #5 on: September 08, 2013, 04:20:42 am »
Hi, sorry to resurrect an old thread, but this is exactly what I'm after. I've got the same problem with the floating centre point on my mame'd chase HQ cab (which has a steering opto, connected to my pc via an optipac).

I've recompiled mame with your file as described, but am still getting the floating centre point issue. Are there any setup options I might have missed? Thanks for any further guidance.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #6 on: September 08, 2013, 05:31:06 am »
Hi! Cheers for giving my hacks a go :) I don't think you've missed any setup options. What version of mame are you compiling with and what game are you trying?

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #7 on: September 08, 2013, 08:48:38 am »
Thanks, I'm using mame 145 as that's what you said you were using. It's the first time I've compiled mame, but it seemed to work. I simply copy and pasted your text into the file over the original text, so I think I did that right too.

The game I've tried it with so far is SCI. It seems better than without the hack, but I'm not sure. I've played around with the various analogue settings in mame.

Any chance you could post a compiled version with your hack, just so I could check it's not a problem with my version? Or just the hacked file, then I could use that when compiling? Thanks very much.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #8 on: September 08, 2013, 10:01:14 am »
>>I'm using mame 145 as that's what you said you were using
Thanks, just wanted to make sure.

>>I simply copy and pasted your text into the file over the original text, so I think I did that right too.
Yes that's all you should need to do.

I've just had a go with SCI and it doesn't work for me either. Not sure what SCI is doing differently to outrun/hangon/wecleman, but I'd have to debug it to find out.

How about running outrun, hang-on or wec le man to verify if the fix is working?

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #9 on: September 08, 2013, 11:48:26 am »
good idea! i've just tried all three and unfortunately theyre not working. the steering wheel is configured to Paddle Analog and shows up as Mouse X. I must have compiled Mame correctly as it works, which maybe leaves my hacked ioport.c file as the culprit? i'll double check it, but if you've got one you can post that would be great! Thanks.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #10 on: September 08, 2013, 12:41:52 pm »
>>the steering wheel is configured to Paddle Analog and shows up as Mouse X
Should be fine.

>>I must have compiled Mame correctly as it works, which maybe leaves my hacked ioport.c file as the culprit? i'll double check it, but if you've got one you can post that would be great!
OK, I've zipped up the exe I compiled and my ioport.c. The zipped file is called build_0145_outrun.zip and you can download it here:

http://www11.zippyshare.com/v/73958392/file.html

Hope this helps! :)

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #11 on: September 08, 2013, 04:15:49 pm »
Thanks so much!! I've just been playing Outrun on my Chase HQ cab. Steering is perfect!

If you ever get a chance to look at SCI please let me know. I'll do whatever I can to help, but as you can probably gather, I'm a total novice! This really should be implemented in MAME as it improves the experience of playing these games so much.

Thanks again!

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #12 on: September 09, 2013, 03:56:59 am »
Excellent stuff huwman, really glad you've got things going! I'll have a look at SCI next weekend as I quite intrigued as to what it does differently to the others.

>>This really should be implemented in MAME as it improves the experience of playing these games so much.
Cool, I agree too :) I think I'll try and come up with the cleaner solution for it at some point, making it work in the latest version of mame too (ioport.c stuff changed quite significantly in v0147, which is why I've just stuck to editing the old v0145 source), then submit it to the mame team and see what they say.

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #13 on: September 09, 2013, 03:52:01 pm »
Yes, it's great being able to play some other games properly, after all the money I've spent on Jpacs and optipacs etc!!

I've tried messing around with the dipswitches on SCI in MAME, as there are options for 360 or 270 wheels, but it doesnt seem to make a difference. I also tried Superchase Criminal Termination, as its part of the same series, and that has the same problem.

But Chase HQ works fine, and so does Power Drift!

Thanks again, and I'm looking forward to hearing if you can make any progress with SCI!


geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #14 on: September 09, 2013, 06:30:46 pm »
I think I've got SCI working now. Outrun etc uses IPT_PADDLE for the steering. SCI uses IPT_AD_STICK_X. So I hacked the apply_analog_min_max function in ioport.c some more. In the apply_analog_min_max function, I now check for both types of steering methods (IPT_PADDLE or IPT_AD_STICK_X), so you should be able to run Outrun or SCI with the same exe and the steering will work as expected.

Here what my apply_analog_min_max function looks like now (there just one line that is different from the original outrun hack):

Code: [Select]
INT32 spin_history = 0;
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
{
/* take the analog minimum and maximum values and apply the inverse of the */
/* sensitivity so that we can clamp against them before applying sensitivity */
INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);

/* for absolute devices, clamp to the bounds absolutely */
if (!analog->wraps)
{
if((analog->field->type == IPT_PADDLE) || (analog->field->type == IPT_AD_STICK_X))
{
value = value + spin_history;

spin_history = 0;

if(value > adjmax)
{
spin_history = value - adjmax;
value = adjmax;
}
else if(value < adjmin)
{
spin_history = value - adjmin;
value = adjmin;
}
}
else
{
if (value > adjmax)
value = adjmax;
else if (value < adjmin)
value = adjmin;
}
}
/* for relative devices, wrap around when we go past the edge */
else
{
INT32 range = adjmax - adjmin;

/* rolls to other end when 1 position past end. */
value = (value - adjmin) % range;
if (value < 0)
value += range;
value += adjmin;
}

return value;
}

Anyways, I've zipped up the exe I compiled, and my ioport.c. The zipped file is called build_0145_sci.zip and you can download it here:
http://www7.zippyshare.com/v/18199545/file.html

Hope this helps!  :)

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #15 on: September 10, 2013, 03:49:33 pm »
Thank you! I've played SCI several times with this revision. To begin with, it seems to be totally fixed, but the centre then starts to drift a bit by the end of the level.

This happened once after the car had spun out, but the other times started to happen towards the end of the level when  driving next to the train. It almost seemed like the appearance of the train triggered the centre to drift! I'll play it through several more times and see if any patterns emerge.

Thanks again!

huwman

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 8
  • Last login:February 13, 2014, 08:32:48 am
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #16 on: September 11, 2013, 09:54:41 am »
Interesting.....I tried it again this morning and SCI works fine now! must have been something to do with my setup. sorry!

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #17 on: February 07, 2017, 05:26:04 am »
Hello!

Sorry if i resurrected this old 3D but i'm really interested to know if there are some news about it....or if with new mame version this kind of "issue" was solved or improved....

Actually i'm working on a Original Jamma Driving Upright cabinet to convert it on a mame cab.   

Thant you for your work dude!


geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #18 on: February 09, 2017, 05:13:37 pm »
Hi! Thanks for the interest! I'm still running my mame cab with a 360 wheel with my hacked versions of mame - I am still happy with them.

To be honest, I got a bit side tracked with other projects and forgot about submitting anything to the mamedevs about this :p I shall post something to them soon I think (Will post a link on here to the thread when I do).

Out of interest, what sort of wheel are going to have in your mame cab (360 or limited turning circle)??

:)

Howard_Casto

  • Idiot Police
  • Trade Count: (+1)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 19400
  • Last login:April 21, 2024, 11:59:54 pm
  • Your Post's Soul is MINE!!! .......Again??
    • The Dragon King
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #19 on: February 09, 2017, 06:30:56 pm »
You know, something that I haven't really explored yet is the fact that with lua scripting, hacks shouldn't be necessary anymore.  As memory can be read and write, it should be possible to manipulate controls without changing drivers.  I'm just getting back into mame atm, but it looks promising.

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #20 on: February 19, 2017, 12:08:19 pm »
Hi! Thanks for the interest! I'm still running my mame cab with a 360 wheel with my hacked versions of mame - I am still happy with them.

To be honest, I got a bit side tracked with other projects and forgot about submitting anything to the mamedevs about this :p I shall post something to them soon I think (Will post a link on here to the thread when I do).

Out of interest, what sort of wheel are going to have in your mame cab (360 or limited turning circle)??

:)

Ehiii thank you for reply me!

About your question, is a bit hard to answer....i had found this old "original cab" (maybe an italian remake of CISCO HEAT)with a WORLD RALLY (GAELCO) jamma board, and the pinout was set to ANALOG CONTROL (in this kind of jamma you could setup 3 way of control joy/analog/digital ).

My wheel are 360  suppose analog (see the image below), maybe in the beginning there is digital, with a pcb for convert the signal....

I love your project, and SEGA MONACO GP it's one of my first game i would play on this cab, SPY HUNTER is the other (i will change the original gear maybe to another with some button, the TURBO SWITCHER could be working.....)

At the moment i miss the monitor, so i cant make any hardware test, i plan soon to add a PC with MAME (arcadevga and other interface to old controls) without removing the original jamma harness.

I would use both....jamma original and pc!

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #21 on: February 19, 2017, 04:15:03 pm »
That wheel is optical, not analog (potentiometer).
If the pcb was set to stick, would you suppose your wheel was a digital stick?

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #22 on: February 19, 2017, 05:26:59 pm »
That wheel is optical, not analog (potentiometer).
If the pcb was set to stick, would you suppose your wheel was a digital stick?

mmm no i found the online the manual of WORD RALLY, the wheel is set to "360 steerling wheel optical"...no other clue  :dizzy: dip 4 and 5 on the game settings are ON

sorry for the mistake....

http://www.gamesdatabase.org/Media/SYSTEM/Arcade/Manual/formated/World_Rally_-_1993_-_Gaelco.pdf

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #23 on: February 21, 2017, 06:54:07 pm »
Cool, thanks for the pics! Yes indeed you have a 360 optical wheel. By the looks of things, a few optical disk teeth are missing (Seen in your 2nd picture) so that's going to be a problem should you try and somehow get the sensor circuit working with mame...

Considering your cab's current condition, I think I'd just recommend quickly wiring/hacking up an old PS2 mouse to your steering mechanism and trying a load of games out and seeing how you get on (Though I probably would recommend this approach considering its what I did with my cab!   :P )

You be able to play all the driving games. Driving games such as Pole Position, SuperSprint, Buggy Boy, APB, World Rally, Turbo, My Monaco GP remake ;) - They will will all play really great. You'll also have the advantage of being able to play lots of non-driving games on it too (Cameltry, PuzzLoop, Arkanoid, Tempest, Warlords etc...).

Things like OutRun, Super Hang-On, Chase HQ, Wec-le-Mans, Daytona, Sega Rally will all still be very playable, but after a few games you'll probably get a little annoyed (as did I) with the way the steering centre position wanders (as described in this thread). If so, let me know, I'll fix my download links and you could give my modified versions of mame a try for yourself.

I see from another thread you want to play SpyHunter and considering what you should do about your current gear shifter (whether to add more fire buttons to the control panel). I also encountered the same dilemma when building my driving cab. In the end I just stuck with the Hi/Low shifter. By the side of the shifter I added 2 buttons, these buttons are 'Shift up' and 'Shift down' buttons, used for driving games that have more than 2 gears (E.g. Virtua Racing, Super Monaco GP). I also bought a bunch of cheap black push buttons on ebay that I concealed into the control panel that I use for things like the SpyHunter weapons, Daytona Car View point, Super Spint player 2 etc... Take a quick look at my "Pole Position II cab scratch build" thread as there are quite a few pictures of my control panel, it might help give you a few ideas.

Hope this helps  :)

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Online Online
  • Posts: 9402
  • Last login:Today at 04:20:33 pm
  • Designated spam hunter
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #24 on: February 21, 2017, 10:04:08 pm »
Considering your cab's current condition, I think I'd just recommend quickly wiring/hacking up an old PS2 mouse to your steering mechanism
If you don't have a spare mouse but do have an Arduino, use StefanBurger's Illuminated Spinner firmware.

The hex firmware file is on the thingiverse page.

Load the hex on the board using ArduinoBuilder.

Four wires and an optional jumper connect to the Pro Micro board:
- Ground (2nd pin, top row, blue wire)
- 5v (4th pin, top row, red wire)
- Data A (1st pin, bottom row, green wire)
- Data B (2nd pin, bottom row, white wire)
- X-axis enable jumper (3rd to 8th pin, bottom row) *not shown*  Without this jumper it operates on the Y-axis.




Scott

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #25 on: February 22, 2017, 12:45:49 am »
With minimal-to-no tweaking you could successfully use the genuine arcade encoder on your cabinet as well, without the need for additional hardware other than arduino.
The mouse hack is obsolete nowadays
« Last Edit: February 22, 2017, 02:15:01 am by baritonomarchetto »

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #26 on: February 22, 2017, 05:31:39 am »
Cool, thanks for the pics! Yes indeed you have a 360 optical wheel. By the looks of things, a few optical disk teeth are missing (Seen in your 2nd picture) so that's going to be a problem should you try and somehow get the sensor circuit working with mame...

I  fixed it with a piece of plastic bottle and a bit of black paint... :P


Considering your cab's current condition, I think I'd just recommend quickly wiring/hacking up an old PS2 mouse to your steering mechanism and trying a load of games out and seeing how you get on (Though I probably would recommend this approach considering its what I did with my cab!   :P )


I would to use an external controller looks like OPTI PAC, but made from an italian user (and friend) of arcadeitalia forum, the board name is SMARTASD. You can controls opti and analogs device and, with and easy external circuit, others 8 light buttons or simply game light trought mamehook.  http://www.arcadeitalia.net/viewtopic.php?f=43&t=20198 

I see from another thread you want to play SpyHunter and considering what you should do about your current gear shifter (whether to add more fire buttons to the control panel). I also encountered the same dilemma when building my driving cab. In the end I just stuck with the Hi/Low shifter. By the side of the shifter I added 2 buttons, these buttons are 'Shift up' and 'Shift down' buttons, used for driving games that have more than 2 gears (E.g. Virtua Racing, Super Monaco GP). I also bought a bunch of cheap black push buttons on ebay that I concealed into the control panel that I use for things like the SpyHunter weapons, Daytona Car View point, Super Spint player 2 etc... Take a quick look at my "Pole Position II cab scratch build" thread as there are quite a few pictures of my control panel, it might help give you a few ideas.

Hope this helps  :)

At the moment im in front of two working options (looking for better to play driving games and SPY HUNTER also) :

- remove my old steerling wheel and replace it with an original SPY HUNTER wheel (yes i found one), so i play definally fine SH but bad the other 360 gams (right?)

- leave the original 360 wheel and use the UP/DOWN shifter gear....with NOS butto (pic below) (for the fire on SH), and add some "view" buttons usefuls for both kind of games...

I'm totally noob for driving cab conversion....im on yours hands!  :notworthy:

PS: Yes...please reup your mame version hack....  :cheers:

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #27 on: February 22, 2017, 05:47:18 am »
I liked jammasd as much as i dislike smartasd: it's mainly a microcontroller board priced 10 times more than an arduino leonardo... a seller deal only.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #28 on: February 22, 2017, 05:54:07 pm »
I must admit, I don't really know much about smartasd boards so I can't really comment. But I can imagine it would be a cool project getting your existing sensor circuit working with an optipac/arduino/smartasd type board so go for it :) BTW. Well done repairing your optical disk using a plastic bottle, neat idea!

The NOS gear shift with the side button looks good, and its cool if you can get hold of a Spy Hunter controller too.

Unfortunately, it is fact that if you go for '360' style steering mechanism (PolePostion/SuperSprint/Arkanoid), then some 'Limited turning circle' style  games (SpyHunter/Daytona/OutRun) might not play so great. And similarly the opposite is true in that if you go for a 'Limited turning circle' style steering mechanism, then '360' style steering mechanism games won't play so great (or not at all).

The problem you are going to have is building a driving cab that suits all your needs, as there is not one solution that suits everything. Everyone who has built a driving cab has had a similar dilemma at some point. I guess only really you can decide what to go for based on what games are most important to you :)

>>PS: Yes...please reup your mame version hack..
No worries. I'll try and upload them this weekend.

Thorvald

  • Trade Count: (0)
  • Jr. Member
  • **
  • Offline Offline
  • Posts: 6
  • Last login:April 15, 2022, 01:36:50 pm
  • I want to build my own arcade controls!
Thanks for all the work on this!  I just finished my cabinet and have a pair of spinners with the 6 inch wheel attachment from Ultimarc.  Works great except for those games that hate 360's...

I'm running the latest 1.82 so I'll likely have to setup a dev environment and apply your changes to a newer build.  Then also look into possible LUA methods (assuming we can get to that low of a level).

Cheers
   Tim

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Sorry for the delay!

Here's my mame steering hack build (Mame version v0.148 Windows 32bit).

mame_0148_geecab_hack_v1_0.zip

In the zip file there is a 'mame_0148_geecab_hack_v1_0.txt' file that reads:
Code: [Select]
Mame v0.148 Geecab Hack v1.0
============================

In this build, if you run:

        mame.exe -showusage

You should see that I've added 2 new options in the CORE MISC OPTIONS section:-

 -hack_steering       Hack: Permanently associate the mouse's axis position at
                      rom start, with the game's central steering wheel
                      position.

 -hack_gears_semiauto Hack: Allows shiftup & shiftdown for racing games that
                      use more than 2 gears. '1st gear' key shifts you down,
                     '2nd gear' key shifts you up.


Example usage
=============

To run Outrun, ChaseHQ, SCI, HangOn, SuperHangOn, PowerDrift, Harddrivin
(Compact version only), RaceDrivin (Compact version only), Wec Le Mans,
KonamiGT, etc... so that they're play better with mouse apply the following:

        mame.exe -mouse -hack_steering

For Harddrivin and RaceDrivin you can also apply the -hack_gears_semiauto
option:

        mame.exe -mouse -hack_steering -hack_gears_semiauto

Note. The -hack_gears_semiauto option currently only works for Harddrivin
(any version) and RaceDrivin (any version).


Source code changes
===================
I modified the following 6 files (Included in the 'hacked_src_files'
directory. Search for //GEECAB comments to give you an idea where I made
my changes):
        mame0148s\mame\src\emu\emuopts.h
        mame0148s\mame\src\emu\emuopts.c
        mame0148s\mame\src\emu\ioport.c
        mame0148s\mame\src\emu\mame.c
        mame0148s\mame\src\emu\ui.c
        mame0148s\mame\src\mame\machine\harddriv.c


Other
=====
You can still download the original mame v0148 source and binaries from:
        http://mamedev.org/oldrel.html

Please be a little prepared as you visit the mediafire site, you might get adverts for other software appear, encoraging you to download something else. Just make sure you only click on the big green 'Download' button near to top right of the page, and the file that you download to your computer is called "mame_0148_geecab_hack_v1_0.zip" (Its 20MB in size).
« Last Edit: March 08, 2017, 07:49:01 pm by geecab »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Thanks for all the work on this!  I just finished my cabinet and have a pair of spinners with the 6 inch wheel attachment from Ultimarc.  Works great except for those games that hate 360's...

I'm running the latest 1.82 so I'll likely have to setup a dev environment and apply your changes to a newer build.  Then also look into possible LUA methods (assuming we can get to that low of a level).

Cheers
   Tim
Hi Tim! A cabinet with 2 spinners sounds cool! I bet its great for things like super sprint, warlords etc :)  Unfortunately, I can't seem to build the latest version of mame anymore (I've done a bit of googling and I think its because mame's latest build environment doesn't support XP users anymore) otherwise I'd have put the steering hacks into the latest version for you. Hopefully the older version will be ok for now (Perhaps you can (like I have done) configure your cab's frontend to run different versions of mame depending on the game you select)?

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Sorry for the delay!

Here's my mame steering hack build (Mame version v0.148 Windows 32bit).

mame_0148_geecab_hack_v1_0.zip


Ehiii!!  Thank you geecab! :notworthy: :notworthy: can i upload on ArcadeItalia (the most important arcade/coin-op italian forum) server your release to avoid missing file again? i provide here the link after upload it.

Yes a new release would be better, i follow on queue to the Thorvald request....

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
The most important Arcade forum in Italy is arcademania.eu, as far as I know...

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
The most important Arcade forum in Italy is arcademania.eu, as far as I know...

The first (born in 2006)....and most old (11 years) ...and with the large amount of italians users!

PS: with a own wikifiles to store the arcade project and anything else useful for coin-ops and flippers

 :blah:

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
With "most old" you mean "older", right? :D
Anyway, nothing you cited make a forum significant.
« Last Edit: March 09, 2017, 07:03:01 am by baritonomarchetto »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Ehiii!!  Thank you geecab! :notworthy: :notworthy: can i upload on ArcadeItalia (the most important arcade/coin-op italian forum) server you release to avoid missing file again? i provide here the link after upload it.
That's cool with me, post/upoad it whereever you like! :)

Yes a new release would be better, i follow on queue to the Thorvald request....

Ok I think the next step is that I shall post a message on the mame dev forum about this. See if I can encourage their developers that a mouse/steering option like this is a worthwhile addition. Its a long shot, but its worth a try. If the mamedevs do decide to add it, they'll probably make a much nicer/cleaner job of the implementation into the latest mame version than I would. I'll post my message to the mamedevs in the next couple of days, will post link on here when its posted :)

baritonomarchetto

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 805
  • Last login:Yesterday at 01:51:33 pm
Fingher crossed. Mamedevs are not open to this kind of "hacks" but it's worth a try

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Sorry for the delay!

Here's my mame steering hack build (Mame version v0.148 Windows 32bit).

mame_0148_geecab_hack_v1_0.zip


Sorry Geecab for bother you again... i have a question about your modified version of mame, because i installed it on my driving cab.

Your version isnt a groovymame hack right? just a simple mame....because would be useful compile a groovymame version to use that on crt soft15Khz crt monitor as mine (image looks more "arcade" also the resolutions more close to real arcade)

I'm totally noob to recompiling mame, i tried a couple of windows software but no good results happens....(also i havent find any .diff on your package)

Can you have a bit of time to recompile a new version using the groovymame diff (maybe youve some dedicatd machine with all installaion stuff over it)?  https://drive.google.com/open?id=0B5iMjDor3P__Wnk4SkI3cXZkbXM  (183)

thank you for everything! youre my last chance to use this amazing hack, not all have an 360 original steerling wheen on a jamma coin-op....  :dunno

 :cheers:

isamu

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 807
  • Last login:April 14, 2024, 08:15:07 pm
  • I'm a llama!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #40 on: December 29, 2017, 07:03:05 pm »
This is cool but what about those of us with 270° wheels that want to play the 360° games?

Marcoqwerty

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 123
  • Last login:March 14, 2024, 02:46:08 pm
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #41 on: December 29, 2017, 08:31:03 pm »
This is cool but what about those of us with 270° wheels that want to play the 360° games?

You should play with mame sensibility and find the right setting "in game test mode"....but if you are on beginning to a new project, better to move on a 360 wheel imho.

Martin0037

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 21
  • Last login:May 11, 2018, 05:47:15 pm
  • I want to build my own arcade controls!
Re: Mame hacks that make driving games play better with mouse/spinner/360wheel
« Reply #42 on: February 27, 2018, 10:49:08 am »
Hi guys.  Great thread this is. Helped me loads so far.  Hope someone can help me here...
Has anyone any idea if a newer version of mame has been released with this sorted or has anyone compiled a newer version of mame with geecabs hack applied?

I’ve tried your mame hack version geecab and it works brilliant,  can’t seem to run newer games on it such as ridge racer or rave racer,  think ridge racer was 0.159 but I might be wrong.

I’m a total noob when it comes to compiling... 


geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Hi there! I think mame's steering wheel code has changed a bit since I last did my hack. I can no longer compile you a new version of mame on windows as I only have a windows XP machine (and it is not possible to build mame on XP anymore). I use Linux Ubuntu now, so I can compile/test the latest version of mame on that. If I get my hack working with the latest sources of mame on Ubuntu, I could send you my Git "diff" file (I'm not sure if you've heard of the Git source control program? but a Git diff file is just a text file generated by Git that clearly details lines of code have been changed/removed/added). If you are able to compile the latest mame sources 'as is' on your windows machine, then you should simply be able to apply my "diff" file to your sources and you should be able to compile will all my code changes (without any manual editing).

Does this sound like a good way forward? I guess first off, are you able to compile the latest mame source 'as is'?


Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Hi, sorry for replying to such a old thread but i have been trying to make a steering wheel hack for hard drivin's airborne i managed to stop the bug in the new version of mame that made the car do donuts and the same for street drivin' and i managed to get the brake input working on it so it's now playable but hard Drivin's Airborne does this weird thing where the steering goes out of alignment when you crash the car and hold the wheel left or right untill the car respawns. When you crash the car the wheel edge value gets reset to =0 and the game seems to use the position the wheel was in at that moment to set a new center point.

 I was able to make a code mod that applied a offset to recenter it when this happens but once the offset is greater than 127 the wheel starts pulling to one side badly again. I tried forcing the center value of the wheels port_minmax to be sent as the wheel position at the exact moment that wheel edge =0  and then watches for wheel movement going past the center point to set it to 1 again as usual but that code doesnt seem to work maybe because the game reads the wheel positions value too fast before the mame driver can intercept it? I've been told that Hard Drivin's Airborne uses a spinner wheel in the original prototype hardware and that this is the reason why only this game has this behaviour. All the other hard drivin's/race drivin's are working fine.

Street drivin would make the car go in circles and i modded the code for that and i fixed the brake input being mapped to the wrong 8 bit ADC channel and the steering fix works on airborne to stop the car going in circles too and it's been merged into the latest version of the mame source code on github but i've been trying now for a couple of weeks to fix this bug in airborne and cannot get my code to work it's close but the maths behind it just doesn't work. I googled some keywords to see if i could find more info and found this post from 2013 where you seem to have basically made a fix for the old version of mame that im sure could fix the wheel alignment problem in Hard Drivin's Airborne. I cannot work out how to get your older code to be modified correctly to work in the latest version of mame and was wondering if you could maybe have a look at it again?

I'll post my almost working code below. It's replacing the wheel latch code in the harddriv.cpp file. I'm using a Logitech G923 wheel.

Code: [Select]
uint16_t harddriv_state::hdc68k_wheel_r()
{
    static const uint16_t g_latchpoint = 0x800;  // Central point for wheel detection.
    static int16_t wheel_offset = 0;             // Cumulative offset to adjust the wheel position based on game events.
    static bool last_wheel_edge = false;         // To track the last state of crossing the center.

    // Read the current wheel position from the 12-bit ADC port.
    uint16_t new_wheel_raw = m_12badc[0].read_safe(0xffff);

    // Apply the cumulative offset to align with the game's perceived center.
    int16_t new_wheel = static_cast<int16_t>(new_wheel_raw) + wheel_offset;

    // Clamping the wheel position to avoid overflow and keep it within expected range. I found out that this helped stop the steering drifting off center when you hit the 2nd last checkpoint on the mountain track.
    const uint16_t min_clamp_value = 0x063A; // Observed minimum value when wheel is turned all the way to the right
    const uint16_t max_clamp_value = 0x09C6; // Observed maximum value when wheel is turned all the way to the left
    if (new_wheel < min_clamp_value) new_wheel = min_clamp_value;
    if (new_wheel > max_clamp_value) new_wheel = max_clamp_value;

    // Edge detection logic to detect being at or crossing the center point using raw ADC data.
    if ((m_hdc68k_last_wheel < g_latchpoint && new_wheel_raw >= g_latchpoint) ||
        (m_hdc68k_last_wheel > g_latchpoint && new_wheel_raw <= g_latchpoint) ||
        new_wheel_raw == g_latchpoint) {
        m_hdc68k_wheel_edge = 1;  // Set edge flag when at or crossing the center based on raw input.
    }

    // Check if the wheel edge flag has changed from 1 to 0, as reset by the game.
    if (last_wheel_edge && !m_hdc68k_wheel_edge) {
        int16_t new_offset_adjustment = g_latchpoint - new_wheel_raw; // Calculate the offset adjustment
        new_offset_adjustment /= 1; // Significantly reduce the impact of each adjustment
        wheel_offset += (new_wheel_raw > g_latchpoint) ? -new_offset_adjustment : new_offset_adjustment;
        wheel_offset = std::clamp(wheel_offset, static_cast<int16_t>(-0xfff), static_cast<int16_t>(0xfff));  // Cap the offset to 3-digit hex range
        new_wheel = static_cast<int16_t>(new_wheel_raw) + wheel_offset; // Reapply the updated offset.

        // Re-clamp the wheel after offset adjustment
        if (new_wheel < min_clamp_value) new_wheel = min_clamp_value;
        if (new_wheel > max_clamp_value) new_wheel = max_clamp_value;
    }

    last_wheel_edge = m_hdc68k_wheel_edge; // Store the last known state of the wheel edge flag.

    // Display current wheel information for debugging.
    popmessage("Wheel Raw: %04X, Wheel Adjusted: %04X, Edge: %d, Offset: %04X (Hex), %d (Dec)",
           new_wheel_raw, new_wheel, m_hdc68k_wheel_edge, static_cast<uint16_t>(wheel_offset & 0xFFFF), wheel_offset);

    // Store the current wheel value for the next comparison.
    m_hdc68k_last_wheel = new_wheel_raw;

    // Return the processed wheel value, formatted as required.
    return (static_cast<uint16_t>(new_wheel) << 8) | 0xff;
}
« Last Edit: April 14, 2024, 11:04:35 pm by Yolo_Swaggins »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Hi there!

 Unfortunately, my mind is a bit hazy regarding my hard drivin' fix/hack but will try and help as best I can.

A few things off the top of my head:

1. My fix was to make hard drivin’ play ok with mouse/spinner, rather than a SteeringWheel/Joystick (that has a fixed centre). So I’m a bit concerned that porting whatever I did back in 2013 might not help much.

2. You’re probably already aware of this, but I’ll mention it anyway - My fix only worked for the Compact British version of hard drivin’ roms (That expects optical encoders for steering, and did the weird centre point latching thing). The full cockpit versions of hard drivin’ & race drivin’ used potentiometers for steering. I am guessing when you say hard drivin’ & race drivin’ are working fine for you, that you must be using the cockpit roms? I don’t suppose there are any street drivin’ or airborne roms available for cockpit cabinets are there?

I have to say, I am fascinated to know what’s going on with this steering/latching stuff again, so at some point soon I’ll get building mame again and try to recreate what you are seeing (I’d also like to have go at street drivin’ and airborne too 😊)!

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Made some progress. Car seems to not go wonky after crashing in Hard Drivin's Airborne with this code and i can drive around untill the timer runs out and the wheels seem to stay straight  :dunno I've not tested it too much as in crashing with the wheel held all the way around to the left or the right because thats not how i play or anyone else i think? Been keeping my regular play style and if i forget to let go of the wheel when i crash theres a offset applied to the new_wheel output that keeps the centre point lined up with what the game is doing.

Original wheel edge bit latch code from harddriv_m.cpp here

Code: [Select]
uint16_t harddriv_state::hdc68k_wheel_r()
{
/* grab the new wheel value */
uint16_t new_wheel = m_12badc[0].read_safe(0xffff);

/* hack to display the wheel position */
if (machine().input().code_pressed(KEYCODE_LSHIFT))
popmessage("%04X", new_wheel);

/* if we crossed the center line, latch the edge bit */
if ((m_hdc68k_last_wheel / 0xf00) != (new_wheel / 0xf00))
m_hdc68k_wheel_edge = 1;

/* remember the last value and return the low 8 bits */
m_hdc68k_last_wheel = new_wheel;
return (new_wheel << 8) | 0xff;
}

And this is the modification i made for Hard Drivin's Airborne to work better and stop going out of alignment so much.

Code: [Select]
uint16_t harddriv_state::hdc68k_wheel_r()
{
    static const uint16_t g_latchpoint = 0x8000;  // Central point for wheel detection.
    static int16_t wheel_offset = 0;             // Cumulative offset to adjust the wheel position based on game events.
    static bool last_wheel_edge = false;         // To track the last state of crossing the center.

    // Read the current wheel position from the 12-bit ADC port.
    uint16_t new_wheel_raw = m_12badc[0].read_safe(0xffff) << 4;


    // Apply the cumulative offset to align with the game's perceived center.
    uint16_t new_wheel = new_wheel_raw + wheel_offset;

    // Edge detection logic to detect being at or crossing the center point using raw ADC data.
    if ((m_hdc68k_last_wheel < g_latchpoint && new_wheel_raw >= g_latchpoint) ||
        (m_hdc68k_last_wheel > g_latchpoint && new_wheel_raw <= g_latchpoint) ||
        new_wheel_raw == g_latchpoint) {
        m_hdc68k_wheel_edge = 1;  // Set edge flag when at or crossing the center based on raw input.
    }

    // Check if the wheel edge flag has changed from 1 to 0, as reset by the game.
    if (last_wheel_edge && !m_hdc68k_wheel_edge) {
        // Calculate the offset adjustment when the wheel is recalibrated.
        int16_t new_offset_adjustment = g_latchpoint - new_wheel_raw;

        // Apply the adjustment based on the current wheel position relative to the center
        if (new_wheel_raw > g_latchpoint) {
            // Wheel is to the left, need to decrease raw value towards the center
            wheel_offset += abs(new_offset_adjustment); // Use addition to adjust back towards the center
        } else {
            // Wheel is to the right, need to increase raw value towards the center
            wheel_offset -= abs(new_offset_adjustment); // Use subtraction if below the center
        }

        new_wheel = new_wheel_raw + wheel_offset; // Reapply the updated offset.
    }

    last_wheel_edge = m_hdc68k_wheel_edge; // Store the last known state of the wheel edge flag.

    // Display current wheel information for debugging.
    popmessage("Wheel Raw: %04X, Wheel Adjusted: %04X, Edge: %d, Offset: %X",
               new_wheel_raw, new_wheel, m_hdc68k_wheel_edge, wheel_offset);

    // Store the current wheel value for the next comparison.
    m_hdc68k_last_wheel = new_wheel_raw;  // Update last_wheel to the raw value to ensure proper comparison next cycle.

    // Return the processed wheel value, formatted as required.
    return (new_wheel << 4) | 0xff;

}

Seems to work fine in Street Drivin' too but that didn't have a wheel alignment issue after the last patch i did on it anyway and it doesn't set wheel edge to 0 when you crash so not a issue there or in any of the other ones really. This code might not play well with the compact versions because of how they do the wheel alignment I think you can just skip the wheel calibration setup and it should work anyway I applied a overclock in the source code for my own version of mame I'm testing and got the frame rate way higher in every one of them because i exceed the 400% limit on the GSP.

I made a dip switch that can toggle between 6 or 7 different types of wheel/sensitivity. I have my Logitech G923 wheel dialled in on it but not tidied the code up or labelled them appropriately yet i'll finish doing that later today or tomorrow after some sleep.

« Last Edit: April 17, 2024, 05:54:38 am by Yolo_Swaggins »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Sounds good to me, great stuff :)

I'm still catching up. I've managed to get mame built from github and I can run hard drivin' (compact) and airborne. I've just not hacked the code yet (But I think that's what I need to do to get a feel for what is happening). I'll start experimenting with my wheel at the weekend.

Something that has always bugged me with the compact roms, is that it is not possible (yet, I think) to successfully calibrate the wheel using the service menu. I went and did some reading/investigation, trying to work out what values to expect (When viewing the "Control Inputs" service menu) from a successfully calibrated wheel. I didn't get very far. Thought I'd post my notes as they might be of interest/help:-

Code: [Select]
Compact harddrivin service manual (HDC_TM-329_2nd.pdf):
041787-02 Steering Encoder Disk.
043807-02 Centering Encoder Disk.

HDC_TM-329_2nd.pdf, From the "Control Inputs" service menu:
As you turn the steering wheel clockwise, the hexadecimal number should increase and change to zero once every turn.
As you turn the wheel counterclockwise, the number should decrease. Everytime the steering wheel passes the center position,
the words center edge should change from blue to green.

HDC_TM-329_2nd.pdf, from a section near the end about installing a new encoder wheel:
Install the steering wheel with the center spoke down. Make sure the single hole on the centering disk is between the opitcal reader on the centering
PCB so the steering wheel will be correctly centered.

From the Race Drivin' Compact Manual, for the Main Board Memory Map, it says:
OPTO: Optical Steering Wheel Reader
400000 (R) OPTORD Read the Optical Counter
404000 (W) OPTORES Reset the Optical Counter
408000 (W) CENRES Reset the Optical Centre Flag

I found a picture of a 041787-02 Steering Encoder Disk, and counted 72 holes. Based on this, I don't think we should see a steering value (When viewing the "Control Inputs" service menu) reported that exceeds 72 (Or maybe 144 if we are counting teeth passing as well has holes). Thus, when turning clockwise you'll see 0 increase to 72 then back to 0 etc... When turning anticlockwise you'll see 72 decrease 0 then back to 72 etc... In mame, I think we see values much greater than 72, this might cause strangeness. I think I'll try and hack things so that I force these 'ideal' values to occur at calibration.

Something odd I noticed, is that in mame when viewing the "Control Inputs" service menu and turning the wheel clockwise, I see the hexadecimal number decrease, not increase...

:)

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Online Online
  • Posts: 9402
  • Last login:Today at 04:20:33 pm
  • Designated spam hunter
Something odd I noticed, is that in mame when viewing the "Control Inputs" service menu and turning the wheel clockwise, I see the hexadecimal number decrease, not increase...
Sounds like the optical data lines (A and B) are swapped, which reverses the axis.
- It could be your setup (not likely), settings, the connections in MAME (also not likely), or the axis reversal setting in MAME's Analog menu.   :dunno




Scott
« Last Edit: April 17, 2024, 11:04:36 am by PL1 »

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Sounds good to me, great stuff :)

I'm still catching up. I've managed to get mame built from github and I can run hard drivin' (compact) and airborne. I've just not hacked the code yet (But I think that's what I need to do to get a feel for what is happening). I'll start experimenting with my wheel at the weekend.

Something that has always bugged me with the compact roms, is that it is not possible (yet, I think) to successfully calibrate the wheel using the service menu. I went and did some reading/investigation, trying to work out what values to expect (When viewing the "Control Inputs" service menu) from a successfully calibrated wheel. I didn't get very far. Thought I'd post my notes as they might be of interest/help:-

Code: [Select]
Compact harddrivin service manual (HDC_TM-329_2nd.pdf):
041787-02 Steering Encoder Disk.
043807-02 Centering Encoder Disk.

HDC_TM-329_2nd.pdf, From the "Control Inputs" service menu:
As you turn the steering wheel clockwise, the hexadecimal number should increase and change to zero once every turn.
As you turn the wheel counterclockwise, the number should decrease. Everytime the steering wheel passes the center position,
the words center edge should change from blue to green.

HDC_TM-329_2nd.pdf, from a section near the end about installing a new encoder wheel:
Install the steering wheel with the center spoke down. Make sure the single hole on the centering disk is between the opitcal reader on the centering
PCB so the steering wheel will be correctly centered.

From the Race Drivin' Compact Manual, for the Main Board Memory Map, it says:
OPTO: Optical Steering Wheel Reader
400000 (R) OPTORD Read the Optical Counter
404000 (W) OPTORES Reset the Optical Counter
408000 (W) CENRES Reset the Optical Centre Flag

I found a picture of a 041787-02 Steering Encoder Disk, and counted 72 holes. Based on this, I don't think we should see a steering value (When viewing the "Control Inputs" service menu) reported that exceeds 72 (Or maybe 144 if we are counting teeth passing as well has holes). Thus, when turning clockwise you'll see 0 increase to 72 then back to 0 etc... When turning anticlockwise you'll see 72 decrease 0 then back to 72 etc... In mame, I think we see values much greater than 72, this might cause strangeness. I think I'll try and hack things so that I force these 'ideal' values to occur at calibration.

Something odd I noticed, is that in mame when viewing the "Control Inputs" service menu and turning the wheel clockwise, I see the hexadecimal number decrease, not increase...

:)

Wow that is the info we have been looking for!
 :notworthy:


From the Race Drivin' Compact Manual, for the Main Board Memory Map, it says:
OPTO: Optical Steering Wheel Reader
400000    (R)   OPTORD      Read the Optical Counter
404000   (W)   OPTORES      Reset the Optical Counter
408000   (W)   CENRES      Reset the Optical Centre Flag

Does this part have any relation to this code in the harddriv.cpp file?

Code: [Select]
PORT_START("mainpcb:a80000")
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM )  /* center edge on steering wheel */

I hacked the code about a month ago so that when i press a button i assign in the input assignment menu in mame it activates this function. When i press the button you see the center point indicator light up and the wheel reset back to 0000...............

There is no wheel calibration in street drivin or in hard drivin's airborne like the other games do. It only has the menu that shows the output value of it when your moving it around. I was thinking if i set the port_minmax from 0 to 71 or 143 ( if the games code counts 0 as a value) then trigger the code above to activate each time this reaches the centerpoint the same way it does when i push the button with this code i "hacked"

Code: [Select]
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_TOGGLE PORT_NAME("wheel centre1")
Maybe then it will function correctly........then all we would need to do is implement the proper scaling for a 900/720/270 degree wheel etc so that it only goes up to the max value when you turn it whatever direction it should go like 71/72 or 143/144 for clockwise/counter clockwise max then the opposite for the other direction. I probobly explained that in a confusing way lol.

I'm having another mess around with it today. I made some other code that was implementing the stuff i was doing in the other code i sent you plus it buffers/smooths the wheel output and truncates the last digit from the hex value you so it doesnt fluctuate as quickly when you turn the wheel around and it seems to have fixed the wheel going out of alignment when you turn it fast, that was another issue you could kinda stop from happening if you made smoother wheel turns physicly but sometimes just not possible if you want or need a sharp turn. The recentring logic i did before doesnt work as well in the new code though i dont know if it's because im messing with the values before i apply the offset. Now that i have the info you provided i don't think any of that is even going to be needed lol

Code: [Select]
#include <numeric>  // For std::accumulate

// Function to calculate the Exponential Moving Average (EMA)
uint16_t harddriv_state::calculate_ema(uint16_t new_value) {
    static float ema_wheel = 0.0;  // Persistent storage of EMA across calls
    static const float alpha = 0.05;  // Smoothing constant

    ema_wheel = alpha * new_value + (1 - alpha) * ema_wheel;

    return static_cast<uint16_t>(ema_wheel);
}

// Main function to handle wheel input and apply adjustments
uint16_t harddriv_state::hdc68k_wheel_r() {
    static const uint16_t g_latchpoint = 0x8000;
    static int16_t wheel_offset = 0;
    static bool last_wheel_edge = false;

    uint16_t new_wheel_raw = m_12badc[0].read_safe(0xffff) << 4;
    uint16_t ema_wheel = calculate_ema(new_wheel_raw);
    uint16_t new_wheel = ema_wheel + wheel_offset;

    // Set wheel edge to 1 if at or crossing the center and it is not already set
    if (!m_hdc68k_wheel_edge &&
        ((m_hdc68k_last_wheel < g_latchpoint && new_wheel_raw >= g_latchpoint) ||
         (m_hdc68k_last_wheel > g_latchpoint && new_wheel_raw <= g_latchpoint))) {
        m_hdc68k_wheel_edge = 1;
    }

    // Handle wheel edge reset and offset adjustment
    if (last_wheel_edge && !m_hdc68k_wheel_edge) {
        int16_t adjustment = g_latchpoint - ema_wheel;
        adjustment = (adjustment / 0x10) * 0x10;  // Normalize adjustment to remove last digit
        wheel_offset += (new_wheel_raw > g_latchpoint) ? -abs(adjustment) : abs(adjustment);
        wheel_offset = (wheel_offset / 0x10) * 0x10; // Normalize wheel_offset to remove last digit
        new_wheel = ema_wheel + wheel_offset;
        new_wheel = (new_wheel / 0x10) * 0x10;  // Normalize new_wheel to remove last digit
    }

    last_wheel_edge = m_hdc68k_wheel_edge; // Store the last state of the wheel edge
    m_hdc68k_last_wheel = new_wheel_raw;   // Update the last wheel value for comparison in the next cycle

    // Continuously show the debugging message
    popmessage("Wheel Raw: %04X, EMA Wheel: %04X, Adjusted: %04X, Edge: %d, Offset: %d",
               new_wheel_raw, ema_wheel, new_wheel, m_hdc68k_wheel_edge, wheel_offset);

    return (new_wheel << 4) | 0xff;
}


Thats where i was last night before i woke up and saw your reply today, i actualy had a look yesterday but none of it was sinking in as i had no sleep for a couple of days lol. I'll get back to you if it's been improved any. Cheers! :applaud:





Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
My wheel center point button can be used to turn the wheel all the way to the left then i hit the button twice and in the input menu you now see the value of the wheel going from 0000 to 0702 when you turn it to the right. I'm just going to change my port_minmax to see if i can get this thing to tally up and alter the code if i need to.

Ok i just tried editing the port_minmax and now when i turn the wheel all the way to the left and hit the wheel edge toggle button i made it starts reading the wheel values properly from 0000 all the way on the left all the way up to 0058 on the right which in decimal = 72. if it needs flipped the other way it can be easily done. Just going to check the behaviour of the wheel in game.  I think that button for wheel center has to be triggered to activate every time that the wheel reaches the right(0058 in hex 72 dec)? Or left if it's the wrong way around? Either way it sounds closer to the original game. I would need to see what the values were on a real machine to make it accurate because we don't know how the machine was scaling these numbers. It was using a 12 bit ADC port so thats why it's a 4 digit hex value. Seems like a waste of hardware for a wheel that only had to read 72 notches? Maybe the wheel edge detection in the other harddriv_m.cpp file just needs the value for the edge detection to trigger to be tweaked to match the real hardware in there they have it set to 0xf00.
« Last Edit: April 20, 2024, 08:26:27 am by Yolo_Swaggins »

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
After having a think about how the machine works, and this is just me thinking out loud having no actual experience with one of the machines in it's testmode and only working with it on the mame emulator is that we need to split the "PORT_MINMAX" of the wheels range in mame into 8 virtual segments meaning it would need to be a port_minmax range that can be divided into 8 segements with no remainder etc? Then what we would need to do in the code is maybe trigger 2 flags each time it hits or passes one of the 8th's.........like each time it passed one the flag for  "404000   (W)   OPTORES Reset the Optical Counter" would need to be triggered once to reset the wheel position to 0000 and at the same time trigger the "408000   (W)   CENRES Reset the Optical Centre Flag" so that it knows that was just 1 full rotation of the emulated wheel in mame based off the port_minmax range being given to it? Depending on how these actualy work you might only need to use the "408000   (W)   CENRES Reset the Optical Centre Flag" when it reaches the middle 8th of the wheels range in mame.......so it would be at 4/8ths...........to let the game know this was the middle we reached.

Hopefully you can understand what i mean by this! I think it would allow the machine being emulated in mame to do the correct maths or functions when the car crashes in airborne or you go offraod untill the timer hits 0. it would know in it's memory at what point the wheel was actually at more in line with the real hardware? I could be totally wrong but it's been annoying me for a while that i got the game to work but there couple of small bugs kinda ruin it if your not aware that you need to let go of the wheel as soon as you crash the car or just before your offroad timer reaches 0  :dunno I seem to have fixed or heavily mitigated the "wheel going out of alignment when turning the wheel fast" in my own version of the game but my guess is you would need to plug in the appropriate port_minmax values that work for your specific wheel or input device. if a calibration menu could be added to mame for this purpose it would be pretty cool, it could normalise the input of anyones wheel/controller to work with each game better.

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Hi Yolo!

Really good work. Unfortunately, I’ve not really made much/any progress. I've been focusing on hacking/understanding the harddrivcb (Compact British) rom.

I’ve been watching this youtube clip because at 24:32 the chap manages to successfully calibrate his wheel:

   

His old settings look like:
    OLD CNTSPTRN 1080 PATCEN -98
His new settings look like (after successfully calibrating):
    NEW CNTSPTRN 1110 PATCEN 14

I hacked mame to trigger the centre edge after 256 steering wheel values. After calibrating things looked like this for me:
    NEW CNTSPTRN 256 PATCEN 0

I concluded that CNTSPTRN is the amount of steering wheel values for 1 complete turn. I was clearly wrong about my 72 theory. I’m not sure where the actual arcade value of 1110 comes from. I guess I’ll just accept that the encoder processor gives you about 1024 values per turn. I can see now from PL1's previous post (Thanks for the post btw!) why you'd get more values out of an optical encoder than just teeth count. The PATCEN thing is to do with straightening up the wheel at the end of the calibration test, if its not dead straight (i.e. to one side of the centre edge) then you get a non-zero number.

Whilst the above is interesting-ish, I realise it doesn’t really help us…

I had observed the centre edge triggering working well in the service menu (You see the steering wheel value get reset to zero each time ‘Centre Edge’ turns green), and you also see the
harddriv_state::hdc68k_wheel_edge_reset_w(uint16_t data) function being called each time a reset happens. However, in-game, when attempting to trigger the centre edge, I had noticed the hdc68k_wheel_edge_reset_w callback never gets called…

You recently wrote about those encoder addresses you’d seen in harddriv.cpp (Good shout by the way! :)), and I got excited and added this:-
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM )  PORT_NAME("Encoder Reset")

I removed my code that automatically triggers the Centre Edge reset (That stuff to do with processing the m_hdc68k_wheel_edge flag and setting the result ^= 0x4000 thing in hdc68k_port1_r) , and assigned a key to the new ‘Encoder Reset’ setting so I could just trigger everything manually.

In the service menu, everything worked well (The manual reset set the steering wheel value to zero, and  hdc68k_wheel_edge_reset_w() was called). In-game, the manual reset now did result in hdc68k_wheel_edge_reset_w() being called, but it seemed to have no effect on the actual steering. Its like the game just ignores the manual encoder reset whilst being played…. Strange… The game also (when you crash) resets the steering to some weird values (I guess to the nearest centre edge) and doesn’t tell you when its done it...

I also added...
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_CUSTOM )  PORT_NAME("Centre Reset")
And assigned a key to that, but that seemed to have absolutely no effect on anything.

Time to sleep on this for a bit… Its interesting stuff :) but frustrating  :timebomb:

PL1

  • Global Moderator
  • Trade Count: (+1)
  • Full Member
  • *****
  • Online Online
  • Posts: 9402
  • Last login:Today at 04:20:33 pm
  • Designated spam hunter
I can see now from PL1's previous post (Thanks for the post btw!) why you'd get more values out of an optical encoder than just teeth count.
Glad to assist.   ;D

For anyone wanting to learn more on optos and encoder wheels including how to calculate opto spacing and encoder wheel measurements, check out this thread.

Am I correct in thinking that as it will be quadrature each hole in the wheel will actually be 2 pulses?
Assuming you have a properly paired encoder wheel and opto spacing, quadrature waveforms have 4 phases per tooth/gap.
- The good spacing image shows the encoder wheel at the left edge of Phase 1.
- Data line A is transitioning from high (not blocked) to low (blocked) and data line B is in the middle of being blocked.
- As you rotate the encoder wheel clockwise, the blocking and un-blocking of the optos will produce the quadrature waveforms shown.




Scott

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Hi Yolo!

Really good work. Unfortunately, I’ve not really made much/any progress. I've been focusing on hacking/understanding the harddrivcb (Compact British) rom.

I’ve been watching this youtube clip because at 24:32 the chap manages to successfully calibrate his wheel:

   

His old settings look like:
    OLD CNTSPTRN 1080 PATCEN -98
His new settings look like (after successfully calibrating):
    NEW CNTSPTRN 1110 PATCEN 14

I hacked mame to trigger the centre edge after 256 steering wheel values. After calibrating things looked like this for me:
    NEW CNTSPTRN 256 PATCEN 0

I concluded that CNTSPTRN is the amount of steering wheel values for 1 complete turn. I was clearly wrong about my 72 theory. I’m not sure where the actual arcade value of 1110 comes from. I guess I’ll just accept that the encoder processor gives you about 1024 values per turn. I can see now from PL1's previous post (Thanks for the post btw!) why you'd get more values out of an optical encoder than just teeth count. The PATCEN thing is to do with straightening up the wheel at the end of the calibration test, if its not dead straight (i.e. to one side of the centre edge) then you get a non-zero number.

Whilst the above is interesting-ish, I realise it doesn’t really help us…

I had observed the centre edge triggering working well in the service menu (You see the steering wheel value get reset to zero each time ‘Centre Edge’ turns green), and you also see the
harddriv_state::hdc68k_wheel_edge_reset_w(uint16_t data) function being called each time a reset happens. However, in-game, when attempting to trigger the centre edge, I had noticed the hdc68k_wheel_edge_reset_w callback never gets called…

You recently wrote about those encoder addresses you’d seen in harddriv.cpp (Good shout by the way! :)), and I got excited and added this:-
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM )  PORT_NAME("Encoder Reset")

I removed my code that automatically triggers the Centre Edge reset (That stuff to do with processing the m_hdc68k_wheel_edge flag and setting the result ^= 0x4000 thing in hdc68k_port1_r) , and assigned a key to the new ‘Encoder Reset’ setting so I could just trigger everything manually.

In the service menu, everything worked well (The manual reset set the steering wheel value to zero, and  hdc68k_wheel_edge_reset_w() was called). In-game, the manual reset now did result in hdc68k_wheel_edge_reset_w() being called, but it seemed to have no effect on the actual steering. Its like the game just ignores the manual encoder reset whilst being played…. Strange… The game also (when you crash) resets the steering to some weird values (I guess to the nearest centre edge) and doesn’t tell you when its done it...

I also added...
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_CUSTOM )  PORT_NAME("Centre Reset")
And assigned a key to that, but that seemed to have absolutely no effect on anything.

Time to sleep on this for a bit… Its interesting stuff :) but frustrating  :timebomb:

I fixed the brake calibration using the same method i used to fix it on Street Drivin'.

Code: [Select]
PORT_START("mainpcb:8BADC.6")        /* b00000 - 8 bit ADC 6 - force brake */
PORT_BIT( 0xff, 0x20, IPT_PEDAL2 ) PORT_SENSITIVITY(25) PORT_MINMAX(0x20, 0xf0) PORT_KEYDELTA(40) PORT_REVERSE PORT_NAME("Force Brake")

Still working on the wheel , i got it to register the 4 turns to the left but in the game the center is off and wheel pulls slightly to the right hand side.

We'll fix this eventually lol.

I now reckon from checking out the compact versioin that airborne might use the same hardware for the wheel but just implements it differently if that makes sense. Might even be the same. That flag you notice that doesnt get called i think is key to it. maybe it has to have the IP_ACTIVE_HIGH instead of low?
« Last Edit: April 20, 2024, 02:58:16 pm by Yolo_Swaggins »

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Cool, I'll try the IP_ACTIVE_HIGH things and see what happens.

>>I now reckon from checking out the compact versioin that airborne might use the same hardware for the wheel but just implements it differently if that makes sense.

Agreed.

One thing I forgot to mention. I started looking at the void harddriv_state::hd68k_wr2_write(offs_t offset, uint16_t data) function. I thought it could be used to retrieve the steering wheel value (the one that you see in the service menu) during the actual game. I thought if we could do that, we'd be able to see exactly where the game thinks the steering centre is after crashing the car. Then maybe following a crash, when you're turning your key to start (and your physical wheel would be centred at that point), you'd be able to set a really accurate offset at that point. That probably doesn't make any sense... Anyways, I'm not really sure what calling hd68k_wr2_write gives you. Its values do change based on steering position though (but only during the game, It never gets called during the service menu).

I'm not sure if this is helpful or not, but here's some hacky code I added to see if I could work out what's going on...

Code: [Select]
void harddriv_state::hd68k_wr2_write(offs_t offset, uint16_t data)
{
    static unsigned int static_count = 0;
    static uint8_t static_data[4];

    static_data[static_count] = data >> 8;
    static_count++;
    if (static_count > 3) static_count = 0;

    if (offset == 0)
    {
        // logerror("Steering Wheel Latch = %02X\n", data);
        m_wheel = data >> 8;
    }
    else
        logerror("/WR2(%04X)=%02X\n", offset, data);


    // The 'data' repeats every 4 times this function is called.
    // You should see the data repeating in this debug output...
    printf("wr2 offset=%04X data=%04X\n", offset, data);

    // Try to put the data together (we must be writing 16bits somewhere?) to see what's going on...
    if (machine().input().code_pressed(KEYCODE_RSHIFT))
    {
        popmessage("wr2 [%02X] [%02X] [%02X] [%02X]", static_data[0], static_data[1], static_data[2], static_data[3]);
    }
}

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
I concluded that CNTSPTRN is the amount of steering wheel values for 1 complete turn. I was clearly wrong about my 72 theory. I’m not sure where the actual arcade value of 1110 comes from

I'm sure i saw somebody on youtube or some other forum saying they had a 1100 degree wheel in the arcade. I don't know if it's true or not but it matches exactly what you said here?

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Still no joy my end...

I've just done a bit more investigation regarding the values I'm seeing in  hd68k_wr2_write().

The range of values it reports is different depending on if you are watching the attract mode, or are viewing the "choose manual or auto transmission screen", or actually driving the car. I have been focusing on the values it reports whilst driving the car during the game.

Here's my latest hack:-
Code: [Select]
void harddriv_state::hd68k_wr2_write(offs_t offset, uint16_t data)
{
    static unsigned int static_count = 0;
    static uint8_t static_data[4];
    static bool seeing_e000 = false;

    static_data[static_count] = data >> 8;
    static_count++;
    if (static_count > 3) static_count = 0;

    if (offset == 0)
    {
        // logerror("Steering Wheel Latch = %02X\n", data);
        m_wheel = data >> 8;
    }
    else
        logerror("/WR2(%04X)=%02X\n", offset, data);

    if ((static_data[2] == 0xE0) && (static_data[0] == 0x00))
    {
        if(!seeing_e000)
        {
            popmessage("wr2 MIDDLE");
            seeing_e000 = true;
        }
    }
    else
    {
        seeing_e000 = false;
    }


    // The 'data' repeats every 4 times this function is called.
    // You should see the data repeating in this debug output...
    //printf("wr2 offset=%04X data=%04X\n", offset, data);

    // Try to put the data together (we must be writing 16bits somewhere?) to see what's going on...
    if (machine().input().code_pressed(KEYCODE_RSHIFT))
    {
        popmessage("wr2 [%02X%02X]", static_data[2], static_data[0]);
    }
}

I noticed that combining the 1st and the 3rd byte showed me a range of values where the middle point is 0xE000.
From middle, if I turn the wheel fully left the value changes from 0xE000, 0xE001, 0xE002, ... up to  0xE112 (Thus 274 possible values)
From middle, if I turn the wheel fully right the value changes from 0xE000, 0xFF1F, 0xFF1E, ... down to 0xFE0D  (Thus, also 274 possible values)
Giving an overall range of 548 values.

No matter what I calibrated the the wheel to in the system settings, this range remained the same (Always 548 values, left limit 0xE112, mid point=0xE000, right limit=0xFE0D).

I also noticed that when you crash with the wheel substantially turned, the value is reset back to 0xE000 when the car re-spawns. If you crash during soft turn, the value remains the same as whatever the value was when you crashed.

I not sure this helps us but thought it was worth a mention :)

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Still no joy my end...

I've just done a bit more investigation regarding the values I'm seeing in  hd68k_wr2_write().

The range of values it reports is different depending on if you are watching the attract mode, or are viewing the "choose manual or auto transmission screen", or actually driving the car. I have been focusing on the values it reports whilst driving the car during the game.

Here's my latest hack:-
Code: [Select]
void harddriv_state::hd68k_wr2_write(offs_t offset, uint16_t data)
{
    static unsigned int static_count = 0;
    static uint8_t static_data[4];
    static bool seeing_e000 = false;

    static_data[static_count] = data >> 8;
    static_count++;
    if (static_count > 3) static_count = 0;

    if (offset == 0)
    {
        // logerror("Steering Wheel Latch = %02X\n", data);
        m_wheel = data >> 8;
    }
    else
        logerror("/WR2(%04X)=%02X\n", offset, data);

    if ((static_data[2] == 0xE0) && (static_data[0] == 0x00))
    {
        if(!seeing_e000)
        {
            popmessage("wr2 MIDDLE");
            seeing_e000 = true;
        }
    }
    else
    {
        seeing_e000 = false;
    }


    // The 'data' repeats every 4 times this function is called.
    // You should see the data repeating in this debug output...
    //printf("wr2 offset=%04X data=%04X\n", offset, data);

    // Try to put the data together (we must be writing 16bits somewhere?) to see what's going on...
    if (machine().input().code_pressed(KEYCODE_RSHIFT))
    {
        popmessage("wr2 [%02X%02X]", static_data[2], static_data[0]);
    }
}

I noticed that combining the 1st and the 3rd byte showed me a range of values where the middle point is 0xE000.
From middle, if I turn the wheel fully left the value changes from 0xE000, 0xE001, 0xE002, ... up to  0xE112 (Thus 274 possible values)
From middle, if I turn the wheel fully right the value changes from 0xE000, 0xFF1F, 0xFF1E, ... down to 0xFE0D  (Thus, also 274 possible values)
Giving an overall range of 548 values.

No matter what I calibrated the the wheel to in the system settings, this range remained the same (Always 548 values, left limit 0xE112, mid point=0xE000, right limit=0xFE0D).

I also noticed that when you crash with the wheel substantially turned, the value is reset back to 0xE000 when the car re-spawns. If you crash during soft turn, the value remains the same as whatever the value was when you crashed.

I not sure this helps us but thought it was worth a mention :)

I was experimenting with the << 4 lower 8 bit thing etc and found i can give myself a 4 digit port_minmax on the 12 bit ADC and the wheel will use the whole 4 digits of it. Surely if we just get the wheel input to match 1-1 with what the game expects we could use those values to apply and subtract offsets to the wheel to keep it in exact or almost exact alignment live as we are playing? I had it showing the same values in the test menu as it did from my raw wheel input. The code i had that worked the most for offset adjustment would work for small turns when you crashed.......as soon as the offset exceeded 127 or went below -128 (uint8_t?) the offset being applied wouldnt match what was happening behind the scenes with the game.......you could make several crashes with the wheel turned a bit and it would stop it pulling to the one side which was better than nothing but with the new code i made that stops the wheel going out of alignment whilst driving and moving the wheel very fast seems to gimp my offset alignment procedure so it doesn't even work at all but that code to stop it happening when your not even crashing and just moving the wheel quick is more valuable to the gameplay and lets me get a much higher score and a longer play session. it used to happen to me on the 2nd last checkpoint in the mountain track and i assumed it was a trigger set by the checkpoint to reset the wheel but i found out the other day it's just because the wheel value changes so fast when your making quick sharp turns on that part of the track it sends it out of synch with the wheel or something. I created a code that buffers the wheel input with EMA algorithm which introduces a tiny bit of latency but stops the wheel ever going out of alignment when you move it fast from left to right etc. I messed around with the values and the port_minmax and got a good wheel sensitivity and responsiveness but stil mitigated the glitch that happens when you move it too fast. My method is a way too complex solution the fix could be much more simply those values you have found must be the key to keeping everything in synch and alignment!  :dunno

I'm talking about airborne and i assume your still talking about the compact version of race drivin'? it's slightly different behaviour between the 2 games but i reckon the solution for one will fix the other.

« Last Edit: April 21, 2024, 03:15:15 pm by Yolo_Swaggins »

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
I got the steering to work on race drivin' compact. I'm going to have a quick once over of the code and i'll stick it up here and put it on github as a commit to the mamedev/master.

I can get past the wheel calibration but it involves pressing a button when you reach the far right to register the turn and the values that show up arent accurate or inline with what should appear on the real machine but when you start the game it just behaves the same as the other Race Drivin' and Hard Drivin'.  ;D

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Wow! Well done Yolo, sounds like progress at last!! :) Can't wait to see the changes :)

Yolo_Swaggins

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 11
  • Last login:Today at 09:49:22 am
  • I want to build my own arcade controls!
Wow! Well done Yolo, sounds like progress at last!! :) Can't wait to see the changes :)

I still haven't got round to using the info you gave me on Airborne im using my older hack to get that working and added differennt wheel sensitivities /port_minmax's through a dip switch menu that changes your wheel to a different calibration and goes through EMA filtering. The fix for the compact version of race drivin' was easier than i thought lol. The test menu calibration is still gimped but you can just skip it.

https://github.com/Madcadden/mame/tree/Madcadden-Hard-Drivin-Race-Drivin-MAME-Build

Code: [Select]
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_CUSTOM )  PORT_TOGGLE PORT_NAME("Center Wheel Edge")  /* center edge on steering wheel, IPT_ACTIVE_HIGH fixes the steering alignment in game! */

Code: [Select]
#include <numeric>  // For std::accumulate

// Function to calculate the Exponential Moving Average (EMA)
uint16_t harddriv_state::calculate_ema(uint16_t new_value) {
    static float ema_wheel = 0.0;  // Persistent storage of EMA across calls
    static bool ema_initialized = false;  // To check if ema_wheel is initialized
    static const float alpha = 0.082;  // Smoothing constant

    if (!ema_initialized) {
        ema_wheel = new_value;  // Initialize EMA with the first raw value
        ema_initialized = true;
    } else {
        ema_wheel = alpha * new_value + (1 - alpha) * ema_wheel;
    }

    // Ensure the last digit of the EMA output is always zero
    return static_cast<uint16_t>(ema_wheel) & 0xFFF0;
}

// Main function to handle wheel input and apply adjustments
uint16_t harddriv_state::hdc68k_wheel_r() {
    static const uint16_t g_latchpoint = 0x8000;  // Center point for wheel edge detection
    static bool initialized = false;  // To ensure the initial setup is done only once
    static int16_t last_offset = 0;   // To store the last offset applied
    static int wheel_edge_zero_count = 0;  // Counter for how many times wheel edge has been set to 0
    static int resets_recorded = 0;   // Counter to delay offset recording

    // Initial setup
    if (!initialized) {
        m_hdc68k_wheel_edge = 1;  // Set the edge to 1 at the start of the game
        initialized = true;  // Prevent further initialization
    }

    uint16_t new_wheel_raw = m_12badc[0].read_safe(0xffff) << 4;
    uint16_t ema_wheel = calculate_ema(new_wheel_raw) << 3;

    // If the game has reset the wheel edge to 0, handle the deviation
    if (m_hdc68k_wheel_edge == 0) {
        wheel_edge_zero_count++;  // Increment the counter each time wheel edge is 0

        // Record adjustment only after the first reset is recorded
        if (resets_recorded > 0) {
            // Check for deviation from the center point
            if (ema_wheel != g_latchpoint) {
                int16_t adjustment = g_latchpoint - ema_wheel;  // Calculate the necessary adjustment
                ema_wheel += adjustment;  // Correct the EMA to the center point
                last_offset = adjustment;  // Store the last offset applied
            } else {
                last_offset = 0;  // No offset needed if already at center
            }
        }

        resets_recorded++;  // Increment resets recorded after processing
        m_hdc68k_wheel_edge = 1;  // Set the wheel edge back to 1 after handling the adjustment
    }

    // Debugging output
    popmessage("Wheel Raw: %04X, EMA Wheel: %04X, Last Offset: %d, Edge: %d, Edge 0 Count: %d, Resets Recorded: %d",
               new_wheel_raw, ema_wheel, last_offset, m_hdc68k_wheel_edge, wheel_edge_zero_count, resets_recorded);

    return ema_wheel;  // Use the adjusted EMA directly
}


Code: [Select]
    // Handlers for the wheel and port inputs
    m_maincpu->space(AS_PROGRAM).install_read_handler(0x400000, 0x400001, read16smo_delegate(*this, FUNC(harddriv_state::hdc68k_wheel_r)));
    m_maincpu->space(AS_PROGRAM).install_write_handler(0x408000, 0x408001, write16smo_delegate(*this, FUNC(harddriv_state::hdc68k_wheel_edge_reset_w)));
    m_maincpu->space(AS_PROGRAM).install_read_handler(0xa80000, 0xafffff, read16smo_delegate(*this, FUNC(harddriv_state::hda68k_port1_r)));


Code: [Select]
class harddriv_state : public device_t
{
public:

void reset_wheel_offset();  // Function to reset the wheel offset


harddriv_state(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

void driver_msp(machine_config &config);
@@ -98,8 +102,21 @@ class harddriv_state : public device_t
void video_int_write_line(int state);
void sound_int_write_line(int state);

//New method declarations for steering logic
uint16_t hdc68k_wheel_r();  // Ensure this is declared only once
uint16_t custom_steering_logic();
uint16_t original_steering_logic();

// Add your EMA function declaration here
uint16_t calculate_ema(uint16_t new_value); // Corrected declaration


protected:

 int16_t wheel_offset = 0;  // Make wheel_offset a member variable

void init_video();

INTERRUPT_GEN_MEMBER(hd68k_irq_gen);
TIMER_CALLBACK_MEMBER(deferred_adsp_bank_switch);
TIMER_CALLBACK_MEMBER(rddsp32_sync_cb);
@@ -122,7 +139,7 @@ class harddriv_state : public device_t
uint16_t hd68k_adc12_r();
uint16_t hdc68k_port1_r();
uint16_t hda68k_port1_r();
// uint16_t hdc68k_wheel_r();
uint16_t hd68k_sound_reset_r();

void hd68k_adc_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);

geecab

  • Trade Count: (0)
  • Full Member
  • ***
  • Offline Offline
  • Posts: 234
  • Last login:Today at 02:03:53 pm
Code: [Select]
PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_CUSTOM )  PORT_TOGGLE PORT_NAME("Center Wheel Edge")  /* center edge on steering wheel, IPT_ACTIVE_HIGH fixes the steering alignment in game! */

OMG lol! I didn't try IP_ACTIVE_HIGH on 0x4000, only on 0x8000. I didn't change it on 0x4000 because it looked like it was doing the right thing in the service menu :p I honestly can't wait to try this later, nice one Yolo and well found! :)