I think it might be hard for anyone who doesn't engage in a subtractive art like this to appreciate it fully.
True dat. The guy who made the viking that I copied also made some cute gnomes. Now take a wild guess which ones most people liked more
May 11, 2024, 01:24:24 am
I think it might be hard for anyone who doesn't engage in a subtractive art like this to appreciate it fully.
By the way, thanks for that reply ThatOneSeong. It was enlightening. I think choices like this get made earlier on in making a program and then get harder and harder to fix later on. So it just becomes the way it is.Right.
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: [Select]PORT_BIT(0xfff, 0x200, IPT_PADDLE) PORT_MINMAX(0x000, 0x3ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_REVERSE PORT_NAME("Steering Wheel")
to this...Code: [Select]PORT_BIT( 0xfff, 0x000, IPT_POSITIONAL ) PORT_POSITIONS(0xfff) PORT_WRAPS PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_REVERSE PORT_NAME("Steering Wheel")
Then in harddriv_m.cpp, replace the hdc68k_wheel_r() function with this...Code: [Select]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;
}
Now, I've been using this for a while and have a few callouts to anyone who is thinking about designing a similar one.
1. If you're going to build a 4-player cab like mine, then 1 big mistake I made is with how the display is inset. This is more of a 3-player build now even though it supports 4 players. If you look closely, the display is about 4 inches into the cabinet. The IR LEDs then surround the screen. Well, the lightguns can only see all 4 IR LEDS if relatively in front of the screen. The ~4-inch inset of the display causes the sides to act like flaps that block the IR. So if you are too far off to the side, then only 3 sensors will be visible. Only 3 people can visibly stand in front of the screen and see all 4 LEDs.
I should have cut the sides in more so that they're flush with the edge of the screen.
2. soldering the gx16 was pretty tight since it needed to accommodate wire that was thick enough to handle 24v at ~3amps. Between the sockets, cables, and lightgun, it means that you're going to be soldering 16 tiny ends that barely fit into the casings, and then make sure that there are no shorts. I'd still do it again because I think it's worth it, but it's probably the most tedious part of the build. I'm looking to limit mine to 2 people only, but that's still something for me to consider If I ever wanted to add additional guns it's definitely something I should plan for on the front end of things.
3. I got the Streamdeck partially because I thought that I could use it for keyboard events as well. I.e., have all of the Dreamcast buttons available to navigate game menus and whatnot. Unfortunately, the thing does not support raw keyboard events. It sends system events. This means that emulators which rely on raw input (such as Flycast) cannot use the Streamdeck to send keys because it either support SDL or raw input, but not both. Emulators that support SDL are ok though.
Not too much, but I mostly wanted to call out #1 since it's a pretty important defect.
FINALLY, I've attached my sketchup plans to the original post in case anyone wants to use them as a base.
PORT_BIT(0xfff, 0x200, IPT_PADDLE) PORT_MINMAX(0x000, 0x3ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_REVERSE PORT_NAME("Steering Wheel")
to this...PORT_BIT( 0xfff, 0x000, IPT_POSITIONAL ) PORT_POSITIONS(0xfff) PORT_WRAPS PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_REVERSE PORT_NAME("Steering Wheel")
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;
}