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 22106 times)

0 Members and 1 Guest are viewing this topic.

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
  • *****
  • Offline Offline
  • Posts: 9402
  • Last login:Today at 10:36:40 am
  • 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
  • *****
  • Offline Offline
  • Posts: 9402
  • Last login:Today at 10:36:40 am
  • 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! :)