mirror of
https://github.com/LNH-team/pico-launcher.git
synced 2026-06-02 09:06:54 +02:00
Initial commit
This commit is contained in:
11
arm9/source/gui/input/IInputSource.h
Normal file
11
arm9/source/gui/input/IInputSource.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "InputKey.h"
|
||||
|
||||
/// @brief Interface for a source of key input.
|
||||
class IInputSource
|
||||
{
|
||||
public:
|
||||
virtual ~IInputSource() { }
|
||||
|
||||
virtual InputKey Sample() const = 0;
|
||||
};
|
||||
45
arm9/source/gui/input/InputKey.h
Normal file
45
arm9/source/gui/input/InputKey.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
enum class InputKey : u16
|
||||
{
|
||||
None = 0,
|
||||
A = 1 << 0,
|
||||
B = 1 << 1,
|
||||
Select = 1 << 2,
|
||||
Start = 1 << 3,
|
||||
DpadRight = 1 << 4,
|
||||
DpadLeft = 1 << 5,
|
||||
DpadUp = 1 << 6,
|
||||
DpadDown = 1 << 7,
|
||||
R = 1 << 8,
|
||||
L = 1 << 9,
|
||||
X = 1 << 10,
|
||||
Y = 1 << 11,
|
||||
Debug = 1 << 13
|
||||
};
|
||||
|
||||
inline InputKey operator&(InputKey lhs, InputKey rhs)
|
||||
{
|
||||
return static_cast<InputKey>(static_cast<u16>(lhs) & static_cast<u16>(rhs));
|
||||
}
|
||||
|
||||
inline InputKey operator|(InputKey lhs, InputKey rhs)
|
||||
{
|
||||
return static_cast<InputKey>(static_cast<u16>(lhs) | static_cast<u16>(rhs));
|
||||
}
|
||||
|
||||
inline InputKey operator~(InputKey lhs)
|
||||
{
|
||||
return static_cast<InputKey>(~static_cast<u16>(lhs));
|
||||
}
|
||||
|
||||
inline InputKey operator^(InputKey lhs, InputKey rhs)
|
||||
{
|
||||
return static_cast<InputKey>(static_cast<u16>(lhs) ^ static_cast<u16>(rhs));
|
||||
}
|
||||
|
||||
inline InputKey operator|=(InputKey& lhs, InputKey rhs)
|
||||
{
|
||||
lhs = lhs | rhs; // don't use |= to prevent recursion
|
||||
return lhs;
|
||||
}
|
||||
58
arm9/source/gui/input/InputProvider.h
Normal file
58
arm9/source/gui/input/InputProvider.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputKey.h"
|
||||
|
||||
class InputProvider
|
||||
{
|
||||
public:
|
||||
/// @brief Returns a bitmask of the keys currently being held.
|
||||
/// @return A bitmask of the keys currently being held.
|
||||
InputKey GetCurrentKeys() const { return _currentKeys; }
|
||||
|
||||
/// @brief Returns whether any of the keys in the given \p mask is currently being held.
|
||||
/// @param mask The mask to check for.
|
||||
/// @return \c true if any of the keys in the \p mask is being held, or \c false otherwise.
|
||||
bool Current(InputKey mask) const { return static_cast<bool>(_currentKeys & mask); }
|
||||
|
||||
/// @brief Returns a bitmask of the keys that went from unpressed to pressed in the latest update.
|
||||
/// @return A bitmask of the keys that went from unpressed to pressed in the latest update.
|
||||
InputKey GetTriggeredKeys() const
|
||||
{
|
||||
return _triggeredKeys;
|
||||
}
|
||||
|
||||
/// @brief Returns whether any of the keys in the given \p mask went from unpressed to pressed in the latest update.
|
||||
/// @param mask The mask to check for.
|
||||
/// @return \c true if any of the keys in the \p mask went from unpressed to pressed
|
||||
/// in the latest update, or \c false otherwise.
|
||||
bool Triggered(InputKey mask) const { return static_cast<bool>(_triggeredKeys & mask); }
|
||||
|
||||
/// @brief Returns a bitmask of the keys that went from pressed to unpressed in the latest update.
|
||||
/// @return A bitmask of the keys that went from pressed to unpressed in the latest update.
|
||||
InputKey GetReleasedKeys() const { return _releasedKeys; }
|
||||
|
||||
/// @brief Returns whether any of the keys in the given \p mask went from pressed to unpressed in the latest update.
|
||||
/// @param mask The mask to check for.
|
||||
/// @return \c true if any of the keys in the \p mask went from pressed to unpressed
|
||||
/// in the latest update, or \c false otherwise.
|
||||
bool Released(InputKey mask) const { return static_cast<bool>(_releasedKeys & mask); }
|
||||
|
||||
/// @brief Updates the input provider.
|
||||
virtual void Update() = 0;
|
||||
|
||||
/// @brief Resets the input provider.
|
||||
virtual void Reset()
|
||||
{
|
||||
_currentKeys = InputKey::None;
|
||||
_triggeredKeys = InputKey::None;
|
||||
_releasedKeys = InputKey::None;
|
||||
}
|
||||
|
||||
protected:
|
||||
InputKey _currentKeys;
|
||||
InputKey _triggeredKeys;
|
||||
InputKey _releasedKeys;
|
||||
|
||||
InputProvider()
|
||||
: _currentKeys(InputKey::None), _triggeredKeys(InputKey::None), _releasedKeys(InputKey::None) { }
|
||||
};
|
||||
58
arm9/source/gui/input/InputRepeater.cpp
Normal file
58
arm9/source/gui/input/InputRepeater.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "common.h"
|
||||
#include "InputRepeater.h"
|
||||
|
||||
void InputRepeater::Update()
|
||||
{
|
||||
_inputProvider->Update();
|
||||
InputKey curKeys = _inputProvider->GetCurrentKeys();
|
||||
InputKey repKeys = InputKey::None;
|
||||
if (_state == State::Idle)
|
||||
{
|
||||
if (static_cast<bool>(curKeys & _repeatMask))
|
||||
{
|
||||
_state = State::FirstRepeat;
|
||||
_frameCounter = 0;
|
||||
repKeys = curKeys & _repeatMask;
|
||||
}
|
||||
}
|
||||
else if (_state == State::FirstRepeat)
|
||||
{
|
||||
if (static_cast<bool>(curKeys & _repeatMask))
|
||||
{
|
||||
if (++_frameCounter >= _firstRepeatDelayFrames)
|
||||
{
|
||||
_state = State::NextRepeat;
|
||||
_frameCounter = 0;
|
||||
repKeys = curKeys & _repeatMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
_state = State::Idle;
|
||||
}
|
||||
else if (_state == State::NextRepeat)
|
||||
{
|
||||
if (static_cast<bool>(curKeys & _repeatMask))
|
||||
{
|
||||
if (++_frameCounter >= _nextRepeatDelayFrames)
|
||||
{
|
||||
_frameCounter = 0;
|
||||
repKeys = curKeys & _repeatMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
_state = State::Idle;
|
||||
}
|
||||
|
||||
InputKey lastRepKeys = _currentKeys & _repeatMask;
|
||||
_currentKeys = curKeys | repKeys;
|
||||
_triggeredKeys = _inputProvider->GetTriggeredKeys() | repKeys;
|
||||
_releasedKeys = _inputProvider->GetReleasedKeys() | (lastRepKeys & (lastRepKeys ^ repKeys));
|
||||
}
|
||||
|
||||
void InputRepeater::Reset()
|
||||
{
|
||||
InputProvider::Reset();
|
||||
_inputProvider->Reset();
|
||||
_state = State::Idle;
|
||||
_frameCounter = 0;
|
||||
}
|
||||
31
arm9/source/gui/input/InputRepeater.h
Normal file
31
arm9/source/gui/input/InputRepeater.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "InputProvider.h"
|
||||
|
||||
/// @brief Input provider that wraps another input provider and adds key repetition on top of it.
|
||||
class InputRepeater : public InputProvider
|
||||
{
|
||||
public:
|
||||
InputRepeater(InputProvider* inputProvider, InputKey repeatMask, u16 firstRepeatDelay, u16 nextRepeatDelay)
|
||||
: _inputProvider(inputProvider), _state(State::Idle)
|
||||
, _frameCounter(0), _repeatMask(repeatMask)
|
||||
, _firstRepeatDelayFrames(firstRepeatDelay)
|
||||
, _nextRepeatDelayFrames(nextRepeatDelay) { }
|
||||
|
||||
void Update() override;
|
||||
void Reset() override;
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
Idle,
|
||||
FirstRepeat,
|
||||
NextRepeat
|
||||
};
|
||||
|
||||
InputProvider* _inputProvider;
|
||||
State _state;
|
||||
u16 _frameCounter;
|
||||
InputKey _repeatMask;
|
||||
u16 _firstRepeatDelayFrames;
|
||||
u16 _nextRepeatDelayFrames;
|
||||
};
|
||||
17
arm9/source/gui/input/PadInputSource.h
Normal file
17
arm9/source/gui/input/PadInputSource.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <nds/input.h>
|
||||
#include "IInputSource.h"
|
||||
#include "sharedMemory.h"
|
||||
|
||||
/// @brief Input source from the physical DS buttons.
|
||||
class PadInputSource : public IInputSource
|
||||
{
|
||||
public:
|
||||
InputKey Sample() const override
|
||||
{
|
||||
u16 arm9Mask = (~REG_KEYINPUT & 0x3FF);
|
||||
u16 arm7Mask = (~SHARED_KEY_XY & 0xB);
|
||||
return static_cast<InputKey>((arm9Mask | (arm7Mask << 10)));
|
||||
}
|
||||
};
|
||||
22
arm9/source/gui/input/SampledInputProvider.cpp
Normal file
22
arm9/source/gui/input/SampledInputProvider.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "common.h"
|
||||
#include "SampledInputProvider.h"
|
||||
|
||||
void SampledInputProvider::Update()
|
||||
{
|
||||
InputKey curKeys = _currentKeys;
|
||||
InputKey trig = InputKey::None;
|
||||
InputKey rel = InputKey::None;
|
||||
|
||||
while (_inputBufferReadPtr != _inputBufferWritePtr)
|
||||
{
|
||||
InputKey nextKeys = _inputBuffer[_inputBufferReadPtr];
|
||||
trig |= (nextKeys ^ curKeys) & nextKeys;
|
||||
rel |= (nextKeys ^ curKeys) & curKeys;
|
||||
curKeys = nextKeys;
|
||||
_inputBufferReadPtr = (_inputBufferReadPtr + 1) & 3;
|
||||
}
|
||||
|
||||
_triggeredKeys = trig;
|
||||
_releasedKeys = rel;
|
||||
_currentKeys = curKeys;
|
||||
}
|
||||
34
arm9/source/gui/input/SampledInputProvider.h
Normal file
34
arm9/source/gui/input/SampledInputProvider.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "InputProvider.h"
|
||||
#include "IInputSource.h"
|
||||
|
||||
/// @brief Input provider providing input from an \see IInputSource.
|
||||
class SampledInputProvider : public InputProvider
|
||||
{
|
||||
public:
|
||||
explicit SampledInputProvider(const IInputSource* inputSource)
|
||||
: _inputSource(inputSource), _inputBufferReadPtr(0), _inputBufferWritePtr(0) { }
|
||||
|
||||
void Update() override;
|
||||
|
||||
/// @brief Samples the input source.
|
||||
void Sample()
|
||||
{
|
||||
_inputBuffer[_inputBufferWritePtr] = _inputSource->Sample();
|
||||
_inputBufferWritePtr = (_inputBufferWritePtr + 1) & 3;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
InputProvider::Reset();
|
||||
_inputBufferReadPtr = 0;
|
||||
_inputBufferWritePtr = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const IInputSource* _inputSource;
|
||||
|
||||
InputKey _inputBuffer[4];
|
||||
u8 _inputBufferReadPtr;
|
||||
u8 _inputBufferWritePtr;
|
||||
};
|
||||
Reference in New Issue
Block a user