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_DenshaDeGoController:
case MDT_Dreameye: case MDT_Dreameye:
mcfg_Create(config::MapleMainDevices[bus], bus, 5); mcfg_Create(config::MapleMainDevices[bus], bus, 5);
if (config::MapleMainDevices[bus] == MDT_FishingController)
// integrated vibration pack
mcfg_Create(MDT_PurupuruPack, bus, 4);
break; break;
case MDT_LightGun: 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 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_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT); mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xF901; // mask off DPad2, C, D and Z; 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) if (index == 2 || index == 3)
{ {
@ -164,26 +165,11 @@ struct maple_sega_controller: maple_base
//state data //state data
//2 key code //2 key code
w16(transform_kcode(pjs.kcode)); w16(getButtonState(pjs));
//triggers // analog axes
//1 R for (int axis = 0; axis < 6; axis++)
w8(get_analog_axis(0, pjs)); w8(getAnalogAxis(axis, 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; 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 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_UP_KEY | AWAVE_DOWN_KEY);
mutualExclusion(kcode, AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY); mutualExclusion(kcode, AWAVE_LEFT_KEY | AWAVE_RIGHT_KEY);
return kcode | AWAVE_TRIGGER_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) if (index < 2 || index > 5)
return 0x80; return 0x80;
index -= 2; 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 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_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT); mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
mutualExclusion(kcode, DC_DPAD2_UP | DC_DPAD2_DOWN); mutualExclusion(kcode, DC_DPAD2_UP | DC_DPAD2_DOWN);
@ -254,7 +242,7 @@ struct maple_sega_twinstick: maple_sega_controller
return MDT_TwinStick; return MDT_TwinStick;
} }
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override { u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
return 0x80; 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 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_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT); mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xF800; return kcode | 0xF800;
@ -293,7 +282,7 @@ struct maple_ascii_stick: maple_sega_controller
return MDT_AsciiStick; return MDT_AsciiStick;
} }
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override { u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override {
return 0x80; 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 return 0x0f093c00; // 4 analog axes (2-5) A B C D Z Start
} }
u32 transform_kcode(u32 kcode) override { u16 getButtonState(const PlainJoystickState &pjs) override {
return kcode | 0xf6f0; // mask off DPad2, X, Y, DPad; return pjs.kcode | 0xf6f0; // mask off DPad2, X, Y, DPad;
} }
MapleDeviceType get_device_type() override { MapleDeviceType get_device_type() override {
return MDT_MaracasController; 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) if (index < 2 || index > 5)
return 0; return 0;
return pjs.joy[index -2]; return pjs.joy[index -2];
@ -1385,6 +1374,8 @@ struct maple_maracas_controller: maple_sega_controller
struct maple_fishing_controller: maple_sega_controller struct maple_fishing_controller: maple_sega_controller
{ {
u32 analogToDPad = ~0;
u32 get_capabilities() override { u32 get_capabilities() override {
// byte 0: 0 0 0 0 0 0 0 0 // byte 0: 0 0 0 0 0 0 0 0
// byte 1: 0 0 a5 a4 a3 a2 a1 a0 // 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 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_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT); mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xf901; // mask off DPad2, D, Z, C; return kcode | 0xf901; // mask off DPad2, D, Z, C;
@ -1404,7 +1428,8 @@ struct maple_fishing_controller: maple_sega_controller
return MDT_FishingController; 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 XYZ axes, acceleration sensor outputs 80 ± 8H (home position)
// in the static state (± 0G), F0h or greater for maximum force (+10G) // in the static state (± 0G), F0h or greater for maximum force (+10G)
// in the positive direction and 11h or less // 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 // X: Right is positive, left is negative
// Y: Down is positive, up is negative // Y: Down is positive, up is negative
// Z: Forward is positive, backward 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 return pjs.trigger[PJTI_R]; // A1: Reel handle output
else if (index == 1) case 1:
return pjs.joy[4]; // A2: acceleration sensor Z return pjs.joy[PJAI_X3]; // A2: acceleration sensor Z
else if (index >= 2 || index <= 5) // A3, A4 are also output as Ra, La, Ua, Da case 2:
return pjs.joy[index -2]; // A5, A6: acceleration sensors X and Y return pjs.joy[PJAI_X1]; // A3: analog stick X
return 0x80; 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 { 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 { u32 get_device_current(int get_max_current) override {
return get_max_current ? 0x0960 : 0x0258; // Max. 240 mA, standby: 60 mA 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 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 return 0xff060000; // no analog axes, X Y A B C Start U/D/L/R
} }
u32 transform_kcode(u32 kcode) override u16 getButtonState(const PlainJoystickState &pjs) override {
{ return pjs.kcode | 0xf100; // mask off DPad2 and Z
return kcode | 0xf100; // mask off DPad2 and Z
} }
MapleDeviceType get_device_type() override { MapleDeviceType get_device_type() override {
return MDT_PopnMusicController; 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) if (index == 0 || index == 1)
return 0; // Right and left triggers return 0; // Right and left triggers
return 0x80; return 0x80;
@ -1565,13 +1513,14 @@ struct maple_racing_controller: maple_sega_controller
//return 0xfe000700; // Steering only //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 // Ra, La are ON when A3 threshold values (La: 40h, Ra: BEh) are exceeded
u32 kcode = pjs.kcode; u32 kcode = pjs.kcode;
if (pjs.joy[PJAI_X1] < 0x40) if (pjs.joy[PJAI_X1] < 0x40)
kcode &= 0xffff -DC_DPAD_LEFT; kcode &= ~DC_DPAD_LEFT;
else if (pjs.joy[PJAI_X1] > 0xBE) 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_UP | DC_DPAD_DOWN);
mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT); mutualExclusion(kcode, DC_DPAD_LEFT | DC_DPAD_RIGHT);
return kcode | 0xff01; // mask off DPad2, D, X, Y, Z, C 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; return MDT_RacingController;
} }
u32 get_analog_axis(int index, const PlainJoystickState &pjs) override { u32 getAnalogAxis(int index, const PlainJoystickState &pjs) override
if (index == 0) {
return pjs.trigger[PJTI_R]; // A1: lever, 0 at rest switch (index)
else if (index == 1) {
return pjs.trigger[PJTI_L]; // A2: lever, 0 at rest case 0: return pjs.trigger[PJTI_R]; // A1: lever, 0 at rest
else if (index == 2) case 1: return pjs.trigger[PJTI_L]; // A2: lever, 0 at rest
return pjs.joy[PJAI_X1]; // A3: 0-0xff, 0x80 at rest case 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) // (A5 and A6 are only valid when the accelerator/brake unit is connected)
return pjs.trigger[PJTI_R2];// A5: lever, 0 at rest case 4: return pjs.trigger[PJTI_R2]; // A5: lever, 0 at rest
else if (index == 5) case 5: return pjs.trigger[PJTI_L2]; // A6: lever, 0 at rest
return pjs.trigger[PJTI_L2];// A6: lever, 0 at rest default: return 0x80; // unused
return 0x80; // unused }
} }
const char *get_device_name() override { 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 { u32 get_device_current(int get_max_current) override {
return get_max_current ? 0x0226 : 0x01B8; // Max. 55 mA, standby: 44 mA 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 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 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. // 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 { MapleDeviceType get_device_type() override {
return MDT_DenshaDeGoController; 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) if (index == 2 || index == 3)
return 0; return 0;
if (index == 0 || index == 1 || index == 4 || index == 5) if (index == 0 || index == 1 || index == 4 || index == 5)