Main > Driving & Racing Cabinets
Mame hacks that make driving games play better with mouse/spinner/360wheel
Yolo_Swaggins:
The 1st and 2nd roms* in the mainpcb:maincpu on street drivin' are the test menu roms that are both interleaved so technically it's 1 rom.
geecab:
Hi Yolo!
Well, I’m convinced after much testing Airborne’s steering re-centering is entirely different to hard/race/street drivin’. The centering encoder signals are completely ignored. For Airborne, when your car re-spawns after crashing, whatever the wheel position your steering wheel is in at that time becomes the new center (regardless of angle). The center position can also self adjust during play should you oversteer (Say that you rotate the wheel 3 times clockwise to go round a tight turn. You’ll only need to do roughly one anit-clockwise rotation for the car to go in a straight line again).
I came to the conclusion that this game can only really be enjoyed with a mouse/spinner. Even then it would need force feedback so you had a feeling of where the steering center is.
Then I had a thought which was followed by a hack which might help...
I modified hdc68k_wheel_r() for airborne. I took out the steering latching stuff. I’ve added a key ‘S’ that can hold to adjust your steering wheel back to center during play. Here’s how it works:
Say that you are playing the game, you want the car to go straight, your steering wheel is in its central position but the car is pulling to the right. To fix this you need to turn your steering wheel left (Until the car is moving in a straight line), then press and hold the ‘S’ key, then turn your steering wheel to its central position, and release the ‘S’ key. That’s it.
I know its not really an ideal solution, but it might improve the game experience and help us get better laps times :)
In hardriv.cpp, in the "static INPUT_PORTS_START( hdrivair )" section, I've changed this line:-
--- Code: ---PORT_BIT(0xfff, 0x200, IPT_PADDLE) PORT_MINMAX(0x000, 0x3ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_REVERSE PORT_NAME("Steering Wheel")
--- End code ---
to this...
--- Code: ---PORT_BIT( 0xfff, 0x000, IPT_POSITIONAL ) PORT_POSITIONS(0xfff) PORT_WRAPS PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_REVERSE PORT_NAME("Steering Wheel")
--- End code ---
Then in harddriv_m.cpp, replace the hdc68k_wheel_r() function with this...
--- Code: ---uint16_t harddriv_state::hdc68k_wheel_r()
{
// grab the new wheel value
uint16_t new_wheel, raw_wheel = m_12badc[0].read_safe(0xffff);
int wheel_diff = 0;
bool is_wheel_increasing = false;
static uint8_t wheel_snapshot = 0;
static uint8_t wheel_offset = 0;
static bool steering_enabled = true;
if (machine().input().code_pressed(KEYCODE_S))
{
if (steering_enabled)
{
popmessage("Steering disabled (Re-center your wheel now...)");
steering_enabled = false;
wheel_snapshot = (m_hdc68k_last_wheel+wheel_offset)&0xff;
}
return ((wheel_snapshot << 8) | 0xff);
}
else
{
if (!steering_enabled)
{
popmessage("Steering enabled");
steering_enabled = true;
wheel_offset = (wheel_snapshot - raw_wheel)&0xff;
m_hdc68k_last_wheel = raw_wheel;
}
}
// Work out which way the wheel is spinning
if((m_hdc68k_last_wheel < 0x400) && (raw_wheel > 0xC00)) is_wheel_increasing = false; //Wrapped from bottom to top
else if ((m_hdc68k_last_wheel > 0xC00) && (raw_wheel < 0x400)) is_wheel_increasing = true; //Wrapped from top to bottom
else if(m_hdc68k_last_wheel > raw_wheel) is_wheel_increasing = false;
else if(m_hdc68k_last_wheel < raw_wheel) is_wheel_increasing = true;
//Steering damping:
//Ensure we don't jump from one encoder value to another too quickly confusing the game
//The game is aware only of changes to m_12badc's lower byte. This means the game can get easily confused if you where to move
//the wheel very quickly from say position 0x800 to 0xC12 in one cycle (Which was perhaps physically impossible using the
//actual arcade encoder). The game would be under the impression the wheel has moved only 0x12 values, rather than 0x412 values.
//If we detect a large change, slowly feed that information back to the game in managemtble amounts.
new_wheel = m_hdc68k_last_wheel;
while(new_wheel != raw_wheel)
{
if (is_wheel_increasing)
{
if (new_wheel >= 0xFFF) new_wheel = 0x000;
else new_wheel++;
}
else
{
if (new_wheel <= 0x000) new_wheel = 0xFFF;
else new_wheel--;
}
//Lets say the encoder can't move more that 32 teeth per cycle...
if (wheel_diff++ > 0x10) break;
}
if (machine().input().code_pressed(KEYCODE_LSHIFT))
{
popmessage("wheel=0x%04X", new_wheel);
}
m_hdc68k_last_wheel = new_wheel;
return ((new_wheel+wheel_offset) << 8) | 0xff;
}
--- End code ---
Yolo_Swaggins:
--- Quote from: geecab on May 10, 2024, 02:43:05 pm ---Hi Yolo!
Well, I’m convinced after much testing Airborne’s steering re-centering is entirely different to hard/race/street drivin’. The centering encoder signals are completely ignored. For Airborne, when your car re-spawns after crashing, whatever the wheel position your steering wheel is in at that time becomes the new center (regardless of angle). The center position can also self adjust during play should you oversteer (Say that you rotate the wheel 3 times clockwise to go round a tight turn. You’ll only need to do roughly one anit-clockwise rotation for the car to go in a straight line again).
I came to the conclusion that this game can only really be enjoyed with a mouse/spinner. Even then it would need force feedback so you had a feeling of where the steering center is.
Then I had a thought which was followed by a hack which might help...
I modified hdc68k_wheel_r() for airborne. I took out the steering latching stuff. I’ve added a key ‘S’ that can hold to adjust your steering wheel back to center during play. Here’s how it works:
Say that you are playing the game, you want the car to go straight, your steering wheel is in its central position but the car is pulling to the right. To fix this you need to turn your steering wheel left (Until the car is moving in a straight line), then press and hold the ‘S’ key, then turn your steering wheel to its central position, and release the ‘S’ key. That’s it.
I know its not really an ideal solution, but it might improve the game experience and help us get better laps times :)
In hardriv.cpp, in the "static INPUT_PORTS_START( hdrivair )" section, I've changed this line:-
--- Code: ---PORT_BIT(0xfff, 0x200, IPT_PADDLE) PORT_MINMAX(0x000, 0x3ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_REVERSE PORT_NAME("Steering Wheel")
--- End code ---
to this...
--- Code: ---PORT_BIT( 0xfff, 0x000, IPT_POSITIONAL ) PORT_POSITIONS(0xfff) PORT_WRAPS PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_REVERSE PORT_NAME("Steering Wheel")
--- End code ---
Then in harddriv_m.cpp, replace the hdc68k_wheel_r() function with this...
--- Code: ---uint16_t harddriv_state::hdc68k_wheel_r()
{
// grab the new wheel value
uint16_t new_wheel, raw_wheel = m_12badc[0].read_safe(0xffff);
int wheel_diff = 0;
bool is_wheel_increasing = false;
static uint8_t wheel_snapshot = 0;
static uint8_t wheel_offset = 0;
static bool steering_enabled = true;
if (machine().input().code_pressed(KEYCODE_S))
{
if (steering_enabled)
{
popmessage("Steering disabled (Re-center your wheel now...)");
steering_enabled = false;
wheel_snapshot = (m_hdc68k_last_wheel+wheel_offset)&0xff;
}
return ((wheel_snapshot << 8) | 0xff);
}
else
{
if (!steering_enabled)
{
popmessage("Steering enabled");
steering_enabled = true;
wheel_offset = (wheel_snapshot - raw_wheel)&0xff;
m_hdc68k_last_wheel = raw_wheel;
}
}
// Work out which way the wheel is spinning
if((m_hdc68k_last_wheel < 0x400) && (raw_wheel > 0xC00)) is_wheel_increasing = false; //Wrapped from bottom to top
else if ((m_hdc68k_last_wheel > 0xC00) && (raw_wheel < 0x400)) is_wheel_increasing = true; //Wrapped from top to bottom
else if(m_hdc68k_last_wheel > raw_wheel) is_wheel_increasing = false;
else if(m_hdc68k_last_wheel < raw_wheel) is_wheel_increasing = true;
//Steering damping:
//Ensure we don't jump from one encoder value to another too quickly confusing the game
//The game is aware only of changes to m_12badc's lower byte. This means the game can get easily confused if you where to move
//the wheel very quickly from say position 0x800 to 0xC12 in one cycle (Which was perhaps physically impossible using the
//actual arcade encoder). The game would be under the impression the wheel has moved only 0x12 values, rather than 0x412 values.
//If we detect a large change, slowly feed that information back to the game in managemtble amounts.
new_wheel = m_hdc68k_last_wheel;
while(new_wheel != raw_wheel)
{
if (is_wheel_increasing)
{
if (new_wheel >= 0xFFF) new_wheel = 0x000;
else new_wheel++;
}
else
{
if (new_wheel <= 0x000) new_wheel = 0xFFF;
else new_wheel--;
}
//Lets say the encoder can't move more that 32 teeth per cycle...
if (wheel_diff++ > 0x10) break;
}
if (machine().input().code_pressed(KEYCODE_LSHIFT))
{
popmessage("wheel=0x%04X", new_wheel);
}
m_hdc68k_last_wheel = new_wheel;
return ((new_wheel+wheel_offset) << 8) | 0xff;
}
--- End code ---
--- End quote ---
Hi Geecab,that is a really good solution for the Hard Drivin' Airborne off center bug. I'll need to try it out and see! I'm thinking it would be more responsive when turning the wheel compared to the EMA buffering code I'm currently using to stop it going off center because it adds a very slight latency to the wheel.
Just thought I'd mention this because you seem to be confused about Street Drivin's steering wheel behaviour. Street Drivin's steering is different from Race Drivin' Compact, Hard Drivin' Compact, the cockpit versions AND different from Airborne.
Street Drivin' doesn't have the "steering going off-center bug" when you crash or when you go offroad or even if you turn the wheel too fast etc, it never goes out of alignment. Only the compact versions have that and Airborne. The only reason it seemed to be happening in Street Drivin' before is because the steering range was the same as the others (0x010, 0xff0), when it was changed it to 0x000, 0x3ff it completely fixed the steering, it stops the bug that happens when you steer to the maximum left or right. The change of the PORT_MINMAX to (0x000, 0x3ff) fixed that bug for Airborne too but Airborne has the same bugs that the compact versions have but unfortunately your solution for the compact versions doesn't fix it for Airborne.
BTW I'm now sure that Street Drivin's ROM is actually a cockpit version and I'm even more certain of that now because if you look at the ROM's that get loaded into the main program memory it shares ROM's with Race Drivin' Panorama which on MAME is a cockpit ROM and not a compact. None of the cockpit ROMs are compatible with the compact except the sound ROM's and Jed Margolin even mentions that fact on his website. You can try it for yourself, Street Drivin' already plays perfectly!
Just thought I'd mention it because it could help narrow down the problem Airborne is having because they both have the same steering wheel range in common but Street Drivin' doesn't do the wheel edge/centering stuff the same as any of the others and that is why it doesn't have the bug you were experiencing on the compact versions or Airborne.
I noticed the first set of ROM's in the main program seem to be the ones that contain the test menu code. I was able to load up the Race Drivin Panorama version of the test menu in Street Drivin' by swapping the ROM's over but it made the screen garbled too. It was all readable and seemed to work but had strange values and the writing just looked weird like the resolution is set wrong or something.
I've gave up on my mission of trying to make Street Drivin' have gears by fiddling with the ROM's because today I found out that the Race Drivin' Panorama has the extra stock car track and even has the drone cars from Street Drivin' on it. The only problem i noticed with it was the frame rate even when using my overclock. I fixed this by loading up only the main PCB ROM's and not the left and right PCB ROM's using the Race Drivin' cockpit machine configuration and now the game plays smooth. I think it's because there is a hack in the MAME source code that's used to get the 3 screens in sync and even when you choose 1 screen only in the MAME video options it still seems to be using that hack and using the side PCB's.
geecab:
Hi Yolo!
>>that is a really good solution for the Hard Drivin' Airborne off center bug. I'll need to try it out and see! I
Cool, hope it helps :)
I have to say, I do think Street Drivin is a compact model (Uses 2 optical encoders). It recenters the steering the same as Hard Drivin and Race Drivin compacts. I can simulate it. The main difference is that Hard/Race Drivin Compacts have a CNTSPTRN value around 1024. Street Drivin has a CNTSPTRN value of around 512.
By having your control setup as IPT_PADDLE with PORT_MINMAX to (0x000, 0x3ff), starting at position 0x200, you'll never see Street Drivin try to recenter. You are limiting your turning values to -512 anti clockwise, +512 clockwise (Thus you are not allowing yourself to complete a 1 full rotation in either direction). You have to turn quite a bit beyond a full rotation to cause a recenter. I think this is why it appears setting PORT_MINMAX(0x000, 0x3ff) might have fixed things for you.
Another thing to remember with your Street Drivin setup, if your hdc68k_wheel_r is set to trigger a 'centre edge' only at 0x000, 0x400, 0x800 & 0xC00, you never see a center edge triggered within that control range you have specified. You could manually trigger one at 0x200 and watch your steering offset by -98 (because -98 is the default patcen for street drivin. Unless you've editted the nvram and changed patcen to 0 that is...).
You could do something similar with Hard/Race Drivin' and see the same thing IPT_PADDLE with PORT_MINMAX to (0x000, 0x8ff), starting at position 0x400, You are limiting your turning values to -1024 anti clockwise, +1024 clockwise (Thus you are not allowing yourself to complete a 1 full rotation in either direction). That is assuming you've got an nvram CNTSPTRN set to 1024 patcen set to 0.
I guess in the end though, it doesn't really matter, it nice to know what's going on behind the scenes, but what works for you works for you :)
Btw. New observation (Which desn't really help us but worth mentioning): I noticed when editing nvrams, I couldn't change street drivin's CNTSPTRN from 512 to 1024. Similarly, I couldn't change Hard/Race Drivin's CNTSPTRN from 1024 to 512 (The nvrams are loaded ok, but the new values are ignored). I summarised that the CNTSPTRN value can't be changed massively. Changing the CNTSPTRN works fine if you change them +/- say 100.
Btw. Another observation: I think the compact games don't 'have' to see a center edge always. With the original hardware it would be possible to miss that one single notch on the encoder disk (So the programmers wouldn't want the game to freak out if it were to miss one). Without triggering a center edge at all, the game would just calculate where the rotational center of wheel is based on its CNTSPTRN values, and it would assume the position of the wheel at first reading would be the center position.
Yolo_Swaggins:
Hi geecab i think im confused because of the code changes you made recently on the version your working on because it changes the behaviour of the emulated machine to be more accurate for the latchbit and there was another factor at play too.
I deleted my NVRAM and used the version of mame thats available for download just now and when you load up street drivin' and calibrate the brake then go into the game the car can do a full turn the steering appears not to be limited, i compared it to the arcade doing a full turn the car turns just as sharp there is a video on youtube of a car doing a full turn to the left at the start in hard drivin and if you compare that to what you see in street drivin the car turns the same as that video with the port_minmax set to 0x000,0x3ff and im using a logitech wheel set to 900 degrees. Car can crash and go offroad and does not exhibit the steering bug that was in the compact version of race drivin and hard drivin.
That is when the code in harddriv_m.cpp was like this so the behaviour you are describing would never have been seen by myself or others using the default code.
--- Code: --- /* merge in the wheel edge latch bit */
if (m_hdc68k_wheel_edge)
result ^= 0x4000;
m_hdc68k_last_port1 = result;
return result;
}
uint16_t harddriv_state::hda68k_port1_r()
{
uint16_t result = m_a80000->read();
/* merge in the wheel edge latch bit */
if (m_hdc68k_wheel_edge)
result ^= 0x4000;
return result;
}
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;
}
--- End code ---
There is another thing that was adding to the confusion. On my own build of harddriv.cpp i still had a 0x400 range of steering but i was using 0x800 as the center point and and my code looked like this
--- Code: ---PORT_BIT(0xfff, 0x800, IPT_PADDLE) PORT_CONDITION("mainpcb:SW1", 0x700, EQUALS, 0x100) PORT_MINMAX(0x600, 0xa00) PORT_SENSITIVITY(1) PORT_KEYDELTA(0) PORT_NAME("Original MAME")
--- End code ---
Now this was being used in conjunction with the latch bit fixes you made in your previous code changes which resulted in my wheel never going off center even with a 0x400 range of motion and the default nvram because the center point was still 0x800..........
When i change my harddriv.cpp to have the 0x000 as the starting point and 0x400 as the end point and using 0x200 as the center AND your code fix for the latchbit behaviour i get exactly the same behaviour you describe. This behavior still happens with your modified code even if i change this ((m_hdc68k_last_wheel & 0xc00) != (new_wheel & 0xc00)) to ((m_hdc68k_last_wheel & 0xf00) != (new_wheel & 0xf00)) which is the default on mame right now because the latchbit behaviour above that part of the code was fixed by you in your version so now i understand what the discrepancy has been between what you observed and what i observed! ;D
I just spent some time trying to figure it out because something seemed off to me now it makes perfect sense!
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version