saturnus: get rid of the round-tripping of analogs through the mednafen input system.

This commit is contained in:
nattthebear 2017-06-18 12:25:01 -04:00
parent 9ff2da5265
commit 37b285fe8d
6 changed files with 792 additions and 824 deletions

View File

@ -98,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
private abstract class ButtonedDevice : IDevice private abstract class ButtonedDevice : IDevice
{ {
private static readonly FloatRange AnalogFloatRange = new FloatRange(-32767, 0, 32767); private static readonly FloatRange AnalogFloatRange = new FloatRange(0, 128, 255);
protected ButtonedDevice() protected ButtonedDevice()
{ {
@ -164,13 +164,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
int pos = offset + AnalogByteOffset; int pos = offset + AnalogByteOffset;
for (int i = 0; i < _bakedAnalogNames.Length; i++) for (int i = 0; i < _bakedAnalogNames.Length; i++)
{ {
var data = (int)controller.GetFloat(_bakedAnalogNames[i]); var data = (byte)(int)controller.GetFloat(_bakedAnalogNames[i]);
var datal = (short)Math.Max(-data, 0); dest[pos++] = data;
var datar = (short)Math.Max(data, 0);
dest[pos++] = (byte)datal;
dest[pos++] = (byte)(datal >> 8);
dest[pos++] = (byte)datar;
dest[pos++] = (byte)(datar >> 8);
} }
} }
@ -233,11 +228,18 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
{ {
"Stick Horizontal", "Stick Horizontal",
"Stick Vertical", "Stick Vertical",
"Third Axis" "Left Shoulder",
"Right Shoulder"
}; };
protected override string[] AnalogNames => _analogNames; protected override string[] AnalogNames => _analogNames;
public ThreeDeeGamepad()
{
Definition.FloatRanges[2] = new FloatRange(0, 0, 255);
Definition.FloatRanges[3] = new FloatRange(0, 0, 255);
}
public override void Update(IController controller, byte[] dest, int offset) public override void Update(IController controller, byte[] dest, int offset)
{ {
base.Update(controller, dest, offset); base.Update(controller, dest, offset);
@ -248,37 +250,19 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
private class Mouse : ButtonedDevice private class Mouse : ButtonedDevice
{ {
private static readonly FloatRange MouseFloatRange = new FloatRange(-32768, 0, 32767);
private static readonly string[] _buttonNames = private static readonly string[] _buttonNames =
{ {
"Left", "Right", "Middle", "Start" "Left", "Right", "Middle", "Start"
}; };
protected override string[] ButtonNames => _buttonNames; protected override string[] ButtonNames => _buttonNames;
protected override int ButtonByteOffset => 8;
private static readonly string[] _analogNames =
public Mouse()
{ {
Definition.FloatControls.AddRange(new[] { "0X", "0Y" }); "X", "Y"
Definition.FloatRanges.AddRange(new[] { MouseFloatRange, MouseFloatRange }); };
}
private void SetMouseAxis(float value, byte[] dest, int offset) protected override string[] AnalogNames => _analogNames;
{
var data = (short)value;
dest[offset++] = 0;
dest[offset++] = 0;
dest[offset++] = (byte)data;
dest[offset++] = (byte)(data >> 8);
}
public override void Update(IController controller, byte[] dest, int offset)
{
base.Update(controller, dest, offset);
SetMouseAxis(controller.GetFloat("0X"), dest, offset + 0);
SetMouseAxis(controller.GetFloat("0Y"), dest, offset + 4);
}
} }
private class Wheel : ButtonedDevice private class Wheel : ButtonedDevice
@ -319,7 +303,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
}; };
protected override string[] AnalogNames => _analogNames; protected override string[] AnalogNames => _analogNames;
protected override int AnalogByteOffset => 3; protected override int AnalogByteOffset => 4;
} }
private class DualMission : Mission private class DualMission : Mission

Binary file not shown.

View File

@ -1,176 +1,168 @@
/******************************************************************************/ /******************************************************************************/
/* Mednafen Sega Saturn Emulation Module */ /* Mednafen Sega Saturn Emulation Module */
/******************************************************************************/ /******************************************************************************/
/* 3dpad.cpp: /* 3dpad.cpp:
** Copyright (C) 2016-2017 Mednafen Team ** Copyright (C) 2016-2017 Mednafen Team
** **
** This program is free software; you can redistribute it and/or ** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation, Inc., ** along with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "common.h" #include "common.h"
#include "3dpad.h" #include "3dpad.h"
namespace MDFN_IEN_SS namespace MDFN_IEN_SS
{ {
IODevice_3DPad::IODevice_3DPad() : dbuttons(0), mode(false) IODevice_3DPad::IODevice_3DPad() : dbuttons(0), mode(false)
{ {
} }
IODevice_3DPad::~IODevice_3DPad() IODevice_3DPad::~IODevice_3DPad()
{ {
} }
void IODevice_3DPad::Power(void) void IODevice_3DPad::Power(void)
{ {
phase = -1; phase = -1;
tl = true; tl = true;
data_out = 0x01; data_out = 0x01;
} }
void IODevice_3DPad::UpdateInput(const uint8* data, const int32 time_elapsed) void IODevice_3DPad::UpdateInput(const uint8 *data, const int32 time_elapsed)
{ {
const uint16 dtmp = MDFN_de16lsb(&data[0]); const uint16 dtmp = MDFN_de16lsb(&data[0]);
dbuttons = (dbuttons & 0x8800) | (dtmp & 0x0FFF); dbuttons = (dbuttons & 0x8800) | (dtmp & 0x0FFF);
mode = (bool)(dtmp & 0x1000); mode = (bool)(dtmp & 0x1000);
for(unsigned axis = 0; axis < 2; axis++) thumb[0] = data[2];
{ thumb[1] = data[3];
int32 tmp = 32767 + MDFN_de16lsb(&data[0x2 + (axis << 2) + 2]) - MDFN_de16lsb(&data[0x2 + (axis << 2) + 0]); shoulder[0] = data[4];
shoulder[1] = data[5];
if(tmp >= (32767 - 128) && tmp < 32767)
tmp = 32767; for (unsigned w = 0; w < 2; w++)
{
tmp = (tmp * 255 + 32767) / 65534; // May not be right for digital mode, but shouldn't matter too much:
thumb[axis] = tmp; if (shoulder[w] <= 0x55)
} dbuttons &= ~(0x0800 << (w << 2));
else if (shoulder[w] >= 0x8E)
for(unsigned w = 0; w < 2; w++) dbuttons |= 0x0800 << (w << 2);
{ }
shoulder[w] = (MDFN_de16lsb(&data[0xA + (w << 1)]) * 255 + 16383) / 32767; }
// May not be right for digital mode, but shouldn't matter too much: uint8 IODevice_3DPad::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
if(shoulder[w] <= 0x55) {
dbuttons &= ~(0x0800 << (w << 2)); uint8 tmp;
else if(shoulder[w] >= 0x8E)
dbuttons |= 0x0800 << (w << 2); if(smpc_out & 0x40)
} {
} phase = -1;
tl = true;
uint8 IODevice_3DPad::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) data_out = 0x01;
{ }
uint8 tmp; else
{
if(smpc_out & 0x40) if((bool)(smpc_out & 0x20) != tl)
{ {
phase = -1; if(phase < 15)
tl = true; {
data_out = 0x01; tl = !tl;
} phase++;
else }
{
if((bool)(smpc_out & 0x20) != tl) if(!phase)
{ {
if(phase < 15) if(mode)
{ {
tl = !tl; buffer[ 0] = 0x1;
phase++; buffer[ 1] = 0x6;
} buffer[ 2] = (((dbuttons >> 0) & 0xF) ^ 0xF);
buffer[ 3] = (((dbuttons >> 4) & 0xF) ^ 0xF);
if(!phase) buffer[ 4] = (((dbuttons >> 8) & 0xF) ^ 0xF);
{ buffer[ 5] = (((dbuttons >> 12) & 0xF) ^ 0xF);
if(mode) buffer[ 6] = (thumb[0] >> 4) & 0xF;
{ buffer[ 7] = (thumb[0] >> 0) & 0xF;
buffer[ 0] = 0x1; buffer[ 8] = (thumb[1] >> 4) & 0xF;
buffer[ 1] = 0x6; buffer[ 9] = (thumb[1] >> 0) & 0xF;
buffer[ 2] = (((dbuttons >> 0) & 0xF) ^ 0xF); buffer[10] = (shoulder[0] >> 4) & 0xF;
buffer[ 3] = (((dbuttons >> 4) & 0xF) ^ 0xF); buffer[11] = (shoulder[0] >> 0) & 0xF;
buffer[ 4] = (((dbuttons >> 8) & 0xF) ^ 0xF); buffer[12] = (shoulder[1] >> 4) & 0xF;
buffer[ 5] = (((dbuttons >> 12) & 0xF) ^ 0xF); buffer[13] = (shoulder[1] >> 0) & 0xF;
buffer[ 6] = (thumb[0] >> 4) & 0xF; buffer[14] = 0x0;
buffer[ 7] = (thumb[0] >> 0) & 0xF; buffer[15] = 0x1;
buffer[ 8] = (thumb[1] >> 4) & 0xF; }
buffer[ 9] = (thumb[1] >> 0) & 0xF; else
buffer[10] = (shoulder[0] >> 4) & 0xF; {
buffer[11] = (shoulder[0] >> 0) & 0xF; phase = 8;
buffer[12] = (shoulder[1] >> 4) & 0xF; buffer[ 8] = 0x0;
buffer[13] = (shoulder[1] >> 0) & 0xF; buffer[ 9] = 0x2;
buffer[14] = 0x0; buffer[10] = (((dbuttons >> 0) & 0xF) ^ 0xF);
buffer[15] = 0x1; buffer[11] = (((dbuttons >> 4) & 0xF) ^ 0xF);
} buffer[12] = (((dbuttons >> 8) & 0xF) ^ 0xF);
else buffer[13] = (((dbuttons >> 12) & 0xF) ^ 0xF);
{ buffer[14] = 0x0;
phase = 8; buffer[15] = 0x1;
buffer[ 8] = 0x0; }
buffer[ 9] = 0x2; }
buffer[10] = (((dbuttons >> 0) & 0xF) ^ 0xF);
buffer[11] = (((dbuttons >> 4) & 0xF) ^ 0xF); data_out = buffer[phase];
buffer[12] = (((dbuttons >> 8) & 0xF) ^ 0xF); }
buffer[13] = (((dbuttons >> 12) & 0xF) ^ 0xF); }
buffer[14] = 0x0;
buffer[15] = 0x1; tmp = (tl << 4) | data_out;
}
} return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
}
data_out = buffer[phase];
} static const char* const ModeSwitchPositions[] =
} {
gettext_noop("Digital(+)"),
tmp = (tl << 4) | data_out; gettext_noop("Analog(○)"),
};
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
} IDIISG IODevice_3DPad_IDII =
{
static const char* const ModeSwitchPositions[] = { "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" },
{ { "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" },
gettext_noop("Digital(+)"), { "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" },
gettext_noop("Analog(○)"), { "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" },
};
{ "b", "B", 6, IDIT_BUTTON },
IDIISG IODevice_3DPad_IDII = { "c", "C", 7, IDIT_BUTTON },
{ { "a", "A", 5, IDIT_BUTTON },
{ "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" }, { "start", "START", 4, IDIT_BUTTON },
{ "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" },
{ "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" }, { "z", "Z", 10, IDIT_BUTTON },
{ "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" }, { "y", "Y", 9, IDIT_BUTTON },
{ "x", "X", 8, IDIT_BUTTON },
{ "b", "B", 6, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ "c", "C", 7, IDIT_BUTTON },
{ "a", "A", 5, IDIT_BUTTON }, IDIIS_Switch("mode", "Mode", 17, ModeSwitchPositions, sizeof(ModeSwitchPositions) / sizeof(ModeSwitchPositions[0])),
{ "start", "START", 4, IDIT_BUTTON },
{ "analog_left", "Analog LEFT ←", 15, IDIT_BUTTON_ANALOG },
{ "z", "Z", 10, IDIT_BUTTON }, { "analog_right", "Analog RIGHT →", 16, IDIT_BUTTON_ANALOG },
{ "y", "Y", 9, IDIT_BUTTON }, { "analog_up", "Analog UP ↑", 13, IDIT_BUTTON_ANALOG },
{ "x", "X", 8, IDIT_BUTTON }, { "analog_down", "Analog DOWN ↓", 14, IDIT_BUTTON_ANALOG },
{ NULL, "empty", 0, IDIT_BUTTON },
{ "rs", "Right Shoulder (Analog)", 12, IDIT_BUTTON_ANALOG },
IDIIS_Switch("mode", "Mode", 17, ModeSwitchPositions, sizeof(ModeSwitchPositions) / sizeof(ModeSwitchPositions[0])), { "ls", "Left Shoulder (Analog)", 11, IDIT_BUTTON_ANALOG },
};
{ "analog_left", "Analog LEFT ←", 15, IDIT_BUTTON_ANALOG },
{ "analog_right", "Analog RIGHT →", 16, IDIT_BUTTON_ANALOG },
{ "analog_up", "Analog UP ↑", 13, IDIT_BUTTON_ANALOG },
{ "analog_down", "Analog DOWN ↓", 14, IDIT_BUTTON_ANALOG },
}
{ "rs", "Right Shoulder (Analog)", 12, IDIT_BUTTON_ANALOG },
{ "ls", "Left Shoulder (Analog)", 11, IDIT_BUTTON_ANALOG },
};
}

View File

@ -1,330 +1,329 @@
/******************************************************************************/ /******************************************************************************/
/* Mednafen Sega Saturn Emulation Module */ /* Mednafen Sega Saturn Emulation Module */
/******************************************************************************/ /******************************************************************************/
/* mission.cpp: /* mission.cpp:
** Copyright (C) 2017 Mednafen Team ** Copyright (C) 2017 Mednafen Team
** **
** This program is free software; you can redistribute it and/or ** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation, Inc., ** along with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
/* /*
Real mission stick has bugs and quirks that aren't emulated here(like apparently latching/updating the physical input state at the end of the Real mission stick has bugs and quirks that aren't emulated here(like apparently latching/updating the physical input state at the end of the
read sequence instead of near the beginning like other controllers do, resulting in increased latency). read sequence instead of near the beginning like other controllers do, resulting in increased latency).
*/ */
#include "common.h" #include "common.h"
#include "mission.h" #include "mission.h"
namespace MDFN_IEN_SS namespace MDFN_IEN_SS
{ {
IODevice_Mission::IODevice_Mission(const bool dual_) : dbuttons(0), afeswitches(0), afspeed(0), dual(dual_) IODevice_Mission::IODevice_Mission(const bool dual_) : dbuttons(0), afeswitches(0), afspeed(0), dual(dual_)
{ {
} }
IODevice_Mission::~IODevice_Mission() IODevice_Mission::~IODevice_Mission()
{ {
} }
void IODevice_Mission::Power(void) void IODevice_Mission::Power(void)
{ {
phase = -1; phase = -1;
tl = true; tl = true;
data_out = 0x01; data_out = 0x01;
// Power-on state not tested: // Power-on state not tested:
afcounter = 0; afcounter = 0;
afphase = false; afphase = false;
} }
void IODevice_Mission::UpdateInput(const uint8* data, const int32 time_elapsed) void IODevice_Mission::UpdateInput(const uint8 *data, const int32 time_elapsed)
{ {
const uint32 dtmp = MDFN_de32lsb(&data[0]); const uint32 dtmp = MDFN_de32lsb(&data[0]);
dbuttons = (dbuttons & 0xF) | ((dtmp & 0xFFF) << 4); dbuttons = (dbuttons & 0xF) | ((dtmp & 0xFFF) << 4);
afeswitches = ((dtmp >> 12) & 0x8FF) << 4; afeswitches = ((dtmp >> 12) & 0x8FF) << 4;
afspeed = (dtmp >> 20) & 0x7; afspeed = (dtmp >> 20) & 0x7;
for(unsigned stick = 0; stick < (dual ? 2 : 1); stick++) int offs = 4;
{ for (unsigned stick = 0; stick < (dual ? 2 : 1); stick++)
for(unsigned axis = 0; axis < 3; axis++) {
{ for (unsigned axis = 0; axis < 3; axis++)
int32 tmp = 32767 + MDFN_de16lsb(&data[0x3 + ((axis + (stick * 3)) * 4) + 2]) - MDFN_de16lsb(&data[0x3 + ((axis + (stick * 3)) * 4) + 0]); {
axes[stick][axis] = data[offs++];
axes[stick][axis] = (tmp * 255 + 32767) / 65534; }
} }
}
//printf("Update: %02x %02x %02x\n", axes[0][0], axes[0][1], axes[0][2]);
//printf("Update: %02x %02x %02x\n", axes[0][0], axes[0][1], axes[0][2]); }
}
uint8 IODevice_Mission::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
uint8 IODevice_Mission::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) {
{ uint8 tmp;
uint8 tmp;
if(smpc_out & 0x40)
if(smpc_out & 0x40) {
{ phase = -1;
phase = -1; tl = true;
tl = true; data_out = 0x01;
data_out = 0x01; }
} else
else {
{ if((bool)(smpc_out & 0x20) != tl)
if((bool)(smpc_out & 0x20) != tl) {
{ if(phase < (dual ? 21 : 13))
if(phase < (dual ? 21 : 13)) {
{ tl = !tl;
tl = !tl; phase++;
phase++; }
}
if(!phase)
if(!phase) {
{ unsigned dbaf = dbuttons & ((afphase - 1) | ~afeswitches);
unsigned dbaf = dbuttons & ((afphase - 1) | ~afeswitches); unsigned c = 0;
unsigned c = 0;
// Digital Left
// Digital Left dbuttons |= ((axes[0][0] <= 0x56) ? 0x4 : 0);
dbuttons |= ((axes[0][0] <= 0x56) ? 0x4 : 0); dbuttons &= ~((axes[0][0] >= 0x6C) ? 0x4 : 0);
dbuttons &= ~((axes[0][0] >= 0x6C) ? 0x4 : 0);
// Digital Right
// Digital Right dbuttons |= ((axes[0][0] >= 0xAB) ? 0x8 : 0);
dbuttons |= ((axes[0][0] >= 0xAB) ? 0x8 : 0); dbuttons &= ~((axes[0][0] <= 0x95) ? 0x8 : 0);
dbuttons &= ~((axes[0][0] <= 0x95) ? 0x8 : 0);
// Digital Up
// Digital Up dbuttons |= ((axes[0][1] <= 0x54) ? 0x1 : 0);
dbuttons |= ((axes[0][1] <= 0x54) ? 0x1 : 0); dbuttons &= ~((axes[0][1] >= 0x6A) ? 0x1 : 0);
dbuttons &= ~((axes[0][1] >= 0x6A) ? 0x1 : 0);
// Digital Down
// Digital Down dbuttons |= ((axes[0][1] >= 0xA9) ? 0x2 : 0);
dbuttons |= ((axes[0][1] >= 0xA9) ? 0x2 : 0); dbuttons &= ~((axes[0][1] <= 0x94) ? 0x2 : 0);
dbuttons &= ~((axes[0][1] <= 0x94) ? 0x2 : 0);
if(!afcounter)
if(!afcounter) {
{ static const uint8 speedtab[7] = { 12, 8, 7, 5, 4, 4/* ? */, 1 };
static const uint8 speedtab[7] = { 12, 8, 7, 5, 4, 4/* ? */, 1 }; afphase = !afphase;
afphase = !afphase; afcounter = speedtab[afspeed];
afcounter = speedtab[afspeed]; }
} afcounter--;
afcounter--;
buffer[c++] = 0x1;
buffer[c++] = 0x1; buffer[c++] = dual ? 0x9 : 0x5;
buffer[c++] = dual ? 0x9 : 0x5; buffer[c++] = (((dbaf >> 0) & 0xF) ^ 0xF);
buffer[c++] = (((dbaf >> 0) & 0xF) ^ 0xF); buffer[c++] = (((dbaf >> 4) & 0xF) ^ 0xF);
buffer[c++] = (((dbaf >> 4) & 0xF) ^ 0xF); buffer[c++] = (((dbaf >> 8) & 0xF) ^ 0xF);
buffer[c++] = (((dbaf >> 8) & 0xF) ^ 0xF); buffer[c++] = (((dbaf >> 12) & 0xF) ^ 0xF);
buffer[c++] = (((dbaf >> 12) & 0xF) ^ 0xF);
for(unsigned stick = 0; stick < (dual ? 2 : 1); stick++)
for(unsigned stick = 0; stick < (dual ? 2 : 1); stick++) {
{ if(stick)
if(stick) {
{ // Not sure, looks like something buggy.
// Not sure, looks like something buggy. buffer[c++] = 0x0;
buffer[c++] = 0x0; buffer[c++] = 0x0;
buffer[c++] = 0x0; }
}
buffer[c++] = (axes[stick][0] >> 4) & 0xF;
buffer[c++] = (axes[stick][0] >> 4) & 0xF; buffer[c++] = (axes[stick][0] >> 0) & 0xF;
buffer[c++] = (axes[stick][0] >> 0) & 0xF; buffer[c++] = (axes[stick][1] >> 4) & 0xF;
buffer[c++] = (axes[stick][1] >> 4) & 0xF; buffer[c++] = (axes[stick][1] >> 0) & 0xF;
buffer[c++] = (axes[stick][1] >> 0) & 0xF; buffer[c++] = (axes[stick][2] >> 4) & 0xF;
buffer[c++] = (axes[stick][2] >> 4) & 0xF; buffer[c++] = (axes[stick][2] >> 0) & 0xF;
buffer[c++] = (axes[stick][2] >> 0) & 0xF; }
} buffer[c++] = 0x0;
buffer[c++] = 0x0; buffer[c++] = 0x1;
buffer[c++] = 0x1; }
}
data_out = buffer[phase];
data_out = buffer[phase]; }
} }
}
tmp = (tl << 4) | data_out;
tmp = (tl << 4) | data_out;
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted); }
}
static const char* const SpeedSwitchPositions[] =
static const char* const SpeedSwitchPositions[] = {
{ gettext_noop("1/7"),
gettext_noop("1/7"), gettext_noop("2/7"),
gettext_noop("2/7"), gettext_noop("3/7"),
gettext_noop("3/7"), gettext_noop("4/7"),
gettext_noop("4/7"), gettext_noop("5/7"),
gettext_noop("5/7"), gettext_noop("6/7"),
gettext_noop("6/7"), gettext_noop("7/7")
gettext_noop("7/7") };
};
static const char* const AFSwitchPositions[] =
static const char* const AFSwitchPositions[] = {
{ gettext_noop("• (Off)"),
gettext_noop("• (Off)"), gettext_noop("•• (On)")
gettext_noop("•• (On)") };
};
IDIISG IODevice_Mission_IDII =
IDIISG IODevice_Mission_IDII = {
{ // 0
// 0 { "b", "B (Stick Left Button)", 6, IDIT_BUTTON },
{ "b", "B (Stick Left Button)", 6, IDIT_BUTTON }, { "c", "C (Stick Right Button)", 8, IDIT_BUTTON },
{ "c", "C (Stick Right Button)", 8, IDIT_BUTTON }, { "a", "A (Stick Trigger)", 7, IDIT_BUTTON },
{ "a", "A (Stick Trigger)", 7, IDIT_BUTTON }, { "start", "START", 9, IDIT_BUTTON },
{ "start", "START", 9, IDIT_BUTTON },
// 4
// 4 { "z", "Z", 13, IDIT_BUTTON },
{ "z", "Z", 13, IDIT_BUTTON }, { "y", "Y", 12, IDIT_BUTTON },
{ "y", "Y", 12, IDIT_BUTTON }, { "x", "X", 11, IDIT_BUTTON },
{ "x", "X", 11, IDIT_BUTTON }, { "r", "R", 14, IDIT_BUTTON },
{ "r", "R", 14, IDIT_BUTTON },
// 8
// 8 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { "l", "L", 10, IDIT_BUTTON },
{ "l", "L", 10, IDIT_BUTTON },
// 12
// 12 IDIIS_Switch("afb", "B AF", 20, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afb", "B AF", 20, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afc", "C AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afc", "C AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afa", "A AF", 19, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afa", "A AF", 19, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
// 16
// 16 IDIIS_Switch("afz", "Z AF", 17, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afz", "Z AF", 17, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afy", "Y AF", 16, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afy", "Y AF", 16, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afx", "X AF", 15, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afx", "X AF", 15, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afr", "R AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afr", "R AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
// 20
// 20 IDIIS_Switch("afspeed", "AF Speed", 23, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])),
IDIIS_Switch("afspeed", "AF Speed", 23, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])), IDIIS_Switch("afl", "L AF", 18, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afl", "L AF", 18, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
// 24
// 24 { "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
{ "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG }, { "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
{ "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG }, { "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
{ "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG }, { "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG }, { "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
{ "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG }, };
};
IDIISG IODevice_MissionNoAF_IDII =
IDIISG IODevice_MissionNoAF_IDII = {
{ // 0
// 0 { "b", "B (Stick Left Button)", 6, IDIT_BUTTON },
{ "b", "B (Stick Left Button)", 6, IDIT_BUTTON }, { "c", "C (Stick Right Button)", 8, IDIT_BUTTON },
{ "c", "C (Stick Right Button)", 8, IDIT_BUTTON }, { "a", "A (Stick Trigger)", 7, IDIT_BUTTON },
{ "a", "A (Stick Trigger)", 7, IDIT_BUTTON }, { "start", "START", 9, IDIT_BUTTON },
{ "start", "START", 9, IDIT_BUTTON },
// 4
// 4 { "z", "Z", 13, IDIT_BUTTON },
{ "z", "Z", 13, IDIT_BUTTON }, { "y", "Y", 12, IDIT_BUTTON },
{ "y", "Y", 12, IDIT_BUTTON }, { "x", "X", 11, IDIT_BUTTON },
{ "x", "X", 11, IDIT_BUTTON }, { "r", "R", 14, IDIT_BUTTON },
{ "r", "R", 14, IDIT_BUTTON },
// 8
// 8 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { "l", "L", 10, IDIT_BUTTON },
{ "l", "L", 10, IDIT_BUTTON },
// 12
// 12 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
// 16
// 16 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
// 20
// 20 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
// 24
// 24 { "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
{ "stick_left", "Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG }, { "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
{ "stick_right", "Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG }, { "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
{ "stick_fore", "Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG }, { "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "stick_back", "Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
{ "throttle_down", "Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG }, { "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
{ "throttle_up", "Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG }, };
};
IDIISG IODevice_DualMission_IDII =
IDIISG IODevice_DualMission_IDII = {
{ // 0
// 0 { "b", "B (R Stick Left Button)", 15, IDIT_BUTTON },
{ "b", "B (R Stick Left Button)", 15, IDIT_BUTTON }, { "c", "C (R Stick Right Button)", 17, IDIT_BUTTON },
{ "c", "C (R Stick Right Button)", 17, IDIT_BUTTON }, { "a", "A (R Stick Trigger)", 16, IDIT_BUTTON },
{ "a", "A (R Stick Trigger)", 16, IDIT_BUTTON }, { "start", "START", 18, IDIT_BUTTON },
{ "start", "START", 18, IDIT_BUTTON },
// 4
// 4 { "z", "Z (L Stick Right Button)", 8, IDIT_BUTTON },
{ "z", "Z (L Stick Right Button)", 8, IDIT_BUTTON }, { "y", "Y (L Stick Left Button)", 6, IDIT_BUTTON },
{ "y", "Y (L Stick Left Button)", 6, IDIT_BUTTON }, { "x", "X (L Stick Trigger)", 7, IDIT_BUTTON },
{ "x", "X (L Stick Trigger)", 7, IDIT_BUTTON }, { "r", "R", 20, IDIT_BUTTON },
{ "r", "R", 20, IDIT_BUTTON },
// 8
// 8 { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { "l", "L", 19, IDIT_BUTTON },
{ "l", "L", 19, IDIT_BUTTON },
// 12
// 12 IDIIS_Switch("afb", "B AF", 26, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afb", "B AF", 26, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afc", "C AF", 27, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afc", "C AF", 27, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afa", "A AF", 25, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afa", "A AF", 25, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
// 16
// 16 IDIIS_Switch("afz", "Z AF", 23, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afz", "Z AF", 23, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afy", "Y AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afy", "Y AF", 22, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afx", "X AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afx", "X AF", 21, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])), IDIIS_Switch("afr", "R AF", 28, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afr", "R AF", 28, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
// 20
// 20 IDIIS_Switch("afspeed", "Autofire Speed", 29, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])),
IDIIS_Switch("afspeed", "Autofire Speed", 29, SpeedSwitchPositions, sizeof(SpeedSwitchPositions) / sizeof(SpeedSwitchPositions[0])), IDIIS_Switch("afl", "L AF", 24, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
IDIIS_Switch("afl", "L AF", 24, AFSwitchPositions, sizeof(AFSwitchPositions) / sizeof(AFSwitchPositions[0])),
// 24
// 24 { "rstick_left", "R Stick LEFT ← (Analog)", 11, IDIT_BUTTON_ANALOG },
{ "rstick_left", "R Stick LEFT ← (Analog)", 11, IDIT_BUTTON_ANALOG }, { "rstick_right", "R Stick RIGHT → (Analog)", 12, IDIT_BUTTON_ANALOG },
{ "rstick_right", "R Stick RIGHT → (Analog)", 12, IDIT_BUTTON_ANALOG }, { "rstick_fore", "R Stick FORE ↑ (Analog)", 9, IDIT_BUTTON_ANALOG },
{ "rstick_fore", "R Stick FORE ↑ (Analog)", 9, IDIT_BUTTON_ANALOG }, { "rstick_back", "R Stick BACK ↓ (Analog)", 10, IDIT_BUTTON_ANALOG },
{ "rstick_back", "R Stick BACK ↓ (Analog)", 10, IDIT_BUTTON_ANALOG },
{ "rthrottle_down", "R Throttle Down (Analog)", 14, IDIT_BUTTON_ANALOG },
{ "rthrottle_down", "R Throttle Down (Analog)", 14, IDIT_BUTTON_ANALOG }, { "rthrottle_up", "R Throttle Up (Analog)", 13, IDIT_BUTTON_ANALOG },
{ "rthrottle_up", "R Throttle Up (Analog)", 13, IDIT_BUTTON_ANALOG },
{ "lstick_left", "L Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG },
{ "lstick_left", "L Stick LEFT ← (Analog)", 2, IDIT_BUTTON_ANALOG }, { "lstick_right", "L Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG },
{ "lstick_right", "L Stick RIGHT → (Analog)", 3, IDIT_BUTTON_ANALOG }, { "lstick_fore", "L Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG },
{ "lstick_fore", "L Stick FORE ↑ (Analog)", 0, IDIT_BUTTON_ANALOG }, { "lstick_back", "L Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "lstick_back", "L Stick BACK ↓ (Analog)", 1, IDIT_BUTTON_ANALOG },
{ "lthrottle_down", "L Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG },
{ "lthrottle_down", "L Throttle Down (Analog)", 5, IDIT_BUTTON_ANALOG }, { "lthrottle_up", "L Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
{ "lthrottle_up", "L Throttle Up (Analog)", 4, IDIT_BUTTON_ANALOG },
};
};
}
}

View File

@ -1,143 +1,143 @@
/******************************************************************************/ /******************************************************************************/
/* Mednafen Sega Saturn Emulation Module */ /* Mednafen Sega Saturn Emulation Module */
/******************************************************************************/ /******************************************************************************/
/* mouse.cpp: /* mouse.cpp:
** Copyright (C) 2016-2017 Mednafen Team ** Copyright (C) 2016-2017 Mednafen Team
** **
** This program is free software; you can redistribute it and/or ** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation, Inc., ** along with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "common.h" #include "common.h"
#include "mouse.h" #include "mouse.h"
namespace MDFN_IEN_SS namespace MDFN_IEN_SS
{ {
IODevice_Mouse::IODevice_Mouse() : buttons(0) IODevice_Mouse::IODevice_Mouse() : buttons(0)
{ {
} }
IODevice_Mouse::~IODevice_Mouse() IODevice_Mouse::~IODevice_Mouse()
{ {
} }
void IODevice_Mouse::Power(void) void IODevice_Mouse::Power(void)
{ {
phase = -1; phase = -1;
tl = true; tl = true;
data_out = 0x00; data_out = 0x00;
accum_xdelta = 0; accum_xdelta = 0;
accum_ydelta = 0; accum_ydelta = 0;
} }
void IODevice_Mouse::UpdateInput(const uint8* data, const int32 time_elapsed) void IODevice_Mouse::UpdateInput(const uint8* data, const int32 time_elapsed)
{ {
accum_xdelta += MDFN_de32lsb(&data[0]); accum_xdelta += data[1];
accum_ydelta -= MDFN_de32lsb(&data[4]); accum_ydelta -= data[2];
buttons = data[8] & 0xF; buttons = data[0] & 0xF;
} }
uint8 IODevice_Mouse::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) uint8 IODevice_Mouse::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
{ {
uint8 tmp; uint8 tmp;
if(smpc_out & 0x40) if(smpc_out & 0x40)
{ {
if(smpc_out & 0x20) if(smpc_out & 0x20)
{ {
if(!tl) if(!tl)
accum_xdelta = accum_ydelta = 0; accum_xdelta = accum_ydelta = 0;
phase = -1; phase = -1;
tl = true; tl = true;
data_out = 0x00; data_out = 0x00;
} }
else else
{ {
if(tl) if(tl)
tl = false; tl = false;
} }
} }
else else
{ {
if(phase < 0) if(phase < 0)
{ {
uint8 flags = 0; uint8 flags = 0;
if(accum_xdelta < 0) if(accum_xdelta < 0)
flags |= 0x1; flags |= 0x1;
if(accum_ydelta < 0) if(accum_ydelta < 0)
flags |= 0x2; flags |= 0x2;
if(accum_xdelta > 255 || accum_xdelta < -256) if(accum_xdelta > 255 || accum_xdelta < -256)
{ {
flags |= 0x4; flags |= 0x4;
accum_xdelta = (accum_xdelta < 0) ? -256 : 255; accum_xdelta = (accum_xdelta < 0) ? -256 : 255;
} }
if(accum_ydelta > 255 || accum_ydelta < -256) if(accum_ydelta > 255 || accum_ydelta < -256)
{ {
flags |= 0x8; flags |= 0x8;
accum_ydelta = (accum_ydelta < 0) ? -256 : 255; accum_ydelta = (accum_ydelta < 0) ? -256 : 255;
} }
buffer[0] = 0xB; buffer[0] = 0xB;
buffer[1] = 0xF; buffer[1] = 0xF;
buffer[2] = 0xF; buffer[2] = 0xF;
buffer[3] = flags; buffer[3] = flags;
buffer[4] = buttons; buffer[4] = buttons;
buffer[5] = (accum_xdelta >> 4) & 0xF; buffer[5] = (accum_xdelta >> 4) & 0xF;
buffer[6] = (accum_xdelta >> 0) & 0xF; buffer[6] = (accum_xdelta >> 0) & 0xF;
buffer[7] = (accum_ydelta >> 4) & 0xF; buffer[7] = (accum_ydelta >> 4) & 0xF;
buffer[8] = (accum_ydelta >> 0) & 0xF; buffer[8] = (accum_ydelta >> 0) & 0xF;
for(int i = 9; i < 16; i++) for(int i = 9; i < 16; i++)
buffer[i] = buffer[8]; buffer[i] = buffer[8];
phase++; phase++;
} }
if((bool)(smpc_out & 0x20) != tl) if((bool)(smpc_out & 0x20) != tl)
{ {
phase = (phase + 1) & 0xF; phase = (phase + 1) & 0xF;
tl = !tl; tl = !tl;
if(phase == 8) if(phase == 8)
accum_xdelta = accum_ydelta = 0; accum_xdelta = accum_ydelta = 0;
} }
data_out = buffer[phase]; data_out = buffer[phase];
} }
tmp = (tl << 4) | data_out; tmp = (tl << 4) | data_out;
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted); return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
} }
IDIISG IODevice_Mouse_IDII = IDIISG IODevice_Mouse_IDII =
{ {
{ "x_axis", "X Axis", -1, IDIT_X_AXIS_REL }, { "x_axis", "X Axis", -1, IDIT_X_AXIS_REL },
{ "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL }, { "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL },
{ "left", "Left Button", 0, IDIT_BUTTON }, { "left", "Left Button", 0, IDIT_BUTTON },
{ "right", "Right Button", 2, IDIT_BUTTON }, { "right", "Right Button", 2, IDIT_BUTTON },
{ "middle", "Middle Button", 1, IDIT_BUTTON }, { "middle", "Middle Button", 1, IDIT_BUTTON },
{ "start", "Start", 3, IDIT_BUTTON }, { "start", "Start", 3, IDIT_BUTTON },
}; };
} }

View File

@ -1,141 +1,134 @@
/******************************************************************************/ /******************************************************************************/
/* Mednafen Sega Saturn Emulation Module */ /* Mednafen Sega Saturn Emulation Module */
/******************************************************************************/ /******************************************************************************/
/* wheel.cpp: /* wheel.cpp:
** Copyright (C) 2017 Mednafen Team ** Copyright (C) 2017 Mednafen Team
** **
** This program is free software; you can redistribute it and/or ** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License ** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2 ** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version. ** of the License, or (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation, Inc., ** along with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "common.h" #include "common.h"
#include "wheel.h" #include "wheel.h"
namespace MDFN_IEN_SS namespace MDFN_IEN_SS
{ {
IODevice_Wheel::IODevice_Wheel() : dbuttons(0) IODevice_Wheel::IODevice_Wheel() : dbuttons(0)
{ {
} }
IODevice_Wheel::~IODevice_Wheel() IODevice_Wheel::~IODevice_Wheel()
{ {
} }
void IODevice_Wheel::Power(void) void IODevice_Wheel::Power(void)
{ {
phase = -1; phase = -1;
tl = true; tl = true;
data_out = 0x01; data_out = 0x01;
} }
void IODevice_Wheel::UpdateInput(const uint8* data, const int32 time_elapsed) void IODevice_Wheel::UpdateInput(const uint8 *data, const int32 time_elapsed)
{ {
dbuttons = (dbuttons & 0xC) | (MDFN_de16lsb(&data[0]) & 0x07F3); dbuttons = (dbuttons & 0xC) | (MDFN_de16lsb(&data[0]) & 0x07F3);
wheel = data[2];
// if (wheel >= 0x6F)
{ dbuttons &= ~0x4;
int32 tmp = 32767 + MDFN_de16lsb(&data[0x2 + 2]) - MDFN_de16lsb(&data[0x2 + 0]); else if (wheel <= 0x67)
dbuttons |= 0x4;
wheel = 1 + tmp * 253 / 65534;
if (wheel <= 0x8F)
if(wheel >= 0x6F) dbuttons &= ~0x8;
dbuttons &= ~0x4; else if (wheel >= 0x97)
else if(wheel <= 0x67) dbuttons |= 0x8;
dbuttons |= 0x4; }
if(wheel <= 0x8F) uint8 IODevice_Wheel::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted)
dbuttons &= ~0x8; {
else if(wheel >= 0x97) uint8 tmp;
dbuttons |= 0x8;
} if(smpc_out & 0x40)
} {
phase = -1;
uint8 IODevice_Wheel::UpdateBus(const uint8 smpc_out, const uint8 smpc_out_asserted) tl = true;
{ data_out = 0x01;
uint8 tmp; }
else
if(smpc_out & 0x40) {
{ if((bool)(smpc_out & 0x20) != tl)
phase = -1; {
tl = true; if(phase < 0)
data_out = 0x01; {
} buffer[ 0] = 0x1;
else buffer[ 1] = 0x3;
{ buffer[ 2] = (((dbuttons >> 0) & 0xF) ^ 0xF);
if((bool)(smpc_out & 0x20) != tl) buffer[ 3] = (((dbuttons >> 4) & 0xF) ^ 0xF);
{ buffer[ 4] = (((dbuttons >> 8) & 0xF) ^ 0xF);
if(phase < 0) buffer[ 5] = (((dbuttons >> 12) & 0xF) ^ 0xF);
{ buffer[ 6] = ((wheel >> 4) & 0xF);
buffer[ 0] = 0x1; buffer[ 7] = ((wheel >> 0) & 0xF);
buffer[ 1] = 0x3; buffer[ 8] = 0x0;
buffer[ 2] = (((dbuttons >> 0) & 0xF) ^ 0xF); buffer[ 9] = 0x1;
buffer[ 3] = (((dbuttons >> 4) & 0xF) ^ 0xF); buffer[10] = 0x1;
buffer[ 4] = (((dbuttons >> 8) & 0xF) ^ 0xF); buffer[11] = ((wheel >> 0) & 0xF);
buffer[ 5] = (((dbuttons >> 12) & 0xF) ^ 0xF); buffer[12] = 0x0;
buffer[ 6] = ((wheel >> 4) & 0xF); buffer[13] = 0x1;
buffer[ 7] = ((wheel >> 0) & 0xF); buffer[14] = 0x1;
buffer[ 8] = 0x0; buffer[15] = 0x1;
buffer[ 9] = 0x1; }
buffer[10] = 0x1;
buffer[11] = ((wheel >> 0) & 0xF); phase = (phase + 1) & 0xF;
buffer[12] = 0x0; data_out = buffer[phase];
buffer[13] = 0x1; tl = !tl;
buffer[14] = 0x1; }
buffer[15] = 0x1; }
}
tmp = (tl << 4) | data_out;
phase = (phase + 1) & 0xF;
data_out = buffer[phase]; return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted);
tl = !tl; }
}
} IDIISG IODevice_Wheel_IDII =
{
tmp = (tl << 4) | data_out; { "up", "L Gear Shift(Equiv. UP ↑)", 2, IDIT_BUTTON, "down" },
{ "down", "R Gear Shift(Equiv. DOWN ↓)", 3, IDIT_BUTTON, "up" },
return (smpc_out & (smpc_out_asserted | 0xE0)) | (tmp &~ smpc_out_asserted); { NULL, "empty", 0, IDIT_BUTTON }, // left
} { NULL, "empty", 0, IDIT_BUTTON }, // right
IDIISG IODevice_Wheel_IDII = { "b", "B (R Group)", 9, IDIT_BUTTON },
{ { "c", "C (R Group)", 10, IDIT_BUTTON },
{ "up", "L Gear Shift(Equiv. UP ↑)", 2, IDIT_BUTTON, "down" }, { "a", "A (R Group)", 8, IDIT_BUTTON },
{ "down", "R Gear Shift(Equiv. DOWN ↓)", 3, IDIT_BUTTON, "up" }, { "start", "START", 7, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, // left
{ NULL, "empty", 0, IDIT_BUTTON }, // right { "z", "Z (L Group)", 4, IDIT_BUTTON },
{ "y", "Y (L Group)", 5, IDIT_BUTTON },
{ "b", "B (R Group)", 9, IDIT_BUTTON }, { "x", "X (L Group)", 6, IDIT_BUTTON },
{ "c", "C (R Group)", 10, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ "a", "A (R Group)", 8, IDIT_BUTTON },
{ "start", "START", 7, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
{ "z", "Z (L Group)", 4, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ "y", "Y (L Group)", 5, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON },
{ "x", "X (L Group)", 6, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON }, { "analog_left", "Analog LEFT ←", 0, IDIT_BUTTON_ANALOG },
{ "analog_right", "Analog RIGHT →", 1, IDIT_BUTTON_ANALOG },
{ NULL, "empty", 0, IDIT_BUTTON }, };
{ NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
{ NULL, "empty", 0, IDIT_BUTTON },
{ "analog_left", "Analog LEFT ←", 0, IDIT_BUTTON_ANALOG }, }
{ "analog_right", "Analog RIGHT →", 1, IDIT_BUTTON_ANALOG },
};
}