maple: fishing controller vibration pack, analog to dpad

refactoring to avoid duplicate code
This commit is contained in:
Flyinghead 2023-05-31 17:01:54 +02:00
parent 9b8fd39d12
commit 231a1b624f
2 changed files with 98 additions and 232 deletions

View File

@ -304,6 +304,9 @@ static void createDreamcastDevices()
case MDT_DenshaDeGoController:
case MDT_Dreameye:
mcfg_Create(config::MapleMainDevices[bus], bus, 5);
if (config::MapleMainDevices[bus] == MDT_FishingController)
// integrated vibration pack
mcfg_Create(MDT_PurupuruPack, bus, 4);
break;
case MDT_LightGun:

View File

@ -66,14 +66,15 @@ struct maple_sega_controller: maple_base
return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R
}
virtual u32 transform_kcode(u32 kcode)
virtual u16 getButtonState(const PlainJoystickState &pjs)
{
u32 kcode = pjs.kcode;
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xF901; // mask off DPad2, C, D and Z;
}
virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs)
virtual u32 getAnalogAxis(int index, const PlainJoystickState &pjs)
{
if (index == 2 || index == 3)
{
@ -164,26 +165,11 @@ struct maple_sega_controller: maple_base
//state data
//2 key code
w16(transform_kcode(pjs.kcode));
w16(getButtonState(pjs));
//triggers
//1 R
w8(get_analog_axis(0, pjs));
//1 L
w8(get_analog_axis(1, pjs));
//joyx
//1
w8(get_analog_axis(2, pjs));
//joyy
//1
w8(get_analog_axis(3, pjs));
//not used on dreamcast
//1
w8(get_analog_axis(4, pjs));
//1
w8(get_analog_axis(5, pjs));
// analog axes
for (int axis = 0; axis < 6; axis++)
w8(getAnalogAxis(axis, pjs));
}
return MDRS_DataTransfer;
@ -212,14 +198,15 @@ struct maple_atomiswave_controller: maple_sega_controller
return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R
}
u32 transform_kcode(u32 kcode) override
u16 getButtonState(const PlainJoystickState &pjs) override
{
u32 kcode = pjs.kcode;
mutualExclusion(kcode, AWAVE_UP_KEY | AWAVE_DOWN_KEY);
mutualExclusion(kcode, AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY);
return kcode | AWAVE_TRIGGER_KEY;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
if (index < 2 || index > 5)
return 0x80;
index -= 2;
@ -241,8 +228,9 @@ struct maple_sega_twinstick: maple_sega_controller
return 0xfefe0000; // no analog axes, X Y A B D Start U/D/L/R U2/D2/L2/R2
}
u32 transform_kcode(u32 kcode) override
u16 getButtonState(const PlainJoystickState &pjs) override
{
u32 kcode = pjs.kcode;
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
mutualExclusion(kcode, DC_DPAD2_UP | DC_DPAD2_DOWN);
@ -254,7 +242,7 @@ struct maple_sega_twinstick: maple_sega_controller
return MDT_TwinStick;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
return 0x80;
}
@ -282,8 +270,9 @@ struct maple_ascii_stick: maple_sega_controller
return 0xff070000; // no analog axes, X Y Z A B C Start U/D/L/R
}
u32 transform_kcode(u32 kcode) override
u16 getButtonState(const PlainJoystickState &pjs) override
{
u32 kcode = pjs.kcode;
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xF800;
@ -293,7 +282,7 @@ struct maple_ascii_stick: maple_sega_controller
return MDT_AsciiStick;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
return 0x80;
}
@ -1354,15 +1343,15 @@ struct maple_maracas_controller: maple_sega_controller
return 0x0f093c00; // 4 analog axes (2-5) A B C D Z Start
}
u32 transform_kcode(u32 kcode) override {
return kcode | 0xf6f0; // mask off DPad2, X, Y, DPad;
u16 getButtonState(const PlainJoystickState &pjs) override {
return pjs.kcode | 0xf6f0; // mask off DPad2, X, Y, DPad;
}
MapleDeviceType get_device_type() override {
return MDT_MaracasController;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
if (index < 2 || index > 5)
return 0;
return pjs.joy[index -2];
@ -1385,6 +1374,8 @@ struct maple_maracas_controller: maple_sega_controller
struct maple_fishing_controller: maple_sega_controller
{
u32 analogToDPad = ~0;
u32 get_capabilities() override {
// byte 0: 0 0 0 0 0 0 0 0
// byte 1: 0 0 a5 a4 a3 a2 a1 a0
@ -1394,7 +1385,40 @@ struct maple_fishing_controller: maple_sega_controller
return 0x0fe063f00; // Ra,La,Da,Ua,A,B,X,Y,Start,A1,A2,A3,A4,A5,A6
}
u32 transform_kcode(u32 kcode) override {
u16 getButtonState(const PlainJoystickState &pjs) override
{
// Analog to DPad handling
if (pjs.joy[PJAI_X1] < 0x30) {
analogToDPad &= ~DC_DPAD_LEFT;
analogToDPad |= DC_DPAD_RIGHT;
}
else if (pjs.joy[PJAI_X1] > 0xd0) {
analogToDPad &= ~DC_DPAD_RIGHT;
analogToDPad |= DC_DPAD_LEFT;
}
else
{
if (pjs.joy[PJAI_X1] >= 0x40)
analogToDPad |= DC_DPAD_LEFT;
if (pjs.joy[PJAI_X1] <= 0xc0)
analogToDPad |= DC_DPAD_RIGHT;
}
if (pjs.joy[PJAI_Y1] < 0x30) {
analogToDPad &= ~DC_DPAD_UP;
analogToDPad |= DC_DPAD_DOWN;
}
else if (pjs.joy[PJAI_Y1] > 0xd0) {
analogToDPad &= ~DC_DPAD_DOWN;
analogToDPad |= DC_DPAD_UP;
}
else
{
if (pjs.joy[PJAI_Y1] >= 0x40)
analogToDPad |= DC_DPAD_UP;
if (pjs.joy[PJAI_Y1] <= 0xc0)
analogToDPad |= DC_DPAD_DOWN;
}
u32 kcode = pjs.kcode & analogToDPad;
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xf901; // mask off DPad2, D, Z, C;
@ -1404,7 +1428,8 @@ struct maple_fishing_controller: maple_sega_controller
return MDT_FishingController;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override
{
// In the XYZ axes, acceleration sensor outputs 80 ± 8H (home position)
// in the static state (± 0G), F0h or greater for maximum force (+10G)
// in the positive direction and 11h or less
@ -1413,13 +1438,23 @@ struct maple_fishing_controller: maple_sega_controller
// X: Right is positive, left is negative
// Y: Down is positive, up is negative
// Z: Forward is positive, backward is negative
if (index == 0)
switch (index)
{
case 0:
return pjs.trigger[PJTI_R]; // A1: Reel handle output
else if (index == 1)
return pjs.joy[4]; // A2: acceleration sensor Z
else if (index >= 2 || index <= 5) // A3, A4 are also output as Ra, La, Ua, Da
return pjs.joy[index -2]; // A5, A6: acceleration sensors X and Y
return 0x80;
case 1:
return pjs.joy[PJAI_X3]; // A2: acceleration sensor Z
case 2:
return pjs.joy[PJAI_X1]; // A3: analog stick X
case 3:
return pjs.joy[PJAI_Y1]; // A4: analog stick Y
case 4:
return pjs.joy[PJAI_X2]; // A5: acceleration sensor X
case 5:
return pjs.joy[PJAI_Y2]; // A6: acceleration sensor Y
default:
return 0x80;
}
}
const char *get_device_name() override {
@ -1429,92 +1464,6 @@ struct maple_fishing_controller: maple_sega_controller
u32 get_device_current(int get_max_current) override {
return get_max_current ? 0x0960 : 0x0258; // Max. 240 mA, standby: 60 mA
}
u32 dma(u32 cmd) override {
//printf("maple_fishing_controller::dma Called 0x%X;Command %d\n", bus_id, cmd);
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
// Fixed Device Status
// (Device ID)
//caps
//4
w32(MFID_0_Input);
//struct data
//3*4
w32(get_capabilities());
w32(0);
w32(0);
//1 area code (Country specification)
w8(0xFF);
//1 direction (Connection method)
w8(0);
//30 (Model name)
wstr(get_device_name(), 30);
//60 (License)
wstr(get_device_brand(), 60);
//2 (Standby current consumption)
w16(get_device_current(0));
//2 (Maximum current consumption)
w16(get_device_current(1));
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
//controller condition
case MDCF_GetCondition:
{
PlainJoystickState pjs;
config->GetInput(&pjs);
//INFO_LOG(MAPLE, "maple_fishing_controller: MDCF_GetCondition: r32(): %d", r32());
//caps
//4
w32(MFID_0_Input);
//state data
//2 key code
w16(transform_kcode(pjs.kcode));
//triggers
//1 R
w8(get_analog_axis(0, pjs));
//1 L
w8(get_analog_axis(1, pjs));
//joyx
//1
w8(get_analog_axis(2, pjs));
//joyy
//1
w8(get_analog_axis(3, pjs));
//not used on dreamcast
//1
w8(get_analog_axis(4, pjs));
//1
w8(get_analog_axis(5, pjs));
}
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "maple_fishing_controller: Unknown maple command %d", cmd);
return MDRE_UnknownCmd;
}
}
};
struct maple_popnmusic_controller: maple_sega_controller
@ -1528,16 +1477,15 @@ struct maple_popnmusic_controller: maple_sega_controller
return 0xff060000; // no analog axes, X Y A B C Start U/D/L/R
}
u32 transform_kcode(u32 kcode) override
{
return kcode | 0xf100; // mask off DPad2 and Z
u16 getButtonState(const PlainJoystickState &pjs) override {
return pjs.kcode | 0xf100; // mask off DPad2 and Z
}
MapleDeviceType get_device_type() override {
return MDT_PopnMusicController;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
if (index == 0 || index == 1)
return 0; // Right and left triggers
return 0x80;
@ -1565,13 +1513,14 @@ struct maple_racing_controller: maple_sega_controller
//return 0xfe000700; // Steering only
}
u32 transform_kcode_racing(const PlainJoystickState &pjs) {
u16 getButtonState(const PlainJoystickState &pjs) override
{
// Ra, La are ON when A3 threshold values (La: 40h, Ra: BEh) are exceeded
u32 kcode = pjs.kcode;
if (pjs.joy[PJAI_X1] < 0x40)
kcode &= 0xffff -DC_DPAD_LEFT;
kcode &= ~DC_DPAD_LEFT;
else if (pjs.joy[PJAI_X1] > 0xBE)
kcode &= 0xffff -DC_DPAD_RIGHT;
kcode &= ~DC_DPAD_RIGHT;
mutualExclusion(kcode, DC_DPAD_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xff01; // mask off DPad2, D, X, Y, Z, C
@ -1581,18 +1530,18 @@ struct maple_racing_controller: maple_sega_controller
return MDT_RacingController;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
if (index == 0)
return pjs.trigger[PJTI_R]; // A1: lever, 0 at rest
else if (index == 1)
return pjs.trigger[PJTI_L]; // A2: lever, 0 at rest
else if (index == 2)
return pjs.joy[PJAI_X1]; // A3: 0-0xff, 0x80 at rest
else if (index == 4) // (A5 and A6 are only valid when the accelerator/brake unit is connected)
return pjs.trigger[PJTI_R2];// A5: lever, 0 at rest
else if (index == 5)
return pjs.trigger[PJTI_L2];// A6: lever, 0 at rest
return 0x80; // unused
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override
{
switch (index)
{
case 0: return pjs.trigger[PJTI_R]; // A1: lever, 0 at rest
case 1: return pjs.trigger[PJTI_L]; // A2: lever, 0 at rest
case 2: return pjs.joy[PJAI_X1]; // A3: 0-0xff, 0x80 at rest
// (A5 and A6 are only valid when the accelerator/brake unit is connected)
case 4: return pjs.trigger[PJTI_R2]; // A5: lever, 0 at rest
case 5: return pjs.trigger[PJTI_L2]; // A6: lever, 0 at rest
default: return 0x80; // unused
}
}
const char *get_device_name() override {
@ -1602,92 +1551,6 @@ struct maple_racing_controller: maple_sega_controller
u32 get_device_current(int get_max_current) override {
return get_max_current ? 0x0226 : 0x01B8; // Max. 55 mA, standby: 44 mA
}
u32 dma(u32 cmd) override
{
//printf("maple_sega_controller::dma Called 0x%X;Command %d\n", bus_id, cmd);
switch (cmd)
{
case MDC_DeviceRequest:
case MDC_AllStatusReq:
// Fixed Device Status
// (Device ID)
//caps
//4
w32(MFID_0_Input);
//struct data
//3*4
w32(get_capabilities());
w32(0);
w32(0);
//1 area code (Country specification)
w8(0xFF);
//1 direction (Connection method)
w8(0);
//30 (Model name)
wstr(get_device_name(), 30);
//60 (License)
wstr(get_device_brand(), 60);
//2 (Standby current consumption)
w16(get_device_current(0));
//2 (Maximum current consumption)
w16(get_device_current(1));
return cmd == MDC_DeviceRequest ? MDRS_DeviceStatus : MDRS_DeviceStatusAll;
//controller condition
case MDCF_GetCondition:
{
PlainJoystickState pjs;
config->GetInput(&pjs);
//caps
//4
w32(MFID_0_Input);
//state data
//2 key code
w16(transform_kcode_racing(pjs));
//triggers
//1 R
w8(get_analog_axis(0, pjs));
//1 L
w8(get_analog_axis(1, pjs));
//joyx
//1
w8(get_analog_axis(2, pjs));
//joyy
//1
w8(get_analog_axis(3, pjs));
//not used on dreamcast
//1
w8(get_analog_axis(4, pjs));
//1
w8(get_analog_axis(5, pjs));
}
return MDRS_DataTransfer;
case MDC_DeviceReset:
return MDRS_DeviceReply;
case MDC_DeviceKill:
return MDRS_DeviceReply;
default:
INFO_LOG(MAPLE, "maple_racing_controller: Unknown maple command %d", cmd);
return MDRE_UnknownCmd;
}
}
};
struct maple_densha_controller: maple_sega_controller
@ -1701,16 +1564,16 @@ struct maple_densha_controller: maple_sega_controller
return 0xff0f3f00; // Ra,La,Da,Ua A,B,C,D,X,Y,Z,Start Xa,Ya,Xb,Yb Analog levers R,L
}
u32 transform_kcode(u32 kcode) override {
u16 getButtonState(const PlainJoystickState &pjs) override {
// Ra,La,Da,Ua are used together, corresponding to the brake lever.
return kcode | 0xF000; // mask off DPad2
return pjs.kcode | 0xF000; // mask off DPad2
}
MapleDeviceType get_device_type() override {
return MDT_DenshaDeGoController;
}
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override {
u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
if (index == 2 || index == 3)
return 0;
if (index == 0 || index == 1 || index == 4 || index == 5)