mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 15:19:53 -06:00
Slot-2 Motion Pak, Guitar Grip emulation (#2183)
* Add DS Motion Pak emulation * Add retail Motion Pak emulation, Guitar Grip emulation * Simplify Motion Pak acceleration conversion formula * Fix Motion Pak emulation axes * Motion Pak: Emulate console laying on a flat table when motion input is not detected * Motion Pak: Add comment * GBACartMotionPak: Update comment
This commit is contained in:

committed by
GitHub

parent
2d04222442
commit
fd74181f7d
@ -169,6 +169,10 @@ LegacyEntry LegacyFile[] =
|
||||
{"HKKey_PowerButton", 0, "Keyboard.HK_PowerButton", true},
|
||||
{"HKKey_VolumeUp", 0, "Keyboard.HK_VolumeUp", true},
|
||||
{"HKKey_VolumeDown", 0, "Keyboard.HK_VolumeDown", true},
|
||||
{"HKKey_GuitarGripGreen", 0, "Keyboard.HK_GuitarGripGreen", true},
|
||||
{"HKKey_GuitarGripRed", 0, "Keyboard.HK_GuitarGripRed", true},
|
||||
{"HKKey_GuitarGripYellow", 0, "Keyboard.HK_GuitarGripYellow", true},
|
||||
{"HKKey_GuitarGripBlue", 0, "Keyboard.HK_GuitarGripBlue", true},
|
||||
|
||||
{"HKJoy_Lid", 0, "Joystick.HK_Lid", true},
|
||||
{"HKJoy_Mic", 0, "Joystick.HK_Mic", true},
|
||||
@ -185,6 +189,10 @@ LegacyEntry LegacyFile[] =
|
||||
{"HKJoy_PowerButton", 0, "Joystick.HK_PowerButton", true},
|
||||
{"HKJoy_VolumeUp", 0, "Joystick.HK_VolumeUp", true},
|
||||
{"HKJoy_VolumeDown", 0, "Joystick.HK_VolumeDown", true},
|
||||
{"HKJoy_GuitarGripGreen", 0, "Joystick.HK_GuitarGripGreen", true},
|
||||
{"HKJoy_GuitarGripRed", 0, "Joystick.HK_GuitarGripRed", true},
|
||||
{"HKJoy_GuitarGripYellow", 0, "Joystick.HK_GuitarGripYellow", true},
|
||||
{"HKJoy_GuitarGripBlue", 0, "Joystick.HK_GuitarGripBlue", true},
|
||||
|
||||
{"JoystickID", 0, "JoystickID", true},
|
||||
|
||||
|
@ -2155,6 +2155,12 @@ QString EmuInstance::gbaAddonName(int addon)
|
||||
return "Solar Sensor (Boktai 2)";
|
||||
case GBAAddon_SolarSensorBoktai3:
|
||||
return "Solar Sensor (Boktai 3)";
|
||||
case GBAAddon_MotionPakHomebrew:
|
||||
return "Motion Pak (Homebrew)";
|
||||
case GBAAddon_MotionPakRetail:
|
||||
return "Motion Pack (Retail)";
|
||||
case GBAAddon_GuitarGrip:
|
||||
return "Guitar Grip";
|
||||
}
|
||||
|
||||
return "???";
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "main.h"
|
||||
#include "NDS.h"
|
||||
#include "EmuThread.h"
|
||||
@ -50,6 +51,10 @@ enum
|
||||
HK_SlowMo,
|
||||
HK_FastForwardToggle,
|
||||
HK_SlowMoToggle,
|
||||
HK_GuitarGripGreen,
|
||||
HK_GuitarGripRed,
|
||||
HK_GuitarGripYellow,
|
||||
HK_GuitarGripBlue,
|
||||
HK_MAX
|
||||
};
|
||||
|
||||
@ -143,6 +148,9 @@ public:
|
||||
void inputRumbleStart(melonDS::u32 len_ms);
|
||||
void inputRumbleStop();
|
||||
|
||||
bool inputHotkeyDown(int id) { return hotkeyDown(id); }
|
||||
float inputMotionQuery(melonDS::Platform::MotionQueryType type);
|
||||
|
||||
void setJoystick(int id);
|
||||
int getJoystickID() { return joystickID; }
|
||||
SDL_Joystick* getJoystick() { return joystick; }
|
||||
@ -332,6 +340,8 @@ private:
|
||||
int joystickID;
|
||||
SDL_Joystick* joystick;
|
||||
SDL_GameController* controller;
|
||||
bool hasAccelerometer = false;
|
||||
bool hasGyroscope = false;
|
||||
bool hasRumble = false;
|
||||
bool isRumbling = false;
|
||||
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <QKeyEvent>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "Platform.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "SDL_sensor.h"
|
||||
#include "main.h"
|
||||
#include "Config.h"
|
||||
|
||||
@ -59,7 +62,11 @@ const char* EmuInstance::hotkeyNames[HK_MAX] =
|
||||
"HK_VolumeDown",
|
||||
"HK_SlowMo",
|
||||
"HK_FastForwardToggle",
|
||||
"HK_SlowMoToggle"
|
||||
"HK_SlowMoToggle",
|
||||
"HK_GuitarGripGreen",
|
||||
"HK_GuitarGripRed",
|
||||
"HK_GuitarGripYellow",
|
||||
"HK_GuitarGripBlue"
|
||||
};
|
||||
|
||||
|
||||
@ -81,6 +88,8 @@ void EmuInstance::inputInit()
|
||||
joystick = nullptr;
|
||||
controller = nullptr;
|
||||
hasRumble = false;
|
||||
hasAccelerometer = false;
|
||||
hasGyroscope = false;
|
||||
isRumbling = false;
|
||||
inputLoadConfig();
|
||||
}
|
||||
@ -128,6 +137,48 @@ void EmuInstance::inputRumbleStop()
|
||||
}
|
||||
}
|
||||
|
||||
float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
||||
{
|
||||
float values[3];
|
||||
if (type <= melonDS::Platform::MotionAccelerationZ)
|
||||
{
|
||||
if (controller && hasAccelerometer)
|
||||
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_ACCEL, values, 3) == 0)
|
||||
{
|
||||
// Map values from DS console orientation to SDL controller orientation.
|
||||
switch (type)
|
||||
{
|
||||
case melonDS::Platform::MotionAccelerationX:
|
||||
return values[0];
|
||||
case melonDS::Platform::MotionAccelerationY:
|
||||
return -values[2];
|
||||
case melonDS::Platform::MotionAccelerationZ:
|
||||
return values[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type <= melonDS::Platform::MotionRotationZ)
|
||||
{
|
||||
if (controller && hasGyroscope)
|
||||
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_GYRO, values, 3) == 0)
|
||||
{
|
||||
// Map values from DS console orientation to SDL controller orientation.
|
||||
switch (type)
|
||||
{
|
||||
case melonDS::Platform::MotionRotationX:
|
||||
return values[0];
|
||||
case melonDS::Platform::MotionRotationY:
|
||||
return -values[2];
|
||||
case melonDS::Platform::MotionRotationZ:
|
||||
return values[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == melonDS::Platform::MotionAccelerationZ)
|
||||
return SDL_STANDARD_GRAVITY;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
void EmuInstance::setJoystick(int id)
|
||||
{
|
||||
@ -147,6 +198,8 @@ void EmuInstance::openJoystick()
|
||||
controller = nullptr;
|
||||
joystick = nullptr;
|
||||
hasRumble = false;
|
||||
hasAccelerometer = false;
|
||||
hasGyroscope = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -163,9 +216,17 @@ void EmuInstance::openJoystick()
|
||||
if (controller)
|
||||
{
|
||||
if (SDL_GameControllerHasRumble(controller))
|
||||
{
|
||||
{
|
||||
hasRumble = true;
|
||||
}
|
||||
}
|
||||
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL))
|
||||
{
|
||||
hasAccelerometer = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE) == 0;
|
||||
}
|
||||
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO))
|
||||
{
|
||||
hasGyroscope = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,8 +237,9 @@ void EmuInstance::closeJoystick()
|
||||
SDL_GameControllerClose(controller);
|
||||
controller = nullptr;
|
||||
hasRumble = false;
|
||||
hasAccelerometer = false;
|
||||
hasGyroscope = false;
|
||||
}
|
||||
|
||||
if (joystick)
|
||||
{
|
||||
SDL_JoystickClose(joystick);
|
||||
|
@ -32,12 +32,20 @@ static constexpr std::initializer_list<int> hk_addons =
|
||||
{
|
||||
HK_SolarSensorIncrease,
|
||||
HK_SolarSensorDecrease,
|
||||
HK_GuitarGripGreen,
|
||||
HK_GuitarGripRed,
|
||||
HK_GuitarGripYellow,
|
||||
HK_GuitarGripBlue,
|
||||
};
|
||||
|
||||
static constexpr std::initializer_list<const char*> hk_addons_labels =
|
||||
{
|
||||
"[Boktai] Sunlight + ",
|
||||
"[Boktai] Sunlight - ",
|
||||
"[Guitar Grip] Green",
|
||||
"[Guitar Grip] Red",
|
||||
"[Guitar Grip] Yellow",
|
||||
"[Guitar Grip] Blue",
|
||||
};
|
||||
|
||||
static_assert(hk_addons.size() == hk_addons_labels.size());
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "Platform.h"
|
||||
#include "Config.h"
|
||||
#include "EmuInstance.h"
|
||||
#include "main.h"
|
||||
#include "CameraManager.h"
|
||||
#include "Net.h"
|
||||
@ -549,6 +550,18 @@ void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv, v
|
||||
return camManager[num]->captureFrame(frame, width, height, yuv);
|
||||
}
|
||||
|
||||
static const int hotkeyMap[] = {
|
||||
HK_GuitarGripGreen,
|
||||
HK_GuitarGripRed,
|
||||
HK_GuitarGripYellow,
|
||||
HK_GuitarGripBlue,
|
||||
};
|
||||
|
||||
bool Addon_KeyDown(KeyType type, void* userdata)
|
||||
{
|
||||
return ((EmuInstance*)userdata)->inputHotkeyDown(hotkeyMap[type]);
|
||||
}
|
||||
|
||||
void Addon_RumbleStart(u32 len, void* userdata)
|
||||
{
|
||||
((EmuInstance*)userdata)->inputRumbleStart(len);
|
||||
@ -559,6 +572,11 @@ void Addon_RumbleStop(void* userdata)
|
||||
((EmuInstance*)userdata)->inputRumbleStop();
|
||||
}
|
||||
|
||||
float Addon_MotionQuery(MotionQueryType type, void* userdata)
|
||||
{
|
||||
return ((EmuInstance*)userdata)->inputMotionQuery(type);
|
||||
}
|
||||
|
||||
DynamicLibrary* DynamicLibrary_Load(const char* lib)
|
||||
{
|
||||
return (DynamicLibrary*) SDL_LoadObject(lib);
|
||||
|
@ -16,6 +16,7 @@
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "NDS.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
@ -320,7 +321,18 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
|
||||
QMenu * submenu = menu->addMenu("Insert add-on cart");
|
||||
QAction *act;
|
||||
|
||||
int addons[] = {GBAAddon_RAMExpansion, GBAAddon_RumblePak, GBAAddon_SolarSensorBoktai1, GBAAddon_SolarSensorBoktai2, GBAAddon_SolarSensorBoktai3, -1};
|
||||
int addons[] = {
|
||||
GBAAddon_RAMExpansion,
|
||||
GBAAddon_RumblePak,
|
||||
GBAAddon_SolarSensorBoktai1,
|
||||
GBAAddon_SolarSensorBoktai2,
|
||||
GBAAddon_SolarSensorBoktai3,
|
||||
GBAAddon_MotionPakHomebrew,
|
||||
GBAAddon_MotionPakRetail,
|
||||
GBAAddon_GuitarGrip,
|
||||
-1
|
||||
};
|
||||
|
||||
for (int i = 0; addons[i] != -1; i++)
|
||||
{
|
||||
int addon = addons[i];
|
||||
|
@ -309,6 +309,10 @@ int main(int argc, char** argv)
|
||||
{
|
||||
printf("SDL couldn't init joystick\n");
|
||||
}
|
||||
if (SDL_Init(SDL_INIT_SENSOR) < 0)
|
||||
{
|
||||
printf("SDL couldn't init motion sensors\n");
|
||||
}
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
const char* err = SDL_GetError();
|
||||
|
Reference in New Issue
Block a user