mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #14592 from hrydgard/control-refactor
Break out EmuScreen's key/axis inputs to ControlMapper.cpp/h
This commit is contained in:
commit
26f69d578a
12 changed files with 424 additions and 321 deletions
|
@ -1565,6 +1565,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
|||
Core/Config.cpp
|
||||
Core/Config.h
|
||||
Core/ConfigValues.h
|
||||
Core/ControlMapper.cpp
|
||||
Core/ControlMapper.h
|
||||
Core/Core.cpp
|
||||
Core/Core.h
|
||||
Core/Compatibility.cpp
|
||||
|
|
312
Core/ControlMapper.cpp
Normal file
312
Core/ControlMapper.cpp
Normal file
|
@ -0,0 +1,312 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Core/KeyMap.h"
|
||||
#include "Core/ControlMapper.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
static float MapAxisValue(float v) {
|
||||
const float deadzone = g_Config.fAnalogDeadzone;
|
||||
const float invDeadzone = g_Config.fAnalogInverseDeadzone;
|
||||
const float sensitivity = g_Config.fAnalogSensitivity;
|
||||
const float sign = v >= 0.0f ? 1.0f : -1.0f;
|
||||
return sign * Clamp(invDeadzone + (abs(v) - deadzone) / (1.0f - deadzone) * (sensitivity - invDeadzone), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ConvertAnalogStick(float &x, float &y) {
|
||||
const bool isCircular = g_Config.bAnalogIsCircular;
|
||||
|
||||
float norm = std::max(fabsf(x), fabsf(y));
|
||||
|
||||
if (norm == 0.0f)
|
||||
return;
|
||||
|
||||
if (isCircular) {
|
||||
float newNorm = sqrtf(x * x + y * y);
|
||||
float factor = newNorm / norm;
|
||||
x *= factor;
|
||||
y *= factor;
|
||||
norm = newNorm;
|
||||
}
|
||||
|
||||
float mappedNorm = MapAxisValue(norm);
|
||||
x = Clamp(x / norm * mappedNorm, -1.0f, 1.0f);
|
||||
y = Clamp(y / norm * mappedNorm, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ControlMapper::SetCallbacks(std::function<void(int)> onVKeyDown, std::function<void(int)> onVKeyUp, std::function<void(char, float, int)> setPSPAxis) {
|
||||
onVKeyDown_ = onVKeyDown;
|
||||
onVKeyUp_ = onVKeyUp;
|
||||
setPSPAxis_ = setPSPAxis;
|
||||
}
|
||||
|
||||
bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) {
|
||||
std::vector<int> pspKeys;
|
||||
KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys);
|
||||
|
||||
if (pspKeys.size() && (key.flags & KEY_IS_REPEAT)) {
|
||||
// Claim that we handled this. Prevents volume key repeats from popping up the volume control on Android.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pspKeys.size(); i++) {
|
||||
pspKey(pspKeys[i], key.flags);
|
||||
}
|
||||
|
||||
if (!pspKeys.size() || key.deviceId == DEVICE_ID_DEFAULT) {
|
||||
if ((key.flags & KEY_DOWN) && key.keyCode == NKCODE_BACK) {
|
||||
*pauseTrigger = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pspKeys.size() > 0;
|
||||
}
|
||||
|
||||
bool ControlMapper::Axis(const AxisInput &axis) {
|
||||
if (axis.value > 0) {
|
||||
processAxis(axis, 1);
|
||||
return true;
|
||||
} else if (axis.value < 0) {
|
||||
processAxis(axis, -1);
|
||||
return true;
|
||||
} else if (axis.value == 0) {
|
||||
// Both directions! Prevents sticking for digital input devices that are axises (like HAT)
|
||||
processAxis(axis, 1);
|
||||
processAxis(axis, -1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool IsAnalogStickKey(int key) {
|
||||
switch (key) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int RotatePSPKeyCode(int x) {
|
||||
switch (x) {
|
||||
case CTRL_UP: return CTRL_RIGHT;
|
||||
case CTRL_RIGHT: return CTRL_DOWN;
|
||||
case CTRL_DOWN: return CTRL_LEFT;
|
||||
case CTRL_LEFT: return CTRL_UP;
|
||||
default:
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapper::setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero) {
|
||||
// The down events can repeat, so just trust the virtKeys array.
|
||||
bool minDown = virtKeys[virtualKeyMin - VIRTKEY_FIRST];
|
||||
bool maxDown = virtKeys[virtualKeyMax - VIRTKEY_FIRST];
|
||||
|
||||
const float scale = virtKeys[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f;
|
||||
float value = 0.0f;
|
||||
if (minDown)
|
||||
value -= scale;
|
||||
if (maxDown)
|
||||
value += scale;
|
||||
if (setZero || minDown || maxDown) {
|
||||
setPSPAxis_(axis, value, stick);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapper::pspKey(int pspKeyCode, int flags) {
|
||||
int rotations = 0;
|
||||
switch (g_Config.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL180:
|
||||
rotations = 2;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL:
|
||||
rotations = 1;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL180:
|
||||
rotations = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rotations; i++) {
|
||||
pspKeyCode = RotatePSPKeyCode(pspKeyCode);
|
||||
}
|
||||
|
||||
if (pspKeyCode >= VIRTKEY_FIRST) {
|
||||
int vk = pspKeyCode - VIRTKEY_FIRST;
|
||||
if (flags & KEY_DOWN) {
|
||||
virtKeys[vk] = true;
|
||||
onVKeyDown(pspKeyCode);
|
||||
}
|
||||
if (flags & KEY_UP) {
|
||||
virtKeys[vk] = false;
|
||||
onVKeyUp(pspKeyCode);
|
||||
}
|
||||
} else {
|
||||
// INFO_LOG(SYSTEM, "pspKey %i %i", pspKeyCode, flags);
|
||||
if (flags & KEY_DOWN)
|
||||
__CtrlButtonDown(pspKeyCode);
|
||||
if (flags & KEY_UP)
|
||||
__CtrlButtonUp(pspKeyCode);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapper::onVKeyDown(int vkey) {
|
||||
switch (vkey) {
|
||||
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_ANALOG_LIGHTLY:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX, false);
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (onVKeyDown_)
|
||||
onVKeyDown_(vkey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapper::onVKeyUp(int vkey) {
|
||||
switch (vkey) {
|
||||
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_ANALOG_LIGHTLY:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX, false);
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (onVKeyUp_)
|
||||
onVKeyUp_(vkey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlMapper::processAxis(const AxisInput &axis, int direction) {
|
||||
// Sanity check
|
||||
if (axis.axisId < 0 || axis.axisId >= JOYSTICK_AXIS_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float scale = virtKeys[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f;
|
||||
|
||||
std::vector<int> results;
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction, &results);
|
||||
|
||||
for (int result : results) {
|
||||
float value = fabs(axis.value) * scale;
|
||||
switch (result) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
setPSPAxis_('X', -value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
setPSPAxis_('X', value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
setPSPAxis_('Y', -value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
setPSPAxis_('Y', value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
setPSPAxis_('X', -value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
setPSPAxis_('X', value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
setPSPAxis_('Y', -value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
setPSPAxis_('Y', value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> resultsOpposite;
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite);
|
||||
|
||||
int axisState = 0;
|
||||
float threshold = axis.deviceId == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD;
|
||||
if (direction == 1 && axis.value >= threshold) {
|
||||
axisState = 1;
|
||||
} else if (direction == -1 && axis.value <= -threshold) {
|
||||
axisState = -1;
|
||||
} else {
|
||||
axisState = 0;
|
||||
}
|
||||
|
||||
if (axisState != axisState_[axis.axisId]) {
|
||||
axisState_[axis.axisId] = axisState;
|
||||
if (axisState != 0) {
|
||||
for (size_t i = 0; i < results.size(); i++) {
|
||||
if (!IsAnalogStickKey(results[i]))
|
||||
pspKey(results[i], KEY_DOWN);
|
||||
}
|
||||
// Also unpress the other direction (unless both directions press the same key.)
|
||||
for (size_t i = 0; i < resultsOpposite.size(); i++) {
|
||||
if (!IsAnalogStickKey(resultsOpposite[i]) && std::find(results.begin(), results.end(), resultsOpposite[i]) == results.end())
|
||||
pspKey(resultsOpposite[i], KEY_UP);
|
||||
}
|
||||
} else if (axisState == 0) {
|
||||
// Release both directions, trying to deal with some erratic controllers that can cause it to stick.
|
||||
for (size_t i = 0; i < results.size(); i++) {
|
||||
if (!IsAnalogStickKey(results[i]))
|
||||
pspKey(results[i], KEY_UP);
|
||||
}
|
||||
for (size_t i = 0; i < resultsOpposite.size(); i++) {
|
||||
if (!IsAnalogStickKey(resultsOpposite[i]))
|
||||
pspKey(resultsOpposite[i], KEY_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
Core/ControlMapper.h
Normal file
45
Core/ControlMapper.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/Input/InputState.h"
|
||||
#include "Core/KeyMap.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
// Utilities for mapping input events to PSP inputs and virtual keys.
|
||||
// Main use is of course from EmuScreen.cpp, but also useful from control settings etc.
|
||||
|
||||
|
||||
// Maps analog stick input to a distorted space according to
|
||||
// the deadzone and shape settings.
|
||||
void ConvertAnalogStick(float &x, float &y);
|
||||
|
||||
|
||||
class ControlMapper {
|
||||
public:
|
||||
bool Key(const KeyInput &key, bool *pauseTrigger);
|
||||
bool Axis(const AxisInput &axis);
|
||||
|
||||
void SetCallbacks(
|
||||
std::function<void(int)> onVKeyDown,
|
||||
std::function<void(int)> onVKeyUp,
|
||||
std::function<void(char, float, int)> setPSPAxis);
|
||||
|
||||
private:
|
||||
void processAxis(const AxisInput &axis, int direction);
|
||||
void pspKey(int pspKeyCode, int flags);
|
||||
void setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero = true);
|
||||
|
||||
void onVKeyDown(int vkey);
|
||||
void onVKeyUp(int vkey);
|
||||
|
||||
// To track mappable virtual keys. We can have as many as we want.
|
||||
bool virtKeys[VIRTKEY_COUNT]{};
|
||||
|
||||
// De-noise mapped axis updates
|
||||
int axisState_[JOYSTICK_AXIS_MAX]{};
|
||||
|
||||
// Callbacks
|
||||
std::function<void(int)> onVKeyDown_;
|
||||
std::function<void(int)> onVKeyUp_;
|
||||
std::function<void(char, float, int)> setPSPAxis_;
|
||||
};
|
|
@ -509,6 +509,7 @@
|
|||
<ClCompile Include="..\ext\udis86\syn-intel.c" />
|
||||
<ClCompile Include="..\ext\udis86\syn.c" />
|
||||
<ClCompile Include="..\ext\udis86\udis86.c" />
|
||||
<ClCompile Include="ControlMapper.cpp" />
|
||||
<ClCompile Include="AVIDump.cpp" />
|
||||
<ClCompile Include="Debugger\MemBlockInfo.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket.cpp" />
|
||||
|
@ -1064,6 +1065,7 @@
|
|||
<ClInclude Include="..\ext\udis86\types.h" />
|
||||
<ClInclude Include="..\ext\udis86\udint.h" />
|
||||
<ClInclude Include="..\ext\udis86\udis86.h" />
|
||||
<ClInclude Include="ControlMapper.h" />
|
||||
<ClInclude Include="AVIDump.h" />
|
||||
<ClInclude Include="ConfigValues.h" />
|
||||
<ClInclude Include="Debugger\MemBlockInfo.h" />
|
||||
|
@ -1398,4 +1400,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -1175,6 +1175,9 @@
|
|||
<ClCompile Include="Debugger\WebSocket\ReplaySubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ControlMapper.cpp">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
|
@ -1892,6 +1895,9 @@
|
|||
<ClInclude Include="Debugger\WebSocket\ReplaySubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ControlMapper.h">
|
||||
<Filter>Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -1918,4 +1924,4 @@
|
|||
<Filter>Ext\libzip</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
311
UI/EmuScreen.cpp
311
UI/EmuScreen.cpp
|
@ -18,6 +18,9 @@
|
|||
#include "ppsspp_config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
#include "Common/Render/TextureAtlas.h"
|
||||
#include "Common/GPU/OpenGL/GLFeatures.h"
|
||||
|
@ -93,6 +96,7 @@
|
|||
static AVIDump avi;
|
||||
#endif
|
||||
|
||||
// TODO: Ugly!
|
||||
static bool frameStep_;
|
||||
static int lastNumFlips;
|
||||
static bool startDumping;
|
||||
|
@ -129,14 +133,45 @@ static void __EmuScreenVblank()
|
|||
#endif
|
||||
}
|
||||
|
||||
// Handles control rotation due to internal screen rotation.
|
||||
// TODO: This should be a callback too, so we don't actually call the __Ctrl functions
|
||||
// from settings screens, etc.
|
||||
static void SetPSPAxis(char axis, float value, int stick) {
|
||||
switch (g_Config.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL:
|
||||
// Standard rotation.
|
||||
break;
|
||||
case ROTATION_LOCKED_HORIZONTAL180:
|
||||
value = -value;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL:
|
||||
value = axis == 'Y' ? value : -value;
|
||||
axis = (axis == 'X') ? 'Y' : 'X';
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL180:
|
||||
value = axis == 'Y' ? -value : value;
|
||||
axis = (axis == 'X') ? 'Y' : 'X';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (axis == 'X')
|
||||
__CtrlSetAnalogX(value, stick);
|
||||
else if (axis == 'Y')
|
||||
__CtrlSetAnalogY(value, stick);
|
||||
}
|
||||
|
||||
EmuScreen::EmuScreen(const Path &filename)
|
||||
: bootPending_(true), gamePath_(filename), invalid_(true), quit_(false), pauseTrigger_(false), saveStatePreviewShownTime_(0.0), saveStatePreview_(nullptr) {
|
||||
memset(axisState_, 0, sizeof(axisState_));
|
||||
: gamePath_(filename) {
|
||||
saveStateSlot_ = SaveState::GetCurrentSlot();
|
||||
__DisplayListenVblank(__EmuScreenVblank);
|
||||
frameStep_ = false;
|
||||
lastNumFlips = gpuStats.numFlips;
|
||||
startDumping = false;
|
||||
controlMapper_.SetCallbacks(
|
||||
std::bind(&EmuScreen::onVKeyDown, this, _1),
|
||||
std::bind(&EmuScreen::onVKeyUp, this, _1),
|
||||
&SetPSPAxis);
|
||||
|
||||
// Make sure we don't leave it at powerdown after the last game.
|
||||
// TODO: This really should be handled elsewhere if it isn't.
|
||||
|
@ -308,7 +343,6 @@ void EmuScreen::bootComplete() {
|
|||
osm.Show(sc->T("PressESC", "Press ESC to open the pause menu"), 3.0f);
|
||||
}
|
||||
#endif
|
||||
memset(virtKeys, 0, sizeof(virtKeys));
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
if (GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
|
@ -596,31 +630,6 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) {
|
|||
}
|
||||
#endif
|
||||
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_ANALOG_LIGHTLY:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX, false);
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX, false);
|
||||
break;
|
||||
|
||||
case VIRTKEY_REWIND:
|
||||
if (SaveState::CanRewind()) {
|
||||
SaveState::Rewind(&AfterSaveStateAction);
|
||||
|
@ -701,31 +710,6 @@ void EmuScreen::onVKeyUp(int virtualKeyCode) {
|
|||
}
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX);
|
||||
break;
|
||||
|
||||
case VIRTKEY_ANALOG_LIGHTLY:
|
||||
setVKeyAnalog('X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX, false);
|
||||
setVKeyAnalog('X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, false);
|
||||
setVKeyAnalog('Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX, false);
|
||||
break;
|
||||
|
||||
case VIRTKEY_RAPID_FIRE:
|
||||
__CtrlSetRapidFire(false);
|
||||
break;
|
||||
|
@ -747,233 +731,16 @@ void EmuScreen::onVKeyUp(int virtualKeyCode) {
|
|||
}
|
||||
}
|
||||
|
||||
// Handles control rotation due to internal screen rotation.
|
||||
static void SetPSPAxis(char axis, float value, int stick) {
|
||||
switch (g_Config.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL:
|
||||
// Standard rotation.
|
||||
break;
|
||||
case ROTATION_LOCKED_HORIZONTAL180:
|
||||
value = -value;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL:
|
||||
value = axis == 'Y' ? value : -value;
|
||||
axis = (axis == 'X') ? 'Y' : 'X';
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL180:
|
||||
value = axis == 'Y' ? -value : value;
|
||||
axis = (axis == 'X') ? 'Y' : 'X';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (axis == 'X')
|
||||
__CtrlSetAnalogX(value, stick);
|
||||
else if (axis == 'Y')
|
||||
__CtrlSetAnalogY(value, stick);
|
||||
}
|
||||
|
||||
inline void EmuScreen::setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero) {
|
||||
// The down events can repeat, so just trust the virtKeys array.
|
||||
bool minDown = virtKeys[virtualKeyMin - VIRTKEY_FIRST];
|
||||
bool maxDown = virtKeys[virtualKeyMax - VIRTKEY_FIRST];
|
||||
|
||||
const float scale = virtKeys[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f;
|
||||
float value = 0.0f;
|
||||
if (minDown)
|
||||
value -= scale;
|
||||
if (maxDown)
|
||||
value += scale;
|
||||
if (setZero || minDown || maxDown)
|
||||
SetPSPAxis(axis, value, stick);
|
||||
}
|
||||
|
||||
bool EmuScreen::key(const KeyInput &key) {
|
||||
Core_NotifyActivity();
|
||||
|
||||
std::vector<int> pspKeys;
|
||||
KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys);
|
||||
|
||||
if (pspKeys.size() && (key.flags & KEY_IS_REPEAT)) {
|
||||
// Claim that we handled this. Prevents volume key repeats from popping up the volume control on Android.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pspKeys.size(); i++) {
|
||||
pspKey(pspKeys[i], key.flags);
|
||||
}
|
||||
|
||||
if (!pspKeys.size() || key.deviceId == DEVICE_ID_DEFAULT) {
|
||||
if ((key.flags & KEY_DOWN) && key.keyCode == NKCODE_BACK) {
|
||||
pauseTrigger_ = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pspKeys.size() > 0;
|
||||
}
|
||||
|
||||
static int RotatePSPKeyCode(int x) {
|
||||
switch (x) {
|
||||
case CTRL_UP: return CTRL_RIGHT;
|
||||
case CTRL_RIGHT: return CTRL_DOWN;
|
||||
case CTRL_DOWN: return CTRL_LEFT;
|
||||
case CTRL_LEFT: return CTRL_UP;
|
||||
default:
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::pspKey(int pspKeyCode, int flags) {
|
||||
int rotations = 0;
|
||||
switch (g_Config.iInternalScreenRotation) {
|
||||
case ROTATION_LOCKED_HORIZONTAL180:
|
||||
rotations = 2;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL:
|
||||
rotations = 1;
|
||||
break;
|
||||
case ROTATION_LOCKED_VERTICAL180:
|
||||
rotations = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rotations; i++) {
|
||||
pspKeyCode = RotatePSPKeyCode(pspKeyCode);
|
||||
}
|
||||
|
||||
if (pspKeyCode >= VIRTKEY_FIRST) {
|
||||
int vk = pspKeyCode - VIRTKEY_FIRST;
|
||||
if (flags & KEY_DOWN) {
|
||||
virtKeys[vk] = true;
|
||||
onVKeyDown(pspKeyCode);
|
||||
}
|
||||
if (flags & KEY_UP) {
|
||||
virtKeys[vk] = false;
|
||||
onVKeyUp(pspKeyCode);
|
||||
}
|
||||
} else {
|
||||
// INFO_LOG(SYSTEM, "pspKey %i %i", pspKeyCode, flags);
|
||||
if (flags & KEY_DOWN)
|
||||
__CtrlButtonDown(pspKeyCode);
|
||||
if (flags & KEY_UP)
|
||||
__CtrlButtonUp(pspKeyCode);
|
||||
}
|
||||
return controlMapper_.Key(key, &pauseTrigger_);
|
||||
}
|
||||
|
||||
bool EmuScreen::axis(const AxisInput &axis) {
|
||||
Core_NotifyActivity();
|
||||
|
||||
if (axis.value > 0) {
|
||||
processAxis(axis, 1);
|
||||
return true;
|
||||
} else if (axis.value < 0) {
|
||||
processAxis(axis, -1);
|
||||
return true;
|
||||
} else if (axis.value == 0) {
|
||||
// Both directions! Prevents sticking for digital input devices that are axises (like HAT)
|
||||
processAxis(axis, 1);
|
||||
processAxis(axis, -1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool IsAnalogStickKey(int key) {
|
||||
switch (key) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuScreen::processAxis(const AxisInput &axis, int direction) {
|
||||
// Sanity check
|
||||
if (axis.axisId < 0 || axis.axisId >= JOYSTICK_AXIS_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float scale = virtKeys[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f;
|
||||
|
||||
std::vector<int> results;
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, direction, &results);
|
||||
|
||||
for (int result : results) {
|
||||
float value = fabs(axis.value) * scale;
|
||||
switch (result) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
SetPSPAxis('X', -value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
SetPSPAxis('X', value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
SetPSPAxis('Y', -value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
SetPSPAxis('Y', value, CTRL_STICK_LEFT);
|
||||
break;
|
||||
|
||||
case VIRTKEY_AXIS_RIGHT_X_MIN:
|
||||
SetPSPAxis('X', -value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_X_MAX:
|
||||
SetPSPAxis('X', value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MIN:
|
||||
SetPSPAxis('Y', -value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
case VIRTKEY_AXIS_RIGHT_Y_MAX:
|
||||
SetPSPAxis('Y', value, CTRL_STICK_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> resultsOpposite;
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite);
|
||||
|
||||
int axisState = 0;
|
||||
float threshold = axis.deviceId == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD;
|
||||
if (direction == 1 && axis.value >= threshold) {
|
||||
axisState = 1;
|
||||
} else if (direction == -1 && axis.value <= -threshold) {
|
||||
axisState = -1;
|
||||
} else {
|
||||
axisState = 0;
|
||||
}
|
||||
|
||||
if (axisState != axisState_[axis.axisId]) {
|
||||
axisState_[axis.axisId] = axisState;
|
||||
if (axisState != 0) {
|
||||
for (size_t i = 0; i < results.size(); i++) {
|
||||
if (!IsAnalogStickKey(results[i]))
|
||||
pspKey(results[i], KEY_DOWN);
|
||||
}
|
||||
// Also unpress the other direction (unless both directions press the same key.)
|
||||
for (size_t i = 0; i < resultsOpposite.size(); i++) {
|
||||
if (!IsAnalogStickKey(resultsOpposite[i]) && std::find(results.begin(), results.end(), resultsOpposite[i]) == results.end())
|
||||
pspKey(resultsOpposite[i], KEY_UP);
|
||||
}
|
||||
} else if (axisState == 0) {
|
||||
// Release both directions, trying to deal with some erratic controllers that can cause it to stick.
|
||||
for (size_t i = 0; i < results.size(); i++) {
|
||||
if (!IsAnalogStickKey(results[i]))
|
||||
pspKey(results[i], KEY_UP);
|
||||
}
|
||||
for (size_t i = 0; i < resultsOpposite.size(); i++) {
|
||||
if (!IsAnalogStickKey(resultsOpposite[i]))
|
||||
pspKey(resultsOpposite[i], KEY_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
return controlMapper_.Axis(axis);
|
||||
}
|
||||
|
||||
class GameInfoBGView : public UI::InertView {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Common/UI/UIScreen.h"
|
||||
#include "Common/UI/Tween.h"
|
||||
#include "Core/KeyMap.h"
|
||||
#include "Core/ControlMapper.h"
|
||||
|
||||
struct AxisInput;
|
||||
|
||||
|
@ -62,43 +63,34 @@ private:
|
|||
void bootComplete();
|
||||
bool hasVisibleUI();
|
||||
void renderUI();
|
||||
void processAxis(const AxisInput &axis, int direction);
|
||||
|
||||
void pspKey(int pspKeyCode, int flags);
|
||||
void onVKeyDown(int virtualKeyCode);
|
||||
void onVKeyUp(int virtualKeyCode);
|
||||
void setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero = true);
|
||||
|
||||
void autoLoad();
|
||||
void checkPowerDown();
|
||||
|
||||
UI::Event OnDevMenu;
|
||||
UI::Event OnChatMenu;
|
||||
bool bootPending_;
|
||||
bool bootPending_ = true;
|
||||
Path gamePath_;
|
||||
|
||||
// Something invalid was loaded, don't try to emulate
|
||||
bool invalid_;
|
||||
bool quit_;
|
||||
bool invalid_ = true;
|
||||
bool quit_ = false;
|
||||
bool stopRender_ = false;
|
||||
std::string errorMessage_;
|
||||
|
||||
// If set, pauses at the end of the frame.
|
||||
bool pauseTrigger_;
|
||||
|
||||
// To track mappable virtual keys. We can have as many as we want.
|
||||
bool virtKeys[VIRTKEY_COUNT];
|
||||
bool pauseTrigger_ = false;
|
||||
|
||||
// In-memory save state used for freezeFrame, which is useful for debugging.
|
||||
std::vector<u8> freezeState_;
|
||||
|
||||
std::string tag_;
|
||||
|
||||
// De-noise mapped axis updates
|
||||
int axisState_[JOYSTICK_AXIS_MAX];
|
||||
|
||||
double saveStatePreviewShownTime_;
|
||||
AsyncImageFileView *saveStatePreview_;
|
||||
double saveStatePreviewShownTime_ = 0.0;
|
||||
AsyncImageFileView *saveStatePreview_ = nullptr;
|
||||
int saveStateSlot_;
|
||||
|
||||
UI::CallbackColorTween *loadingViewColor_ = nullptr;
|
||||
|
@ -113,4 +105,6 @@ private:
|
|||
|
||||
bool autoRotatingAnalogCW_ = false;
|
||||
bool autoRotatingAnalogCCW_ = false;
|
||||
|
||||
ControlMapper controlMapper_;
|
||||
};
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include "Common/OSVersion.h"
|
||||
#include "Common/GPU/ShaderTranslation.h"
|
||||
|
||||
#include "Core/ControlMapper.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Core.h"
|
||||
|
@ -1326,35 +1327,6 @@ bool NativeKey(const KeyInput &key) {
|
|||
return retval;
|
||||
}
|
||||
|
||||
static float MapAxisValue(float v) {
|
||||
const float deadzone = g_Config.fAnalogDeadzone;
|
||||
const float invDeadzone = g_Config.fAnalogInverseDeadzone;
|
||||
const float sensitivity = g_Config.fAnalogSensitivity;
|
||||
const float sign = v >= 0.0f ? 1.0f : -1.0f;
|
||||
return sign * Clamp(invDeadzone + (abs(v) - deadzone) / (1.0f - deadzone) * (sensitivity - invDeadzone), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static void ConvertAnalogStick(float &x, float &y) {
|
||||
const bool isCircular = g_Config.bAnalogIsCircular;
|
||||
|
||||
float norm = std::max(fabsf(x), fabsf(y));
|
||||
|
||||
if (norm == 0.0f)
|
||||
return;
|
||||
|
||||
if (isCircular) {
|
||||
float newNorm = sqrtf(x * x + y * y);
|
||||
float factor = newNorm / norm;
|
||||
x *= factor;
|
||||
y *= factor;
|
||||
norm = newNorm;
|
||||
}
|
||||
|
||||
float mappedNorm = MapAxisValue(norm);
|
||||
x = Clamp(x / norm * mappedNorm, -1.0f, 1.0f);
|
||||
y = Clamp(y / norm * mappedNorm, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
static bool AnalogStickAxis(const AxisInput &axis) {
|
||||
static float history[JOYSTICK_AXIS_MAX+1] = { 0.0f };
|
||||
|
||||
|
|
|
@ -382,6 +382,7 @@
|
|||
<ClInclude Include="..\..\Core\AVIDump.h" />
|
||||
<ClInclude Include="..\..\Core\Compatibility.h" />
|
||||
<ClInclude Include="..\..\Core\Config.h" />
|
||||
<ClInclude Include="..\..\Core\ControlMapper.h" />
|
||||
<ClInclude Include="..\..\Core\Core.h" />
|
||||
<ClInclude Include="..\..\Core\CoreParameter.h" />
|
||||
<ClInclude Include="..\..\Core\CoreTiming.h" />
|
||||
|
@ -616,6 +617,7 @@
|
|||
<ClCompile Include="..\..\Core\AVIDump.cpp" />
|
||||
<ClCompile Include="..\..\Core\Compatibility.cpp" />
|
||||
<ClCompile Include="..\..\Core\Config.cpp" />
|
||||
<ClCompile Include="..\..\Core\ControlMapper.cpp" />
|
||||
<ClCompile Include="..\..\Core\Core.cpp" />
|
||||
<ClCompile Include="..\..\Core\CoreTiming.cpp" />
|
||||
<ClCompile Include="..\..\Core\CwCheat.cpp" />
|
||||
|
|
|
@ -1021,9 +1021,6 @@
|
|||
<ClCompile Include="..\..\ext\libzip\zip_pkware.c">
|
||||
<Filter>Ext\libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\libzip\zip_mkstempm.c">
|
||||
<Filter>Ext\libzip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\libzip\zip_libzip_version.c">
|
||||
<Filter>Ext\libzip</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1110,6 +1107,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\KeyMap.cpp" />
|
||||
<ClCompile Include="..\..\Core\ThreadPools.cpp" />
|
||||
<ClCompile Include="..\..\Core\ControlMapper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
|
@ -1748,6 +1746,7 @@
|
|||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\KeyMap.h" />
|
||||
<ClInclude Include="..\..\Core\ThreadPools.h" />
|
||||
<ClInclude Include="..\..\Core\ControlMapper.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\ext\gason\LICENSE">
|
||||
|
|
|
@ -378,6 +378,7 @@ EXEC_AND_LIB_FILES := \
|
|||
$(SRC)/Core/HW/SasAudio.cpp.arm \
|
||||
$(SRC)/Core/HW/SasReverb.cpp.arm \
|
||||
$(SRC)/Core/HW/StereoResampler.cpp.arm \
|
||||
$(SRC)/Core/ControlMapper.cpp \
|
||||
$(SRC)/Core/Core.cpp \
|
||||
$(SRC)/Core/Compatibility.cpp \
|
||||
$(SRC)/Core/Config.cpp \
|
||||
|
|
|
@ -427,6 +427,7 @@ SOURCES_CXX += \
|
|||
$(EXTDIR)/jpge/jpge.cpp \
|
||||
$(COREDIR)/AVIDump.cpp \
|
||||
$(COREDIR)/Config.cpp \
|
||||
$(COREDIR)/ControlMapper.cpp \
|
||||
$(COREDIR)/TextureReplacer.cpp \
|
||||
$(COREDIR)/Core.cpp \
|
||||
$(COREDIR)/WaveFile.cpp \
|
||||
|
|
Loading…
Add table
Reference in a new issue