mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
Add retail Motion Pak emulation, Guitar Grip emulation
This commit is contained in:
parent
3ccfc262e4
commit
593642ff57
@ -724,6 +724,27 @@ void CartRumblePak::ROMWrite(u32 addr, u16 val)
|
||||
}
|
||||
}
|
||||
|
||||
CartGuitarGrip::CartGuitarGrip(void* userdata) :
|
||||
CartCommon(GuitarGrip),
|
||||
UserData(userdata)
|
||||
{
|
||||
}
|
||||
|
||||
CartGuitarGrip::~CartGuitarGrip() = default;
|
||||
|
||||
u16 CartGuitarGrip::ROMRead(u32 addr) const
|
||||
{
|
||||
return 0xF9FF;
|
||||
}
|
||||
|
||||
u8 CartGuitarGrip::SRAMRead(u32 addr)
|
||||
{
|
||||
return ~((Platform::Addon_KeyDown(Platform::KeyGuitarGripGreen, UserData) ? 0x40 : 0)
|
||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripRed, UserData) ? 0x20 : 0)
|
||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripYellow, UserData) ? 0x10 : 0)
|
||||
| (Platform::Addon_KeyDown(Platform::KeyGuitarGripBlue, UserData) ? 0x08 : 0));
|
||||
}
|
||||
|
||||
GBACartSlot::GBACartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& cart) noexcept : NDS(nds), Cart(std::move(cart))
|
||||
{
|
||||
}
|
||||
@ -874,8 +895,14 @@ void GBACartSlot::LoadAddon(void* userdata, int type) noexcept
|
||||
case GBAAddon_RumblePak:
|
||||
Cart = std::make_unique<CartRumblePak>(userdata);
|
||||
break;
|
||||
case GBAAddon_MotionPak:
|
||||
Cart = std::make_unique<CartMotionPak>(userdata);
|
||||
case GBAAddon_MotionPakHomebrew:
|
||||
Cart = std::make_unique<CartMotionPakHomebrew>(userdata);
|
||||
break;
|
||||
case GBAAddon_MotionPakRetail:
|
||||
Cart = std::make_unique<CartMotionPakRetail>(userdata);
|
||||
break;
|
||||
case GBAAddon_GuitarGrip:
|
||||
Cart = std::make_unique<CartGuitarGrip>(userdata);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -33,7 +33,9 @@ enum CartType
|
||||
GameSolarSensor = 0x102,
|
||||
RAMExpansion = 0x201,
|
||||
RumblePak = 0x202,
|
||||
MotionPak = 0x203,
|
||||
MotionPakHomebrew = 0x203,
|
||||
MotionPakRetail = 0x204,
|
||||
GuitarGrip = 0x205,
|
||||
};
|
||||
|
||||
// CartCommon -- base code shared by all cart types
|
||||
@ -212,12 +214,26 @@ private:
|
||||
u16 RumbleState = 0;
|
||||
};
|
||||
|
||||
// CartMotionPak -- DS Motion Pak (Kionix/homebrew)
|
||||
class CartMotionPak : public CartCommon
|
||||
// CartGuitarGrip -- DS Guitar Grip (used in various NDS games)
|
||||
class CartGuitarGrip : public CartCommon
|
||||
{
|
||||
public:
|
||||
CartMotionPak(void* userdata);
|
||||
~CartMotionPak() override;
|
||||
CartGuitarGrip(void* userdata);
|
||||
~CartGuitarGrip() override;
|
||||
|
||||
u16 ROMRead(u32 addr) const override;
|
||||
u8 SRAMRead(u32 addr) override;
|
||||
|
||||
private:
|
||||
void* UserData;
|
||||
};
|
||||
|
||||
// CartMotionPakHomebrew -- DS Motion Pak (Homebrew)
|
||||
class CartMotionPakHomebrew : public CartCommon
|
||||
{
|
||||
public:
|
||||
CartMotionPakHomebrew(void* userdata);
|
||||
~CartMotionPakHomebrew() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
@ -231,11 +247,35 @@ private:
|
||||
u16 ShiftVal = 0;
|
||||
};
|
||||
|
||||
// CartMotionPakRetail -- DS Motion Pack (Retail)
|
||||
class CartMotionPakRetail : public CartCommon
|
||||
{
|
||||
public:
|
||||
CartMotionPakRetail(void* userdata);
|
||||
~CartMotionPakRetail() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
u16 ROMRead(u32 addr) const override;
|
||||
u8 SRAMRead(u32 addr) override;
|
||||
|
||||
private:
|
||||
void* UserData;
|
||||
u8 Value;
|
||||
u8 Step = 16;
|
||||
};
|
||||
|
||||
// possible inputs for GBA carts that might accept user input
|
||||
enum
|
||||
{
|
||||
Input_SolarSensorDown = 0,
|
||||
Input_SolarSensorUp,
|
||||
Input_GuitarGripGreen,
|
||||
Input_GuitarGripRed,
|
||||
Input_GuitarGripYellow,
|
||||
Input_GuitarGripBlue,
|
||||
};
|
||||
|
||||
class GBACartSlot
|
||||
|
@ -31,28 +31,28 @@ using Platform::LogLevel;
|
||||
namespace GBACart
|
||||
{
|
||||
|
||||
CartMotionPak::CartMotionPak(void* userdata) :
|
||||
CartCommon(MotionPak),
|
||||
CartMotionPakHomebrew::CartMotionPakHomebrew(void* userdata) :
|
||||
CartCommon(MotionPakHomebrew),
|
||||
UserData(userdata)
|
||||
{
|
||||
}
|
||||
|
||||
CartMotionPak::~CartMotionPak() = default;
|
||||
CartMotionPakHomebrew::~CartMotionPakHomebrew() = default;
|
||||
|
||||
void CartMotionPak::Reset()
|
||||
void CartMotionPakHomebrew::Reset()
|
||||
{
|
||||
ShiftVal = 0;
|
||||
}
|
||||
|
||||
void CartMotionPak::DoSavestate(Savestate* file)
|
||||
void CartMotionPakHomebrew::DoSavestate(Savestate* file)
|
||||
{
|
||||
CartCommon::DoSavestate(file);
|
||||
file->Var16(&ShiftVal);
|
||||
}
|
||||
|
||||
u16 CartMotionPak::ROMRead(u32 addr) const
|
||||
u16 CartMotionPakHomebrew::ROMRead(u32 addr) const
|
||||
{
|
||||
// CHECKME: Does this apply to the Kionix/homebrew cart as well?
|
||||
// CHECKME: Does this apply to the homebrew cart as well?
|
||||
return 0xFCFF;
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ static int RotationToMotionPak(float rot)
|
||||
);
|
||||
}
|
||||
|
||||
u8 CartMotionPak::SRAMRead(u32 addr)
|
||||
u8 CartMotionPakHomebrew::SRAMRead(u32 addr)
|
||||
{
|
||||
// CHECKME: SRAM address mask
|
||||
addr &= 0xFFFF;
|
||||
@ -129,6 +129,70 @@ u8 CartMotionPak::SRAMRead(u32 addr)
|
||||
return val;
|
||||
}
|
||||
|
||||
static int AccelerationToMotionPakRetail(float accel)
|
||||
{
|
||||
// Formula provided by xperia64 (melonDS/#74)
|
||||
const float GRAVITY_M_S2 = 9.80665f;
|
||||
const float VOLTAGE = 3.3f;
|
||||
|
||||
return std::clamp(
|
||||
(int) ((accel * (VOLTAGE / 5) / GRAVITY_M_S2 + (VOLTAGE / 2)) * 256 / VOLTAGE),
|
||||
0, 254
|
||||
);
|
||||
}
|
||||
|
||||
CartMotionPakRetail::CartMotionPakRetail(void* userdata) :
|
||||
CartCommon(MotionPakRetail),
|
||||
UserData(userdata)
|
||||
{
|
||||
}
|
||||
|
||||
CartMotionPakRetail::~CartMotionPakRetail() = default;
|
||||
|
||||
void CartMotionPakRetail::Reset()
|
||||
{
|
||||
Value = 0;
|
||||
Step = 16;
|
||||
}
|
||||
|
||||
void CartMotionPakRetail::DoSavestate(Savestate* file)
|
||||
{
|
||||
CartCommon::DoSavestate(file);
|
||||
file->Var8(&Value);
|
||||
file->Var8(&Step);
|
||||
}
|
||||
|
||||
u16 CartMotionPakRetail::ROMRead(u32 addr) const
|
||||
{
|
||||
return 0xFCFF;
|
||||
}
|
||||
|
||||
u8 CartMotionPakRetail::SRAMRead(u32 addr)
|
||||
{
|
||||
switch (Step)
|
||||
{
|
||||
case 0: // Synchronization - read 0xFF
|
||||
Value = 0xFF;
|
||||
break;
|
||||
case 4: // X acceleration
|
||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationX, UserData));
|
||||
break;
|
||||
case 8: // Y acceleration
|
||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationY, UserData));
|
||||
break;
|
||||
case 12: // Z acceleration
|
||||
Value = AccelerationToMotionPakRetail(Platform::Addon_MotionQuery(Platform::MotionAccelerationZ, UserData));
|
||||
break;
|
||||
case 16: // Synchronization - read 0b00
|
||||
Step = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shift = 6 - ((Step & 3) * 2);
|
||||
Step++;
|
||||
return (Value >> shift) & 0x03;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -211,7 +211,9 @@ enum
|
||||
{
|
||||
GBAAddon_RAMExpansion = 1,
|
||||
GBAAddon_RumblePak = 2,
|
||||
GBAAddon_MotionPak = 3,
|
||||
GBAAddon_MotionPakHomebrew = 3,
|
||||
GBAAddon_MotionPakRetail = 4,
|
||||
GBAAddon_GuitarGrip = 5,
|
||||
};
|
||||
|
||||
class SPU;
|
||||
|
@ -322,6 +322,18 @@ void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv, v
|
||||
|
||||
// interface for addon inputs
|
||||
|
||||
enum KeyType
|
||||
{
|
||||
KeyGuitarGripGreen,
|
||||
KeyGuitarGripRed,
|
||||
KeyGuitarGripYellow,
|
||||
KeyGuitarGripBlue,
|
||||
};
|
||||
|
||||
// Check if a given key is being pressed.
|
||||
// @param type The type of the key to check.
|
||||
bool Addon_KeyDown(KeyType type, void* userdata);
|
||||
|
||||
// Called by the DS Rumble Pak emulation to start the necessary
|
||||
// rumble effects on the connected game controller, if available.
|
||||
// @param len The duration of the controller rumble effect in milliseconds.
|
||||
|
@ -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},
|
||||
|
||||
|
@ -2090,8 +2090,12 @@ QString EmuInstance::gbaAddonName(int addon)
|
||||
return "Rumble Pak";
|
||||
case GBAAddon_RAMExpansion:
|
||||
return "Memory expansion";
|
||||
case GBAAddon_MotionPak:
|
||||
return "Motion Pak";
|
||||
case GBAAddon_MotionPakHomebrew:
|
||||
return "Motion Pak (Homebrew)";
|
||||
case GBAAddon_MotionPakRetail:
|
||||
return "Motion Pack (Retail)";
|
||||
case GBAAddon_GuitarGrip:
|
||||
return "Guitar Grip";
|
||||
}
|
||||
|
||||
return "???";
|
||||
|
@ -51,6 +51,10 @@ enum
|
||||
HK_SlowMo,
|
||||
HK_FastForwardToggle,
|
||||
HK_SlowMoToggle,
|
||||
HK_GuitarGripGreen,
|
||||
HK_GuitarGripRed,
|
||||
HK_GuitarGripYellow,
|
||||
HK_GuitarGripBlue,
|
||||
HK_MAX
|
||||
};
|
||||
|
||||
@ -143,6 +147,8 @@ public:
|
||||
void inputLoadConfig();
|
||||
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);
|
||||
|
@ -62,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"
|
||||
};
|
||||
|
||||
|
||||
@ -208,7 +212,6 @@ void EmuInstance::closeJoystick()
|
||||
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());
|
||||
|
@ -550,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);
|
||||
|
@ -320,7 +320,14 @@ 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_MotionPak, -1};
|
||||
int addons[] = {
|
||||
GBAAddon_RAMExpansion,
|
||||
GBAAddon_RumblePak,
|
||||
GBAAddon_MotionPakHomebrew,
|
||||
GBAAddon_MotionPakRetail,
|
||||
GBAAddon_GuitarGrip,
|
||||
-1
|
||||
};
|
||||
for (int i = 0; addons[i] != -1; i++)
|
||||
{
|
||||
int addon = addons[i];
|
||||
|
Loading…
Reference in New Issue
Block a user