diff --git a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp index 5b6f977aa..6195efe36 100644 --- a/core/hw/maple/maple_cfg.cpp +++ b/core/hw/maple/maple_cfg.cpp @@ -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: diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index c911202c8..4ea27b5f2 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -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)