Cocoa Port: Refactor out more input-related stuff into some new files -- ClientInputHandler.cpp/.h.

This commit is contained in:
rogerman 2017-09-11 23:32:30 -07:00
parent cb4ecbe17e
commit d0f16193c5
20 changed files with 1493 additions and 1211 deletions

View File

@ -18,38 +18,22 @@
#include <mach/mach.h>
#include <mach/mach_time.h>
#include "NDSSystem.h"
#include "GPU.h"
#include "movie.h"
#include "rtc.h"
#include "slot2.h"
#include "../../GPU.h"
#include "../../movie.h"
#include "../../NDSSystem.h"
#include "../../rtc.h"
#include "audiosamplegenerator.h"
#include "ClientExecutionControl.h"
ClientExecutionControl::ClientExecutionControl()
{
_nullSampleGenerator = new NullGenerator;
_internalNoiseGenerator = new InternalNoiseGenerator;
_whiteNoiseGenerator = new WhiteNoiseGenerator;
_sineWaveGenerator = new SineWaveGenerator(250.0, MIC_SAMPLE_RATE);
_selectedAudioFileGenerator = NULL;
_inputHandler = NULL;
_newSettingsPendingOnReset = true;
_newSettingsPendingOnExecutionLoopStart = true;
_newSettingsPendingOnNDSExec = true;
_enableAutohold = false;
_touchLocXPending = _touchLocXProcessing = _touchLocXApplied = 0;
_touchLocYPending = _touchLocYProcessing = _touchLocYApplied = 0;
_touchPressurePending = _touchPressureProcessing = _touchPressureApplied = 50;
_paddleValuePending = _paddleValueProcessing = _paddleValueApplied = 0;
_paddleAdjustPending = _paddleAdjustProcessing = _paddleAdjustApplied = 0;
_softwareMicSampleGeneratorPending = _softwareMicSampleGeneratorProcessing = _softwareMicSampleGeneratorApplied = _nullSampleGenerator;
_needResetFramesToSkip = false;
_frameTime = 0.0;
@ -102,65 +86,9 @@ ClientExecutionControl::ClientExecutionControl()
_cpuEmulationEngineNameOut = _ndsFrameInfo.cpuEmulationEngineName;
_slot1DeviceNameOut = _ndsFrameInfo.slot1DeviceName;
memset(_clientInputPending, 0, sizeof(_clientInputPending));
memset(_clientInputProcessing, 0, sizeof(_clientInputProcessing));
memset(_clientInputApplied, 0, sizeof(_clientInputApplied));
_userInputMap[NDSInputID_Debug] = 0;
_userInputMap[NDSInputID_R] = 1;
_userInputMap[NDSInputID_L] = 2;
_userInputMap[NDSInputID_X] = 3;
_userInputMap[NDSInputID_Y] = 4;
_userInputMap[NDSInputID_A] = 5;
_userInputMap[NDSInputID_B] = 6;
_userInputMap[NDSInputID_Start] = 7;
_userInputMap[NDSInputID_Select] = 8;
_userInputMap[NDSInputID_Up] = 9;
_userInputMap[NDSInputID_Down] = 10;
_userInputMap[NDSInputID_Left] = 11;
_userInputMap[NDSInputID_Right] = 12;
_userInputMap[NDSInputID_Lid] = 13;
_inputStateBitMap[NDSInputID_A] = NDSInputStateBit_A;
_inputStateBitMap[NDSInputID_B] = NDSInputStateBit_B;
_inputStateBitMap[NDSInputID_Select] = NDSInputStateBit_Select;
_inputStateBitMap[NDSInputID_Start] = NDSInputStateBit_Start;
_inputStateBitMap[NDSInputID_Right] = NDSInputStateBit_Right;
_inputStateBitMap[NDSInputID_Left] = NDSInputStateBit_Left;
_inputStateBitMap[NDSInputID_Up] = NDSInputStateBit_Up;
_inputStateBitMap[NDSInputID_Down] = NDSInputStateBit_Down;
_inputStateBitMap[NDSInputID_R] = NDSInputStateBit_R;
_inputStateBitMap[NDSInputID_L] = NDSInputStateBit_L;
_inputStateBitMap[NDSInputID_X] = NDSInputStateBit_X;
_inputStateBitMap[NDSInputID_Y] = NDSInputStateBit_Y;
_inputStateBitMap[NDSInputID_Debug] = NDSInputStateBit_Debug;
_inputStateBitMap[NDSInputID_Touch] = NDSInputStateBit_Touch;
_inputStateBitMap[NDSInputID_Lid] = NDSInputStateBit_Lid;
_inputStateBitMap[NDSInputID_Piano_C] = NDSInputStateBit_Piano_C;
_inputStateBitMap[NDSInputID_Piano_CSharp] = NDSInputStateBit_Piano_CSharp;
_inputStateBitMap[NDSInputID_Piano_D] = NDSInputStateBit_Piano_D;
_inputStateBitMap[NDSInputID_Piano_DSharp] = NDSInputStateBit_Piano_DSharp;
_inputStateBitMap[NDSInputID_Piano_E] = NDSInputStateBit_Piano_E;
_inputStateBitMap[NDSInputID_Piano_F] = NDSInputStateBit_Piano_F;
_inputStateBitMap[NDSInputID_Piano_FSharp] = NDSInputStateBit_Piano_FSharp;
_inputStateBitMap[NDSInputID_Piano_G] = NDSInputStateBit_Piano_G;
_inputStateBitMap[NDSInputID_Piano_GSharp] = NDSInputStateBit_Piano_GSharp;
_inputStateBitMap[NDSInputID_Piano_A] = NDSInputStateBit_Piano_A;
_inputStateBitMap[NDSInputID_Piano_ASharp] = NDSInputStateBit_Piano_ASharp;
_inputStateBitMap[NDSInputID_Piano_B] = NDSInputStateBit_Piano_B;
_inputStateBitMap[NDSInputID_Piano_HighC] = NDSInputStateBit_Piano_HighC;
_inputStateBitMap[NDSInputID_GuitarGrip_Green] = NDSInputStateBit_GuitarGrip_Green;
_inputStateBitMap[NDSInputID_GuitarGrip_Red] = NDSInputStateBit_GuitarGrip_Red;
_inputStateBitMap[NDSInputID_GuitarGrip_Yellow] = NDSInputStateBit_GuitarGrip_Yellow;
_inputStateBitMap[NDSInputID_GuitarGrip_Blue] = NDSInputStateBit_GuitarGrip_Blue;
_inputStateBitMap[NDSInputID_Paddle] = NDSInputStateBit_Paddle;
_inputStateBitMap[NDSInputID_Microphone] = NDSInputStateBit_Microphone;
_inputStateBitMap[NDSInputID_Reset] = NDSInputStateBit_Reset;
pthread_mutex_init(&_mutexSettingsPendingOnReset, NULL);
pthread_mutex_init(&_mutexSettingsPendingOnExecutionLoopStart, NULL);
pthread_mutex_init(&_mutexSettingsPendingOnNDSExec, NULL);
pthread_mutex_init(&_mutexInputsPending, NULL);
pthread_mutex_init(&_mutexOutputPostNDSExec, NULL);
}
@ -169,13 +97,17 @@ ClientExecutionControl::~ClientExecutionControl()
pthread_mutex_destroy(&this->_mutexSettingsPendingOnReset);
pthread_mutex_destroy(&this->_mutexSettingsPendingOnExecutionLoopStart);
pthread_mutex_destroy(&this->_mutexSettingsPendingOnNDSExec);
pthread_mutex_destroy(&this->_mutexInputsPending);
pthread_mutex_destroy(&this->_mutexOutputPostNDSExec);
delete this->_nullSampleGenerator;
delete this->_internalNoiseGenerator;
delete this->_whiteNoiseGenerator;
delete this->_sineWaveGenerator;
}
ClientInputHandler* ClientExecutionControl::GetClientInputHandler()
{
return this->_inputHandler;
}
void ClientExecutionControl::SetClientInputHandler(ClientInputHandler *inputHandler)
{
this->_inputHandler = inputHandler;
}
CPUEmulationEngineID ClientExecutionControl::GetCPUEmulationEngineID()
@ -956,406 +888,6 @@ void ClientExecutionControl::ApplySettingsOnNDSExec()
}
}
bool ClientExecutionControl::GetEnableAutohold()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const bool enable = this->_enableAutohold;
pthread_mutex_unlock(&this->_mutexInputsPending);
return enable;
}
void ClientExecutionControl::SetEnableAutohold(bool enable)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_enableAutohold = enable;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientExecutionControl::ClearAutohold()
{
pthread_mutex_lock(&this->_mutexInputsPending);
for (size_t i = 0; i < NDSInputID_InputCount; i++)
{
this->_clientInputPending[i].autohold = false;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientExecutionControl::SetClientInputStateUsingID(NDSInputID inputID, bool pressedState)
{
this->SetClientInputStateUsingID(inputID, pressedState, false, 0, 0);
}
void ClientExecutionControl::SetClientInputStateUsingID(NDSInputID inputID, bool pressedState, bool isTurboEnabled, uint32_t turboPattern, uint32_t turboPatternLength)
{
if (inputID >= NDSInputID_InputCount)
{
return;
}
pthread_mutex_lock(&this->_mutexInputsPending);
if (this->_enableAutohold && pressedState)
{
this->_clientInputPending[inputID].autohold = true;
}
this->_clientInputPending[inputID].isPressed = pressedState;
this->_clientInputPending[inputID].turbo = isTurboEnabled;
this->_clientInputPending[inputID].turboPattern = turboPattern;
this->_clientInputPending[inputID].turboPatternLength = (turboPatternLength > 32) ? 32 : turboPatternLength;
const uint64_t bitValue = (1 << _inputStateBitMap[inputID]);
this->_ndsFrameInfo.inputStatesPending.value = (this->_clientInputPending[inputID].isPressed) ? this->_ndsFrameInfo.inputStatesPending.value & ~bitValue : this->_ndsFrameInfo.inputStatesPending.value | bitValue;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientExecutionControl::SetClientTouchState(bool pressedState, uint8_t touchLocX, uint8_t touchLocY, uint8_t touchPressure)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_clientInputPending[NDSInputID_Touch].isPressed = pressedState;
this->_touchLocXPending = touchLocX;
this->_touchLocYPending = touchLocY;
this->_touchPressurePending = touchPressure;
this->_ndsFrameInfo.inputStatesPending.Touch = (this->_clientInputPending[NDSInputID_Touch].isPressed) ? 0 : 1;
this->_ndsFrameInfo.touchLocXPending = this->_touchLocXPending;
this->_ndsFrameInfo.touchLocYPending = this->_touchLocYPending;
this->_ndsFrameInfo.touchPressurePending = this->_touchPressurePending;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
double ClientExecutionControl::GetSineWaveFrequency()
{
return this->_sineWaveGenerator->getFrequency();
}
void ClientExecutionControl::SetSineWaveFrequency(double freq)
{
this->_sineWaveGenerator->setFrequency(freq);
}
AudioGenerator* ClientExecutionControl::GetClientSoftwareMicSampleGenerator()
{
pthread_mutex_lock(&this->_mutexInputsPending);
AudioGenerator *softwareMicSampleGenerator = this->_softwareMicSampleGeneratorPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
return softwareMicSampleGenerator;
}
AudioGenerator* ClientExecutionControl::GetClientSoftwareMicSampleGeneratorApplied()
{
return this->_softwareMicSampleGeneratorApplied;
}
AudioSampleBlockGenerator* ClientExecutionControl::GetClientSelectedAudioFileGenerator()
{
pthread_mutex_lock(&this->_mutexInputsPending);
AudioSampleBlockGenerator *selectedAudioFileGenerator = this->_selectedAudioFileGenerator;
pthread_mutex_unlock(&this->_mutexInputsPending);
return selectedAudioFileGenerator;
}
void ClientExecutionControl::SetClientSelectedAudioFileGenerator(AudioSampleBlockGenerator *selectedAudioFileGenerator)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_selectedAudioFileGenerator = selectedAudioFileGenerator;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
bool ClientExecutionControl::GetClientSoftwareMicState()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const bool isPressed = this->_clientInputPending[NDSInputID_Microphone].isPressed;
pthread_mutex_unlock(&this->_mutexInputsPending);
return isPressed;
}
bool ClientExecutionControl::GetClientSoftwareMicStateApplied()
{
return this->_clientInputApplied[NDSInputID_Microphone].isPressed;
}
void ClientExecutionControl::SetClientSoftwareMicState(bool pressedState, MicrophoneMode micMode)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_clientInputPending[NDSInputID_Microphone].isPressed = pressedState;
this->_ndsFrameInfo.inputStatesPending.Microphone = (this->_clientInputPending[NDSInputID_Microphone].isPressed) ? 0 : 1;
if (pressedState)
{
switch (micMode)
{
case MicrophoneMode_InternalNoise:
this->_softwareMicSampleGeneratorPending = this->_internalNoiseGenerator;
break;
case MicrophoneMode_WhiteNoise:
this->_softwareMicSampleGeneratorPending = this->_whiteNoiseGenerator;
break;
case MicrophoneMode_SineWave:
this->_softwareMicSampleGeneratorPending = this->_sineWaveGenerator;
break;
case MicrophoneMode_AudioFile:
if (this->_selectedAudioFileGenerator != NULL)
{
this->_softwareMicSampleGeneratorPending = this->_selectedAudioFileGenerator;
}
break;
default:
this->_softwareMicSampleGeneratorPending = this->_nullSampleGenerator;
break;
}
}
else
{
this->_softwareMicSampleGeneratorPending = this->_nullSampleGenerator;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
int16_t ClientExecutionControl::GetClientPaddleAdjust()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const int16_t paddleAdjust = this->_paddleAdjustPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
return paddleAdjust;
}
void ClientExecutionControl::SetClientPaddleAdjust(int16_t paddleAdjust)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_paddleAdjustPending = paddleAdjust;
this->_paddleValuePending = this->_paddleValueApplied + paddleAdjust;
this->_ndsFrameInfo.paddleValuePending = this->_paddleValuePending;
this->_ndsFrameInfo.paddleAdjustPending = this->_paddleAdjustPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientExecutionControl::ProcessInputs()
{
// Before we begin input processing, we need to send all pending inputs to the core code.
pthread_mutex_lock(&this->_mutexInputsPending);
NDS_setPad(this->_clientInputPending[NDSInputID_Right].isPressed,
this->_clientInputPending[NDSInputID_Left].isPressed,
this->_clientInputPending[NDSInputID_Down].isPressed,
this->_clientInputPending[NDSInputID_Up].isPressed,
this->_clientInputPending[NDSInputID_Select].isPressed,
this->_clientInputPending[NDSInputID_Start].isPressed,
this->_clientInputPending[NDSInputID_B].isPressed,
this->_clientInputPending[NDSInputID_A].isPressed,
this->_clientInputPending[NDSInputID_Y].isPressed,
this->_clientInputPending[NDSInputID_X].isPressed,
this->_clientInputPending[NDSInputID_L].isPressed,
this->_clientInputPending[NDSInputID_R].isPressed,
this->_clientInputPending[NDSInputID_Debug].isPressed,
this->_clientInputPending[NDSInputID_Lid].isPressed);
if (this->_clientInputPending[NDSInputID_Touch].isPressed)
{
NDS_setTouchPos((u16)this->_touchLocXPending, (u16)this->_touchLocYPending);
}
else
{
NDS_releaseTouch();
}
NDS_setMic(this->_clientInputPending[NDSInputID_Microphone].isPressed);
// Copy all pending inputs for further processing.
for (size_t i = 0; i < NDSInputID_InputCount; i++)
{
this->_clientInputProcessing[i].isPressed = this->_clientInputPending[i].isPressed;
this->_clientInputProcessing[i].autohold = this->_clientInputPending[i].autohold;
this->_clientInputProcessing[i].turbo = this->_clientInputPending[i].turbo;
if ( (this->_clientInputProcessing[i].turboPattern != this->_clientInputPending[i].turboPattern) ||
(this->_clientInputProcessing[i].turboPatternLength != this->_clientInputPending[i].turboPatternLength) )
{
this->_clientInputProcessing[i].turboPatternStep = 0;
this->_clientInputProcessing[i].turboPattern = this->_clientInputPending[i].turboPattern;
this->_clientInputProcessing[i].turboPatternLength = this->_clientInputPending[i].turboPatternLength;
}
}
this->_touchLocXProcessing = this->_touchLocXPending;
this->_touchLocYProcessing = this->_touchLocYPending;
this->_touchPressureProcessing = this->_touchPressurePending;
this->_paddleAdjustProcessing = this->_paddleAdjustPending;
this->_paddleValueProcessing = this->_paddleValuePending;
this->_softwareMicSampleGeneratorProcessing = this->_softwareMicSampleGeneratorPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
// Begin processing the input based on current parameters.
NDS_beginProcessingInput();
UserInput &processedInput = NDS_getProcessingUserInput();
if (movieMode == MOVIEMODE_PLAY)
{
FCEUMOV_HandlePlayback();
this->_clientInputProcessing[NDSInputID_A].isPressed = processedInput.buttons.A;
this->_clientInputProcessing[NDSInputID_B].isPressed = processedInput.buttons.B;
this->_clientInputProcessing[NDSInputID_Select].isPressed = processedInput.buttons.T;
this->_clientInputProcessing[NDSInputID_Start].isPressed = processedInput.buttons.S;
this->_clientInputProcessing[NDSInputID_Right].isPressed = processedInput.buttons.R;
this->_clientInputProcessing[NDSInputID_Left].isPressed = processedInput.buttons.L;
this->_clientInputProcessing[NDSInputID_Up].isPressed = processedInput.buttons.U;
this->_clientInputProcessing[NDSInputID_Down].isPressed = processedInput.buttons.D;
this->_clientInputProcessing[NDSInputID_R].isPressed = processedInput.buttons.E;
this->_clientInputProcessing[NDSInputID_L].isPressed = processedInput.buttons.W;
this->_clientInputProcessing[NDSInputID_X].isPressed = processedInput.buttons.X;
this->_clientInputProcessing[NDSInputID_Y].isPressed = processedInput.buttons.Y;
this->_clientInputProcessing[NDSInputID_Debug].isPressed = processedInput.buttons.G;
this->_clientInputProcessing[NDSInputID_Touch].isPressed = processedInput.touch.isTouch;
this->_clientInputProcessing[NDSInputID_Lid].isPressed = processedInput.buttons.F;
this->_clientInputProcessing[NDSInputID_Microphone].isPressed = (processedInput.mic.micButtonPressed != 0);
this->_touchLocXProcessing = processedInput.touch.touchX >> 4;
this->_touchLocYProcessing = processedInput.touch.touchY >> 4;
}
else
{
if (this->GetExecutionBehaviorApplied() != ExecutionBehavior_FrameJump)
{
size_t i = 0;
// First process the inputs that exist in the core code's UserInput struct. The core code will
// use this struct for its own purposes later.
for (; i <= NDSInputID_Lid; i++)
{
bool &pressedState = (i != NDSInputID_Touch) ? processedInput.buttons.array[this->_userInputMap[(NDSInputID)i]] : processedInput.touch.isTouch;
pressedState = (this->_clientInputProcessing[i].isPressed || this->_clientInputProcessing[i].autohold);
this->_clientInputProcessing[i].isPressed = pressedState;
if (this->_clientInputProcessing[i].turbo)
{
const bool turboPressedState = ( ((this->_clientInputProcessing[i].turboPattern >> this->_clientInputProcessing[i].turboPatternStep) & 0x00000001) == 1 );
pressedState = (pressedState && turboPressedState);
this->_clientInputProcessing[i].isPressed = pressedState;
this->_clientInputProcessing[i].turboPatternStep++;
if (this->_clientInputProcessing[i].turboPatternStep >= this->_clientInputProcessing[i].turboPatternLength)
{
this->_clientInputProcessing[i].turboPatternStep = 0;
}
}
}
// Process the remaining inputs.
for (i = NDSInputID_Piano_C; i < NDSInputID_InputCount; i++)
{
bool &pressedState = this->_clientInputProcessing[i].isPressed;
pressedState = (this->_clientInputProcessing[i].isPressed || this->_clientInputProcessing[i].autohold);
if (this->_clientInputProcessing[i].turbo)
{
const bool turboPressedState = ( ((this->_clientInputProcessing[i].turboPattern >> this->_clientInputProcessing[i].turboPatternStep) & 0x00000001) == 1 );
pressedState = (pressedState && turboPressedState);
this->_clientInputProcessing[i].turboPatternStep++;
if (this->_clientInputProcessing[i].turboPatternStep >= this->_clientInputProcessing[i].turboPatternLength)
{
this->_clientInputProcessing[i].turboPatternStep = 0;
}
}
}
}
else
{
memset(&processedInput, 0, sizeof(UserInput));
memset(this->_clientInputProcessing, 0, sizeof(this->_clientInputProcessing));
this->_softwareMicSampleGeneratorProcessing = this->_nullSampleGenerator;
}
}
}
void ClientExecutionControl::ApplyInputs()
{
NDS_endProcessingInput();
this->_touchLocXApplied = this->_touchLocXProcessing;
this->_touchLocYApplied = this->_touchLocYProcessing;
this->_touchPressureApplied = this->_touchPressureProcessing;
this->_paddleAdjustApplied = this->_paddleAdjustProcessing;
this->_paddleValueApplied = this->_paddleValueProcessing;
memcpy(this->_clientInputApplied, this->_clientInputProcessing, sizeof(this->_clientInputProcessing));
CommonSettings.StylusPressure = (int)this->_touchPressureApplied;
this->_softwareMicSampleGeneratorApplied = this->_softwareMicSampleGeneratorProcessing;
if (!this->_clientInputApplied[NDSInputID_Microphone].isPressed)
{
this->_internalNoiseGenerator->setSamplePosition(0);
this->_sineWaveGenerator->setCyclePosition(0.0);
if (this->_selectedAudioFileGenerator != NULL)
{
this->_selectedAudioFileGenerator->setSamplePosition(0);
}
}
// Setup the inputs from SLOT-2 devices.
const NDS_SLOT2_TYPE slot2DeviceType = slot2_GetSelectedType();
switch (slot2DeviceType)
{
case NDS_SLOT2_GUITARGRIP:
guitarGrip_setKey(this->_clientInputApplied[NDSInputID_GuitarGrip_Green].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Red].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Yellow].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Blue].isPressed);
break;
case NDS_SLOT2_EASYPIANO:
piano_setKey(this->_clientInputApplied[NDSInputID_Piano_C].isPressed,
this->_clientInputApplied[NDSInputID_Piano_CSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_D].isPressed,
this->_clientInputApplied[NDSInputID_Piano_DSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_E].isPressed,
this->_clientInputApplied[NDSInputID_Piano_F].isPressed,
this->_clientInputApplied[NDSInputID_Piano_FSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_G].isPressed,
this->_clientInputApplied[NDSInputID_Piano_GSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_A].isPressed,
this->_clientInputApplied[NDSInputID_Piano_ASharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_B].isPressed,
this->_clientInputApplied[NDSInputID_Piano_HighC].isPressed);
break;
case NDS_SLOT2_PADDLE:
Paddle_SetValue((uint16_t)this->_paddleValueApplied);
break;
default:
break;
}
if (movieMode == MOVIEMODE_RECORD)
{
FCEUMOV_HandleRecording();
}
}
void ClientExecutionControl::FetchOutputPostNDSExec()
{
pthread_mutex_lock(&this->_mutexOutputPostNDSExec);
@ -1375,46 +907,52 @@ void ClientExecutionControl::FetchOutputPostNDSExec()
free(tempBuffer);
this->_ndsFrameInfo.inputStatesApplied.value = INPUT_STATES_CLEAR_VALUE;
this->_ndsFrameInfo.inputStatesApplied.A = (this->_clientInputApplied[NDSInputID_A].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.B = (this->_clientInputApplied[NDSInputID_B].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Select = (this->_clientInputApplied[NDSInputID_Select].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Start = (this->_clientInputApplied[NDSInputID_Start].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Right = (this->_clientInputApplied[NDSInputID_Right].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Left = (this->_clientInputApplied[NDSInputID_Left].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Up = (this->_clientInputApplied[NDSInputID_Up].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Down = (this->_clientInputApplied[NDSInputID_Down].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.R = (this->_clientInputApplied[NDSInputID_R].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.L = (this->_clientInputApplied[NDSInputID_L].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.X = (this->_clientInputApplied[NDSInputID_X].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Y = (this->_clientInputApplied[NDSInputID_Y].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Debug = (this->_clientInputApplied[NDSInputID_Debug].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Touch = (this->_clientInputApplied[NDSInputID_Touch].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Lid = (this->_clientInputApplied[NDSInputID_Lid].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoC = (this->_clientInputApplied[NDSInputID_Piano_C].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoCSharp = (this->_clientInputApplied[NDSInputID_Piano_CSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoD = (this->_clientInputApplied[NDSInputID_Piano_D].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoDSharp = (this->_clientInputApplied[NDSInputID_Piano_DSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoE = (this->_clientInputApplied[NDSInputID_Piano_E].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoF = (this->_clientInputApplied[NDSInputID_Piano_F].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoFSharp = (this->_clientInputApplied[NDSInputID_Piano_FSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoG = (this->_clientInputApplied[NDSInputID_Piano_G].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoGSharp = (this->_clientInputApplied[NDSInputID_Piano_GSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoA = (this->_clientInputApplied[NDSInputID_Piano_A].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoASharp = (this->_clientInputApplied[NDSInputID_Piano_ASharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoB = (this->_clientInputApplied[NDSInputID_Piano_B].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoHighC = (this->_clientInputApplied[NDSInputID_Piano_HighC].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripBlue = (this->_clientInputApplied[NDSInputID_GuitarGrip_Blue].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripYellow = (this->_clientInputApplied[NDSInputID_GuitarGrip_Yellow].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripRed = (this->_clientInputApplied[NDSInputID_GuitarGrip_Red].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripGreen = (this->_clientInputApplied[NDSInputID_GuitarGrip_Green].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Paddle = (this->_clientInputApplied[NDSInputID_Paddle].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Microphone = (this->_clientInputApplied[NDSInputID_Microphone].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Reset = (this->_clientInputApplied[NDSInputID_Reset].isPressed) ? 0 : 1;
this->_ndsFrameInfo.touchLocXApplied = this->_touchLocXApplied;
this->_ndsFrameInfo.touchLocYApplied = this->_touchLocYApplied;
this->_ndsFrameInfo.touchPressureApplied = this->_touchPressureApplied;
this->_ndsFrameInfo.paddleValueApplied = this->_paddleValueApplied;
this->_ndsFrameInfo.paddleAdjustApplied = this->_paddleAdjustApplied;
if (this->_inputHandler != NULL)
{
const ClientInput *appliedInput = this->_inputHandler->GetClientInputsApplied();
this->_ndsFrameInfo.inputStatesApplied.A = (appliedInput[NDSInputID_A].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.B = (appliedInput[NDSInputID_B].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Select = (appliedInput[NDSInputID_Select].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Start = (appliedInput[NDSInputID_Start].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Right = (appliedInput[NDSInputID_Right].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Left = (appliedInput[NDSInputID_Left].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Up = (appliedInput[NDSInputID_Up].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Down = (appliedInput[NDSInputID_Down].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.R = (appliedInput[NDSInputID_R].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.L = (appliedInput[NDSInputID_L].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.X = (appliedInput[NDSInputID_X].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Y = (appliedInput[NDSInputID_Y].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Debug = (appliedInput[NDSInputID_Debug].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Touch = (appliedInput[NDSInputID_Touch].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Lid = (appliedInput[NDSInputID_Lid].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoC = (appliedInput[NDSInputID_Piano_C].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoCSharp = (appliedInput[NDSInputID_Piano_CSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoD = (appliedInput[NDSInputID_Piano_D].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoDSharp = (appliedInput[NDSInputID_Piano_DSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoE = (appliedInput[NDSInputID_Piano_E].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoF = (appliedInput[NDSInputID_Piano_F].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoFSharp = (appliedInput[NDSInputID_Piano_FSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoG = (appliedInput[NDSInputID_Piano_G].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoGSharp = (appliedInput[NDSInputID_Piano_GSharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoA = (appliedInput[NDSInputID_Piano_A].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoASharp = (appliedInput[NDSInputID_Piano_ASharp].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoB = (appliedInput[NDSInputID_Piano_B].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.PianoHighC = (appliedInput[NDSInputID_Piano_HighC].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripBlue = (appliedInput[NDSInputID_GuitarGrip_Blue].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripYellow = (appliedInput[NDSInputID_GuitarGrip_Yellow].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripRed = (appliedInput[NDSInputID_GuitarGrip_Red].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.GuitarGripGreen = (appliedInput[NDSInputID_GuitarGrip_Green].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Paddle = (appliedInput[NDSInputID_Paddle].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Microphone = (appliedInput[NDSInputID_Microphone].isPressed) ? 0 : 1;
this->_ndsFrameInfo.inputStatesApplied.Reset = (appliedInput[NDSInputID_Reset].isPressed) ? 0 : 1;
this->_ndsFrameInfo.touchLocXApplied = this->_inputHandler->GetTouchLocXApplied();
this->_ndsFrameInfo.touchLocYApplied = this->_inputHandler->GetTouchLocYApplied();
this->_ndsFrameInfo.touchPressureApplied = this->_inputHandler->GetTouchPressureApplied();
this->_ndsFrameInfo.paddleValueApplied = this->_inputHandler->GetPaddleValueApplied();
this->_ndsFrameInfo.paddleAdjustApplied = this->_inputHandler->GetPaddleAdjustApplied();
}
pthread_mutex_unlock(&this->_mutexOutputPostNDSExec);
}

View File

@ -22,6 +22,8 @@
#include <map>
#include <string>
#include "ClientInputHandler.h"
#include "../../slot1.h"
#undef BOOL
@ -40,18 +42,6 @@
#define FRAME_SKIP_BIAS 0.1 // May be any real number. This value acts as a vector addition to the frame skip.
#define MAX_FRAME_SKIP (DS_FRAMES_PER_SECOND / 2.98)
#define INPUT_STATES_CLEAR_VALUE 0xFFFFFFFF00FF03FFULL
#define MIC_SAMPLE_RATE 16000.0
#define MIC_SAMPLE_RESOLUTION 8 // Bits per sample; must be a multiple of 8
#define MIC_NUMBER_CHANNELS 1 // Number of channels
#define MIC_SAMPLE_SIZE ((MIC_SAMPLE_RESOLUTION / 8) * MIC_NUMBER_CHANNELS) // Bytes per sample, multiplied by the number of channels
#define MIC_MAX_BUFFER_SAMPLES ((MIC_SAMPLE_RATE / DS_FRAMES_PER_SECOND) * MIC_SAMPLE_SIZE)
#define MIC_CAPTURE_FRAMES 192 // The number of audio frames that the NDS microphone should pull. The lower this value, the lower the latency. Ensure that this value is not too low, or else audio frames may be lost.
#define MIC_NULL_LEVEL_THRESHOLD 2.5
#define MIC_CLIP_LEVEL_THRESHOLD 39.743665431525209 // ((2.0/pi) * MIC_NULL_SAMPLE_VALUE) - 1.0
#define MIC_NULL_SAMPLE_VALUE 64
enum ExecutionBehavior
{
ExecutionBehavior_Pause = 0,
@ -73,248 +63,6 @@ enum CPUEmulationEngineID
CPUEmulationEngineID_DynamicRecompiler = 1
};
enum NDSInputID
{
NDSInputID_A = 0,
NDSInputID_B,
NDSInputID_Select,
NDSInputID_Start,
NDSInputID_Right,
NDSInputID_Left,
NDSInputID_Up,
NDSInputID_Down,
NDSInputID_R,
NDSInputID_L,
NDSInputID_X,
NDSInputID_Y,
NDSInputID_Debug,
NDSInputID_Touch,
NDSInputID_Lid,
NDSInputID_Piano_C,
NDSInputID_Piano_CSharp,
NDSInputID_Piano_D,
NDSInputID_Piano_DSharp,
NDSInputID_Piano_E,
NDSInputID_Piano_F,
NDSInputID_Piano_FSharp,
NDSInputID_Piano_G,
NDSInputID_Piano_GSharp,
NDSInputID_Piano_A,
NDSInputID_Piano_ASharp,
NDSInputID_Piano_B,
NDSInputID_Piano_HighC,
NDSInputID_GuitarGrip_Green,
NDSInputID_GuitarGrip_Red,
NDSInputID_GuitarGrip_Yellow,
NDSInputID_GuitarGrip_Blue,
NDSInputID_Paddle,
NDSInputID_Microphone,
NDSInputID_Reset,
NDSInputID_InputCount
};
enum NDSInputStateBit
{
NDSInputStateBit_A = 0,
NDSInputStateBit_B = 1,
NDSInputStateBit_Select = 2,
NDSInputStateBit_Start = 3,
NDSInputStateBit_Right = 4,
NDSInputStateBit_Left = 5,
NDSInputStateBit_Up = 6,
NDSInputStateBit_Down = 7,
NDSInputStateBit_R = 8,
NDSInputStateBit_L = 9,
NDSInputStateBit_X = 16,
NDSInputStateBit_Y = 17,
NDSInputStateBit_Debug = 19,
NDSInputStateBit_Touch = 22,
NDSInputStateBit_Lid = 23,
NDSInputStateBit_Piano_C = 32,
NDSInputStateBit_Piano_CSharp = 33,
NDSInputStateBit_Piano_D = 34,
NDSInputStateBit_Piano_DSharp = 35,
NDSInputStateBit_Piano_E = 36,
NDSInputStateBit_Piano_F = 37,
NDSInputStateBit_Piano_FSharp = 38,
NDSInputStateBit_Piano_G = 39,
NDSInputStateBit_Piano_GSharp = 40,
NDSInputStateBit_Piano_A = 41,
NDSInputStateBit_Piano_ASharp = 42,
NDSInputStateBit_Piano_B = 45,
NDSInputStateBit_Piano_HighC = 46,
NDSInputStateBit_GuitarGrip_Green = 51,
NDSInputStateBit_GuitarGrip_Red = 52,
NDSInputStateBit_GuitarGrip_Yellow = 53,
NDSInputStateBit_GuitarGrip_Blue = 54,
NDSInputStateBit_Paddle = 56,
NDSInputStateBit_Microphone = 57,
NDSInputStateBit_Reset = 58
};
enum MicrophoneMode
{
MicrophoneMode_None = 0,
MicrophoneMode_InternalNoise,
MicrophoneMode_AudioFile,
MicrophoneMode_WhiteNoise,
MicrophoneMode_Physical,
MicrophoneMode_SineWave
};
class AudioGenerator;
class NullGenerator;
class InternalNoiseGenerator;
class WhiteNoiseGenerator;
class SineWaveGenerator;
class AudioSampleBlockGenerator;
typedef std::map<NDSInputID, size_t> NDSUserInputMap;
typedef std::map<NDSInputID, NDSInputStateBit> NDSInputStateBitMap;
typedef union
{
uint64_t value;
struct
{
uint16_t gbaKeys;
uint16_t ndsKeysExt;
uint16_t easyPianoKeys;
uint8_t guitarGripKeys;
uint8_t miscKeys;
};
struct
{
#ifndef MSB_FIRST
uint8_t A:1;
uint8_t B:1;
uint8_t Select:1;
uint8_t Start:1;
uint8_t Right:1;
uint8_t Left:1;
uint8_t Up:1;
uint8_t Down:1;
uint8_t R:1;
uint8_t L:1;
uint8_t :6;
uint8_t X:1;
uint8_t Y:1;
uint8_t :1;
uint8_t Debug:1;
uint8_t :2;
uint8_t Touch:1;
uint8_t Lid:1;
uint8_t :8;
uint8_t PianoC:1;
uint8_t PianoCSharp:1;
uint8_t PianoD:1;
uint8_t PianoDSharp:1;
uint8_t PianoE:1;
uint8_t PianoF:1;
uint8_t PianoFSharp:1;
uint8_t PianoG:1;
uint8_t PianoGSharp:1;
uint8_t PianoA:1;
uint8_t PianoASharp:1;
uint8_t :2;
uint8_t PianoB:1;
uint8_t PianoHighC:1;
uint8_t :1;
uint8_t :3;
uint8_t GuitarGripBlue:1;
uint8_t GuitarGripYellow:1;
uint8_t GuitarGripRed:1;
uint8_t GuitarGripGreen:1;
uint8_t :1;
uint8_t Paddle:1;
uint8_t Microphone:1;
uint8_t Reset:1;
uint8_t :5;
#else
uint8_t Down:1;
uint8_t Up:1;
uint8_t Left:1;
uint8_t Right:1;
uint8_t Start:1;
uint8_t Select:1;
uint8_t B:1;
uint8_t A:1;
uint8_t :6;
uint8_t L:1;
uint8_t R:1;
uint8_t Lid:1;
uint8_t Touch:1;
uint8_t :2;
uint8_t Debug:1;
uint8_t :1;
uint8_t Y:1;
uint8_t X:1;
uint8_t :8;
uint8_t PianoG:1;
uint8_t PianoFSharp:1;
uint8_t PianoF:1;
uint8_t PianoE:1;
uint8_t PianoDSharp:1;
uint8_t PianoD:1;
uint8_t PianoCSharp:1;
uint8_t PianoC:1;
uint8_t :1;
uint8_t PianoHighC:1;
uint8_t PianoB:1;
uint8_t :2;
uint8_t PianoASharp:1;
uint8_t PianoA:1;
uint8_t PianoGSharp:1;
uint8_t :1;
uint8_t GuitarGripGreen:1;
uint8_t GuitarGripRed:1;
uint8_t GuitarGripYellow:1;
uint8_t GuitarGripBlue:1;
uint8_t :3;
uint8_t :5;
uint8_t Reset:1;
uint8_t Microphone:1;
uint8_t Paddle:1;
#endif
};
} NDSInputState; // Each bit represents the Pressed/Released state of a single input. Pressed=0, Released=1
struct ClientInput
{
bool isPressed;
bool turbo;
bool autohold;
uint32_t turboPattern;
uint8_t turboPatternStep;
uint8_t turboPatternLength;
};
typedef struct ClientInput ClientInput;
struct ClientExecutionControlSettings
{
CPUEmulationEngineID cpuEngineID;
@ -435,51 +183,18 @@ struct NDSFrameInfo
class ClientExecutionControl
{
private:
NDSUserInputMap _userInputMap;
NDSInputStateBitMap _inputStateBitMap;
AudioGenerator *_softwareMicSampleGeneratorPending;
AudioGenerator *_softwareMicSampleGeneratorProcessing;
AudioGenerator *_softwareMicSampleGeneratorApplied;
NullGenerator *_nullSampleGenerator;
InternalNoiseGenerator *_internalNoiseGenerator;
WhiteNoiseGenerator *_whiteNoiseGenerator;
SineWaveGenerator *_sineWaveGenerator;
AudioSampleBlockGenerator *_selectedAudioFileGenerator;
protected:
ClientInputHandler *_inputHandler;
ClientExecutionControlSettings _settingsPending;
ClientExecutionControlSettings _settingsApplied;
NDSFrameInfo _ndsFrameInfo;
ClientInput _clientInputPending[NDSInputID_InputCount];
ClientInput _clientInputProcessing[NDSInputID_InputCount];
ClientInput _clientInputApplied[NDSInputID_InputCount];
bool _newSettingsPendingOnReset;
bool _newSettingsPendingOnExecutionLoopStart;
bool _newSettingsPendingOnNDSExec;
bool _enableAutohold;
uint8_t _touchLocXPending;
uint8_t _touchLocYPending;
uint8_t _touchPressurePending;
int16_t _paddleValuePending;
int16_t _paddleAdjustPending;
uint8_t _touchLocXProcessing;
uint8_t _touchLocYProcessing;
uint8_t _touchPressureProcessing;
int16_t _paddleValueProcessing;
int16_t _paddleAdjustProcessing;
uint8_t _touchLocXApplied;
uint8_t _touchLocYApplied;
uint8_t _touchPressureApplied;
int16_t _paddleValueApplied;
int16_t _paddleAdjustApplied;
bool _needResetFramesToSkip;
double _frameTime;
@ -493,13 +208,15 @@ private:
pthread_mutex_t _mutexSettingsPendingOnReset;
pthread_mutex_t _mutexSettingsPendingOnExecutionLoopStart;
pthread_mutex_t _mutexSettingsPendingOnNDSExec;
pthread_mutex_t _mutexInputsPending;
pthread_mutex_t _mutexOutputPostNDSExec;
public:
ClientExecutionControl();
~ClientExecutionControl();
ClientInputHandler* GetClientInputHandler();
void SetClientInputHandler(ClientInputHandler *inputHandler);
CPUEmulationEngineID GetCPUEmulationEngineID();
const char* GetCPUEmulationEngineName();
void SetCPUEmulationEngineByID(CPUEmulationEngineID engineID);
@ -589,32 +306,6 @@ public:
void ApplySettingsOnExecutionLoopStart();
void ApplySettingsOnNDSExec();
bool GetEnableAutohold();
void SetEnableAutohold(bool enable);
void ClearAutohold();
void SetClientInputStateUsingID(NDSInputID inputID, bool pressedState);
void SetClientInputStateUsingID(NDSInputID inputID, bool pressedState, bool isTurboEnabled, uint32_t turboPattern, uint32_t turboPatternLength);
void SetClientTouchState(bool pressedState, uint8_t touchLocX, uint8_t touchLocY, uint8_t touchPressure);
double GetSineWaveFrequency();
void SetSineWaveFrequency(double freq);
AudioGenerator* GetClientSoftwareMicSampleGenerator();
AudioGenerator* GetClientSoftwareMicSampleGeneratorApplied();
AudioSampleBlockGenerator* GetClientSelectedAudioFileGenerator();
void SetClientSelectedAudioFileGenerator(AudioSampleBlockGenerator *selectedAudioFileGenerator);
bool GetClientSoftwareMicState();
bool GetClientSoftwareMicStateApplied();
void SetClientSoftwareMicState(bool pressedState, MicrophoneMode micMode);
int16_t GetClientPaddleAdjust();
void SetClientPaddleAdjust(int16_t paddleAdjust);
void ProcessInputs();
void ApplyInputs();
void FetchOutputPostNDSExec();
const NDSFrameInfo& GetNDSFrameInfo();
uint64_t GetFrameIndex();

View File

@ -0,0 +1,613 @@
/*
Copyright (C) 2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../../movie.h"
#include "../../NDSSystem.h"
#include "../../slot2.h"
#include "audiosamplegenerator.h"
#include "ClientExecutionControl.h"
#include "ClientInputHandler.h"
ClientInputDeviceProperties ClientInputDevicePropertiesEncoder::EncodeKeyboardInput(const int32_t keyCode, bool keyPressed)
{
ClientInputDeviceProperties inputProperty;
strncpy(inputProperty.deviceCode, "GenericClientKeyboard", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.deviceName, "Keyboard", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH, "%i", (int)keyCode);
snprintf(inputProperty.elementName, INPUT_HANDLER_STRING_LENGTH, "KeyCode %i", (int)keyCode);
inputProperty.isAnalog = false;
inputProperty.state = (keyPressed) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
inputProperty.intCoordX = 0;
inputProperty.intCoordY = 0;
inputProperty.floatCoordX = 0.0f;
inputProperty.floatCoordY = 0.0f;
inputProperty.scalar = (keyPressed) ? 1.0f : 0.0f;
inputProperty.object = NULL;
return inputProperty;
}
ClientInputDeviceProperties ClientInputDevicePropertiesEncoder::EncodeMouseInput(const int32_t buttonNumber, float touchLocX, float touchLocY, bool buttonPressed)
{
ClientInputDeviceProperties inputProperty;
strncpy(inputProperty.deviceCode, "GenericClientMouse", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.deviceName, "Mouse", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH, "%i", (int)buttonNumber);
strncpy(inputProperty.elementName, "Generic Mouse Button", INPUT_HANDLER_STRING_LENGTH);
inputProperty.isAnalog = false;
inputProperty.state = (buttonPressed) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
inputProperty.intCoordX = (int32_t)touchLocX;
inputProperty.intCoordY = (int32_t)touchLocY;
inputProperty.floatCoordX = touchLocX;
inputProperty.floatCoordY = touchLocY;
inputProperty.scalar = (buttonPressed) ? 1.0f : 0.0f;
inputProperty.object = NULL;
return inputProperty;
}
ClientInputHandler::ClientInputHandler()
{
_execControl = NULL;
_nullSampleGenerator = new NullGenerator;
_internalNoiseGenerator = new InternalNoiseGenerator;
_whiteNoiseGenerator = new WhiteNoiseGenerator;
_sineWaveGenerator = new SineWaveGenerator(250.0, MIC_SAMPLE_RATE);
_selectedAudioFileGenerator = NULL;
_enableAutohold = false;
_touchLocXPending = _touchLocXProcessing = _touchLocXApplied = 0;
_touchLocYPending = _touchLocYProcessing = _touchLocYApplied = 0;
_touchPressurePending = _touchPressureProcessing = _touchPressureApplied = 50;
_paddleValuePending = _paddleValueProcessing = _paddleValueApplied = 0;
_paddleAdjustPending = _paddleAdjustProcessing = _paddleAdjustApplied = 0;
_softwareMicSampleGeneratorPending = _softwareMicSampleGeneratorProcessing = _softwareMicSampleGeneratorApplied = _nullSampleGenerator;
memset(_clientInputPending, 0, sizeof(_clientInputPending));
memset(_clientInputProcessing, 0, sizeof(_clientInputProcessing));
memset(_clientInputApplied, 0, sizeof(_clientInputApplied));
_userInputMap[NDSInputID_Debug] = 0;
_userInputMap[NDSInputID_R] = 1;
_userInputMap[NDSInputID_L] = 2;
_userInputMap[NDSInputID_X] = 3;
_userInputMap[NDSInputID_Y] = 4;
_userInputMap[NDSInputID_A] = 5;
_userInputMap[NDSInputID_B] = 6;
_userInputMap[NDSInputID_Start] = 7;
_userInputMap[NDSInputID_Select] = 8;
_userInputMap[NDSInputID_Up] = 9;
_userInputMap[NDSInputID_Down] = 10;
_userInputMap[NDSInputID_Left] = 11;
_userInputMap[NDSInputID_Right] = 12;
_userInputMap[NDSInputID_Lid] = 13;
_inputStateBitMap[NDSInputID_A] = NDSInputStateBit_A;
_inputStateBitMap[NDSInputID_B] = NDSInputStateBit_B;
_inputStateBitMap[NDSInputID_Select] = NDSInputStateBit_Select;
_inputStateBitMap[NDSInputID_Start] = NDSInputStateBit_Start;
_inputStateBitMap[NDSInputID_Right] = NDSInputStateBit_Right;
_inputStateBitMap[NDSInputID_Left] = NDSInputStateBit_Left;
_inputStateBitMap[NDSInputID_Up] = NDSInputStateBit_Up;
_inputStateBitMap[NDSInputID_Down] = NDSInputStateBit_Down;
_inputStateBitMap[NDSInputID_R] = NDSInputStateBit_R;
_inputStateBitMap[NDSInputID_L] = NDSInputStateBit_L;
_inputStateBitMap[NDSInputID_X] = NDSInputStateBit_X;
_inputStateBitMap[NDSInputID_Y] = NDSInputStateBit_Y;
_inputStateBitMap[NDSInputID_Debug] = NDSInputStateBit_Debug;
_inputStateBitMap[NDSInputID_Touch] = NDSInputStateBit_Touch;
_inputStateBitMap[NDSInputID_Lid] = NDSInputStateBit_Lid;
_inputStateBitMap[NDSInputID_Piano_C] = NDSInputStateBit_Piano_C;
_inputStateBitMap[NDSInputID_Piano_CSharp] = NDSInputStateBit_Piano_CSharp;
_inputStateBitMap[NDSInputID_Piano_D] = NDSInputStateBit_Piano_D;
_inputStateBitMap[NDSInputID_Piano_DSharp] = NDSInputStateBit_Piano_DSharp;
_inputStateBitMap[NDSInputID_Piano_E] = NDSInputStateBit_Piano_E;
_inputStateBitMap[NDSInputID_Piano_F] = NDSInputStateBit_Piano_F;
_inputStateBitMap[NDSInputID_Piano_FSharp] = NDSInputStateBit_Piano_FSharp;
_inputStateBitMap[NDSInputID_Piano_G] = NDSInputStateBit_Piano_G;
_inputStateBitMap[NDSInputID_Piano_GSharp] = NDSInputStateBit_Piano_GSharp;
_inputStateBitMap[NDSInputID_Piano_A] = NDSInputStateBit_Piano_A;
_inputStateBitMap[NDSInputID_Piano_ASharp] = NDSInputStateBit_Piano_ASharp;
_inputStateBitMap[NDSInputID_Piano_B] = NDSInputStateBit_Piano_B;
_inputStateBitMap[NDSInputID_Piano_HighC] = NDSInputStateBit_Piano_HighC;
_inputStateBitMap[NDSInputID_GuitarGrip_Green] = NDSInputStateBit_GuitarGrip_Green;
_inputStateBitMap[NDSInputID_GuitarGrip_Red] = NDSInputStateBit_GuitarGrip_Red;
_inputStateBitMap[NDSInputID_GuitarGrip_Yellow] = NDSInputStateBit_GuitarGrip_Yellow;
_inputStateBitMap[NDSInputID_GuitarGrip_Blue] = NDSInputStateBit_GuitarGrip_Blue;
_inputStateBitMap[NDSInputID_Paddle] = NDSInputStateBit_Paddle;
_inputStateBitMap[NDSInputID_Microphone] = NDSInputStateBit_Microphone;
_inputStateBitMap[NDSInputID_Reset] = NDSInputStateBit_Reset;
pthread_mutex_init(&_mutexInputsPending, NULL);
}
ClientInputHandler::~ClientInputHandler()
{
pthread_mutex_destroy(&this->_mutexInputsPending);
delete this->_nullSampleGenerator;
delete this->_internalNoiseGenerator;
delete this->_whiteNoiseGenerator;
delete this->_sineWaveGenerator;
}
ClientExecutionControl* ClientInputHandler::GetClientExecutionController()
{
return this->_execControl;
}
void ClientInputHandler::SetClientExecutionController(ClientExecutionControl *execControl)
{
this->_execControl = execControl;
}
bool ClientInputHandler::GetEnableAutohold()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const bool enable = this->_enableAutohold;
pthread_mutex_unlock(&this->_mutexInputsPending);
return enable;
}
void ClientInputHandler::SetEnableAutohold(bool enable)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_enableAutohold = enable;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientInputHandler::ClearAutohold()
{
pthread_mutex_lock(&this->_mutexInputsPending);
for (size_t i = 0; i < NDSInputID_InputCount; i++)
{
this->_clientInputPending[i].autohold = false;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientInputHandler::SetClientInputStateUsingID(NDSInputID inputID, bool pressedState)
{
this->SetClientInputStateUsingID(inputID, pressedState, false, 0, 0);
}
void ClientInputHandler::SetClientInputStateUsingID(NDSInputID inputID, bool pressedState, bool isTurboEnabled, uint32_t turboPattern, uint32_t turboPatternLength)
{
if (inputID >= NDSInputID_InputCount)
{
return;
}
pthread_mutex_lock(&this->_mutexInputsPending);
if (this->_enableAutohold && pressedState)
{
this->_clientInputPending[inputID].autohold = true;
}
this->_clientInputPending[inputID].isPressed = pressedState;
this->_clientInputPending[inputID].turbo = isTurboEnabled;
this->_clientInputPending[inputID].turboPattern = turboPattern;
this->_clientInputPending[inputID].turboPatternLength = (turboPatternLength > 32) ? 32 : turboPatternLength;
if (this->_execControl != NULL)
{
NDSFrameInfo &frameInfoMutable = (NDSFrameInfo &)this->_execControl->GetNDSFrameInfo();
const uint64_t bitValue = (1 << this->_inputStateBitMap[inputID]);
frameInfoMutable.inputStatesPending.value = (this->_clientInputPending[inputID].isPressed) ? frameInfoMutable.inputStatesPending.value & ~bitValue : frameInfoMutable.inputStatesPending.value | bitValue;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
void ClientInputHandler::SetClientTouchState(bool pressedState, uint8_t touchLocX, uint8_t touchLocY, uint8_t touchPressure)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_clientInputPending[NDSInputID_Touch].isPressed = pressedState;
this->_touchLocXPending = touchLocX;
this->_touchLocYPending = touchLocY;
this->_touchPressurePending = touchPressure;
if (this->_execControl != NULL)
{
NDSFrameInfo &frameInfoMutable = (NDSFrameInfo &)this->_execControl->GetNDSFrameInfo();
frameInfoMutable.inputStatesPending.Touch = (this->_clientInputPending[NDSInputID_Touch].isPressed) ? 0 : 1;
frameInfoMutable.touchLocXPending = this->_touchLocXPending;
frameInfoMutable.touchLocYPending = this->_touchLocYPending;
frameInfoMutable.touchPressurePending = this->_touchPressurePending;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
double ClientInputHandler::GetSineWaveFrequency()
{
return this->_sineWaveGenerator->getFrequency();
}
void ClientInputHandler::SetSineWaveFrequency(double freq)
{
this->_sineWaveGenerator->setFrequency(freq);
}
AudioGenerator* ClientInputHandler::GetClientSoftwareMicSampleGenerator()
{
pthread_mutex_lock(&this->_mutexInputsPending);
AudioGenerator *softwareMicSampleGenerator = this->_softwareMicSampleGeneratorPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
return softwareMicSampleGenerator;
}
AudioGenerator* ClientInputHandler::GetClientSoftwareMicSampleGeneratorApplied()
{
return this->_softwareMicSampleGeneratorApplied;
}
AudioSampleBlockGenerator* ClientInputHandler::GetClientSelectedAudioFileGenerator()
{
pthread_mutex_lock(&this->_mutexInputsPending);
AudioSampleBlockGenerator *selectedAudioFileGenerator = this->_selectedAudioFileGenerator;
pthread_mutex_unlock(&this->_mutexInputsPending);
return selectedAudioFileGenerator;
}
void ClientInputHandler::SetClientSelectedAudioFileGenerator(AudioSampleBlockGenerator *selectedAudioFileGenerator)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_selectedAudioFileGenerator = selectedAudioFileGenerator;
pthread_mutex_unlock(&this->_mutexInputsPending);
}
bool ClientInputHandler::GetClientSoftwareMicState()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const bool isPressed = this->_clientInputPending[NDSInputID_Microphone].isPressed;
pthread_mutex_unlock(&this->_mutexInputsPending);
return isPressed;
}
bool ClientInputHandler::GetClientSoftwareMicStateApplied()
{
return this->_clientInputApplied[NDSInputID_Microphone].isPressed;
}
void ClientInputHandler::SetClientSoftwareMicState(bool pressedState, MicrophoneMode micMode)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_clientInputPending[NDSInputID_Microphone].isPressed = pressedState;
if (this->_execControl != NULL)
{
NDSFrameInfo &frameInfoMutable = (NDSFrameInfo &)this->_execControl->GetNDSFrameInfo();
frameInfoMutable.inputStatesPending.Microphone = (this->_clientInputPending[NDSInputID_Microphone].isPressed) ? 0 : 1;
}
if (pressedState)
{
switch (micMode)
{
case MicrophoneMode_InternalNoise:
this->_softwareMicSampleGeneratorPending = this->_internalNoiseGenerator;
break;
case MicrophoneMode_WhiteNoise:
this->_softwareMicSampleGeneratorPending = this->_whiteNoiseGenerator;
break;
case MicrophoneMode_SineWave:
this->_softwareMicSampleGeneratorPending = this->_sineWaveGenerator;
break;
case MicrophoneMode_AudioFile:
if (this->_selectedAudioFileGenerator != NULL)
{
this->_softwareMicSampleGeneratorPending = this->_selectedAudioFileGenerator;
}
break;
default:
this->_softwareMicSampleGeneratorPending = this->_nullSampleGenerator;
break;
}
}
else
{
this->_softwareMicSampleGeneratorPending = this->_nullSampleGenerator;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
int16_t ClientInputHandler::GetClientPaddleAdjust()
{
pthread_mutex_lock(&this->_mutexInputsPending);
const int16_t paddleAdjust = this->_paddleAdjustPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
return paddleAdjust;
}
void ClientInputHandler::SetClientPaddleAdjust(int16_t paddleAdjust)
{
pthread_mutex_lock(&this->_mutexInputsPending);
this->_paddleAdjustPending = paddleAdjust;
this->_paddleValuePending = this->_paddleValueApplied + paddleAdjust;
if (this->_execControl != NULL)
{
NDSFrameInfo &frameInfoMutable = (NDSFrameInfo &)this->_execControl->GetNDSFrameInfo();
frameInfoMutable.paddleValuePending = this->_paddleValuePending;
frameInfoMutable.paddleAdjustPending = this->_paddleAdjustPending;
}
pthread_mutex_unlock(&this->_mutexInputsPending);
}
const ClientInput* ClientInputHandler::GetClientInputsApplied()
{
return this->_clientInputApplied;
}
uint8_t ClientInputHandler::GetTouchLocXApplied()
{
return this->_touchLocXApplied;
}
uint8_t ClientInputHandler::GetTouchLocYApplied()
{
return this->_touchLocYApplied;
}
uint8_t ClientInputHandler::GetTouchPressureApplied()
{
return this->_touchPressureApplied;
}
int16_t ClientInputHandler::GetPaddleValueApplied()
{
return this->_paddleValueApplied;
}
int16_t ClientInputHandler:: GetPaddleAdjustApplied()
{
return this->_paddleAdjustApplied;
}
void ClientInputHandler::ProcessInputs()
{
// Before we begin input processing, we need to send all pending inputs to the core code.
pthread_mutex_lock(&this->_mutexInputsPending);
NDS_setPad(this->_clientInputPending[NDSInputID_Right].isPressed,
this->_clientInputPending[NDSInputID_Left].isPressed,
this->_clientInputPending[NDSInputID_Down].isPressed,
this->_clientInputPending[NDSInputID_Up].isPressed,
this->_clientInputPending[NDSInputID_Select].isPressed,
this->_clientInputPending[NDSInputID_Start].isPressed,
this->_clientInputPending[NDSInputID_B].isPressed,
this->_clientInputPending[NDSInputID_A].isPressed,
this->_clientInputPending[NDSInputID_Y].isPressed,
this->_clientInputPending[NDSInputID_X].isPressed,
this->_clientInputPending[NDSInputID_L].isPressed,
this->_clientInputPending[NDSInputID_R].isPressed,
this->_clientInputPending[NDSInputID_Debug].isPressed,
this->_clientInputPending[NDSInputID_Lid].isPressed);
if (this->_clientInputPending[NDSInputID_Touch].isPressed)
{
NDS_setTouchPos((u16)this->_touchLocXPending, (u16)this->_touchLocYPending);
}
else
{
NDS_releaseTouch();
}
NDS_setMic(this->_clientInputPending[NDSInputID_Microphone].isPressed);
// Copy all pending inputs for further processing.
for (size_t i = 0; i < NDSInputID_InputCount; i++)
{
this->_clientInputProcessing[i].isPressed = this->_clientInputPending[i].isPressed;
this->_clientInputProcessing[i].autohold = this->_clientInputPending[i].autohold;
this->_clientInputProcessing[i].turbo = this->_clientInputPending[i].turbo;
if ( (this->_clientInputProcessing[i].turboPattern != this->_clientInputPending[i].turboPattern) ||
(this->_clientInputProcessing[i].turboPatternLength != this->_clientInputPending[i].turboPatternLength) )
{
this->_clientInputProcessing[i].turboPatternStep = 0;
this->_clientInputProcessing[i].turboPattern = this->_clientInputPending[i].turboPattern;
this->_clientInputProcessing[i].turboPatternLength = this->_clientInputPending[i].turboPatternLength;
}
}
this->_touchLocXProcessing = this->_touchLocXPending;
this->_touchLocYProcessing = this->_touchLocYPending;
this->_touchPressureProcessing = this->_touchPressurePending;
this->_paddleAdjustProcessing = this->_paddleAdjustPending;
this->_paddleValueProcessing = this->_paddleValuePending;
this->_softwareMicSampleGeneratorProcessing = this->_softwareMicSampleGeneratorPending;
pthread_mutex_unlock(&this->_mutexInputsPending);
// Begin processing the input based on current parameters.
NDS_beginProcessingInput();
UserInput &processedInput = NDS_getProcessingUserInput();
if (movieMode == MOVIEMODE_PLAY)
{
FCEUMOV_HandlePlayback();
this->_clientInputProcessing[NDSInputID_A].isPressed = processedInput.buttons.A;
this->_clientInputProcessing[NDSInputID_B].isPressed = processedInput.buttons.B;
this->_clientInputProcessing[NDSInputID_Select].isPressed = processedInput.buttons.T;
this->_clientInputProcessing[NDSInputID_Start].isPressed = processedInput.buttons.S;
this->_clientInputProcessing[NDSInputID_Right].isPressed = processedInput.buttons.R;
this->_clientInputProcessing[NDSInputID_Left].isPressed = processedInput.buttons.L;
this->_clientInputProcessing[NDSInputID_Up].isPressed = processedInput.buttons.U;
this->_clientInputProcessing[NDSInputID_Down].isPressed = processedInput.buttons.D;
this->_clientInputProcessing[NDSInputID_R].isPressed = processedInput.buttons.E;
this->_clientInputProcessing[NDSInputID_L].isPressed = processedInput.buttons.W;
this->_clientInputProcessing[NDSInputID_X].isPressed = processedInput.buttons.X;
this->_clientInputProcessing[NDSInputID_Y].isPressed = processedInput.buttons.Y;
this->_clientInputProcessing[NDSInputID_Debug].isPressed = processedInput.buttons.G;
this->_clientInputProcessing[NDSInputID_Touch].isPressed = processedInput.touch.isTouch;
this->_clientInputProcessing[NDSInputID_Lid].isPressed = processedInput.buttons.F;
this->_clientInputProcessing[NDSInputID_Microphone].isPressed = (processedInput.mic.micButtonPressed != 0);
this->_touchLocXProcessing = processedInput.touch.touchX >> 4;
this->_touchLocYProcessing = processedInput.touch.touchY >> 4;
}
else
{
if ( (this->_execControl != NULL) && (this->_execControl->GetExecutionBehaviorApplied() != ExecutionBehavior_FrameJump) )
{
size_t i = 0;
// First process the inputs that exist in the core code's UserInput struct. The core code will
// use this struct for its own purposes later.
for (; i <= NDSInputID_Lid; i++)
{
bool &pressedState = (i != NDSInputID_Touch) ? processedInput.buttons.array[this->_userInputMap[(NDSInputID)i]] : processedInput.touch.isTouch;
pressedState = (this->_clientInputProcessing[i].isPressed || this->_clientInputProcessing[i].autohold);
this->_clientInputProcessing[i].isPressed = pressedState;
if (this->_clientInputProcessing[i].turbo)
{
const bool turboPressedState = ( ((this->_clientInputProcessing[i].turboPattern >> this->_clientInputProcessing[i].turboPatternStep) & 0x00000001) == 1 );
pressedState = (pressedState && turboPressedState);
this->_clientInputProcessing[i].isPressed = pressedState;
this->_clientInputProcessing[i].turboPatternStep++;
if (this->_clientInputProcessing[i].turboPatternStep >= this->_clientInputProcessing[i].turboPatternLength)
{
this->_clientInputProcessing[i].turboPatternStep = 0;
}
}
}
// Process the remaining inputs.
for (i = NDSInputID_Piano_C; i < NDSInputID_InputCount; i++)
{
bool &pressedState = this->_clientInputProcessing[i].isPressed;
pressedState = (this->_clientInputProcessing[i].isPressed || this->_clientInputProcessing[i].autohold);
if (this->_clientInputProcessing[i].turbo)
{
const bool turboPressedState = ( ((this->_clientInputProcessing[i].turboPattern >> this->_clientInputProcessing[i].turboPatternStep) & 0x00000001) == 1 );
pressedState = (pressedState && turboPressedState);
this->_clientInputProcessing[i].turboPatternStep++;
if (this->_clientInputProcessing[i].turboPatternStep >= this->_clientInputProcessing[i].turboPatternLength)
{
this->_clientInputProcessing[i].turboPatternStep = 0;
}
}
}
}
else
{
memset(&processedInput, 0, sizeof(UserInput));
memset(this->_clientInputProcessing, 0, sizeof(this->_clientInputProcessing));
this->_softwareMicSampleGeneratorProcessing = this->_nullSampleGenerator;
}
}
}
void ClientInputHandler::ApplyInputs()
{
NDS_endProcessingInput();
this->_touchLocXApplied = this->_touchLocXProcessing;
this->_touchLocYApplied = this->_touchLocYProcessing;
this->_touchPressureApplied = this->_touchPressureProcessing;
this->_paddleAdjustApplied = this->_paddleAdjustProcessing;
this->_paddleValueApplied = this->_paddleValueProcessing;
memcpy(this->_clientInputApplied, this->_clientInputProcessing, sizeof(this->_clientInputProcessing));
CommonSettings.StylusPressure = (int)this->_touchPressureApplied;
this->_softwareMicSampleGeneratorApplied = this->_softwareMicSampleGeneratorProcessing;
if (!this->_clientInputApplied[NDSInputID_Microphone].isPressed)
{
this->_internalNoiseGenerator->setSamplePosition(0);
this->_sineWaveGenerator->setCyclePosition(0.0);
if (this->_selectedAudioFileGenerator != NULL)
{
this->_selectedAudioFileGenerator->setSamplePosition(0);
}
}
// Setup the inputs from SLOT-2 devices.
const NDS_SLOT2_TYPE slot2DeviceType = slot2_GetSelectedType();
switch (slot2DeviceType)
{
case NDS_SLOT2_GUITARGRIP:
guitarGrip_setKey(this->_clientInputApplied[NDSInputID_GuitarGrip_Green].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Red].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Yellow].isPressed,
this->_clientInputApplied[NDSInputID_GuitarGrip_Blue].isPressed);
break;
case NDS_SLOT2_EASYPIANO:
piano_setKey(this->_clientInputApplied[NDSInputID_Piano_C].isPressed,
this->_clientInputApplied[NDSInputID_Piano_CSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_D].isPressed,
this->_clientInputApplied[NDSInputID_Piano_DSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_E].isPressed,
this->_clientInputApplied[NDSInputID_Piano_F].isPressed,
this->_clientInputApplied[NDSInputID_Piano_FSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_G].isPressed,
this->_clientInputApplied[NDSInputID_Piano_GSharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_A].isPressed,
this->_clientInputApplied[NDSInputID_Piano_ASharp].isPressed,
this->_clientInputApplied[NDSInputID_Piano_B].isPressed,
this->_clientInputApplied[NDSInputID_Piano_HighC].isPressed);
break;
case NDS_SLOT2_PADDLE:
Paddle_SetValue((uint16_t)this->_paddleValueApplied);
break;
default:
break;
}
if (movieMode == MOVIEMODE_RECORD)
{
FCEUMOV_HandleRecording();
}
}

View File

@ -0,0 +1,400 @@
/*
Copyright (C) 2017 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CLIENT_INPUT_HANDLER_H_
#define _CLIENT_INPUT_HANDLER_H_
#include <pthread.h>
#include <string.h>
#include <map>
#include <vector>
#define INPUT_HANDLER_STRING_LENGTH 256
#define INPUT_STATES_CLEAR_VALUE 0xFFFFFFFF00FF03FFULL
#define MIC_SAMPLE_RATE 16000.0
#define MIC_SAMPLE_RESOLUTION 8 // Bits per sample; must be a multiple of 8
#define MIC_NUMBER_CHANNELS 1 // Number of channels
#define MIC_SAMPLE_SIZE ((MIC_SAMPLE_RESOLUTION / 8) * MIC_NUMBER_CHANNELS) // Bytes per sample, multiplied by the number of channels
#define MIC_MAX_BUFFER_SAMPLES ((MIC_SAMPLE_RATE / DS_FRAMES_PER_SECOND) * MIC_SAMPLE_SIZE)
#define MIC_CAPTURE_FRAMES 192 // The number of audio frames that the NDS microphone should pull. The lower this value, the lower the latency. Ensure that this value is not too low, or else audio frames may be lost.
#define MIC_NULL_LEVEL_THRESHOLD 2.5
#define MIC_CLIP_LEVEL_THRESHOLD 39.743665431525209 // ((2.0/pi) * MIC_NULL_SAMPLE_VALUE) - 1.0
#define MIC_NULL_SAMPLE_VALUE 64
enum NDSInputID
{
NDSInputID_A = 0,
NDSInputID_B,
NDSInputID_Select,
NDSInputID_Start,
NDSInputID_Right,
NDSInputID_Left,
NDSInputID_Up,
NDSInputID_Down,
NDSInputID_R,
NDSInputID_L,
NDSInputID_X,
NDSInputID_Y,
NDSInputID_Debug,
NDSInputID_Touch,
NDSInputID_Lid,
NDSInputID_Piano_C,
NDSInputID_Piano_CSharp,
NDSInputID_Piano_D,
NDSInputID_Piano_DSharp,
NDSInputID_Piano_E,
NDSInputID_Piano_F,
NDSInputID_Piano_FSharp,
NDSInputID_Piano_G,
NDSInputID_Piano_GSharp,
NDSInputID_Piano_A,
NDSInputID_Piano_ASharp,
NDSInputID_Piano_B,
NDSInputID_Piano_HighC,
NDSInputID_GuitarGrip_Green,
NDSInputID_GuitarGrip_Red,
NDSInputID_GuitarGrip_Yellow,
NDSInputID_GuitarGrip_Blue,
NDSInputID_Paddle,
NDSInputID_Microphone,
NDSInputID_Reset,
NDSInputID_InputCount
};
enum NDSInputStateBit
{
NDSInputStateBit_A = 0,
NDSInputStateBit_B = 1,
NDSInputStateBit_Select = 2,
NDSInputStateBit_Start = 3,
NDSInputStateBit_Right = 4,
NDSInputStateBit_Left = 5,
NDSInputStateBit_Up = 6,
NDSInputStateBit_Down = 7,
NDSInputStateBit_R = 8,
NDSInputStateBit_L = 9,
NDSInputStateBit_X = 16,
NDSInputStateBit_Y = 17,
NDSInputStateBit_Debug = 19,
NDSInputStateBit_Touch = 22,
NDSInputStateBit_Lid = 23,
NDSInputStateBit_Piano_C = 32,
NDSInputStateBit_Piano_CSharp = 33,
NDSInputStateBit_Piano_D = 34,
NDSInputStateBit_Piano_DSharp = 35,
NDSInputStateBit_Piano_E = 36,
NDSInputStateBit_Piano_F = 37,
NDSInputStateBit_Piano_FSharp = 38,
NDSInputStateBit_Piano_G = 39,
NDSInputStateBit_Piano_GSharp = 40,
NDSInputStateBit_Piano_A = 41,
NDSInputStateBit_Piano_ASharp = 42,
NDSInputStateBit_Piano_B = 45,
NDSInputStateBit_Piano_HighC = 46,
NDSInputStateBit_GuitarGrip_Green = 51,
NDSInputStateBit_GuitarGrip_Red = 52,
NDSInputStateBit_GuitarGrip_Yellow = 53,
NDSInputStateBit_GuitarGrip_Blue = 54,
NDSInputStateBit_Paddle = 56,
NDSInputStateBit_Microphone = 57,
NDSInputStateBit_Reset = 58
};
enum ClientInputDeviceState
{
ClientInputDeviceState_Off = 0,
ClientInputDeviceState_On,
ClientInputDeviceState_Mixed
};
enum MicrophoneMode
{
MicrophoneMode_None = 0,
MicrophoneMode_InternalNoise,
MicrophoneMode_AudioFile,
MicrophoneMode_WhiteNoise,
MicrophoneMode_Physical,
MicrophoneMode_SineWave
};
class ClientExecutionControl;
class AudioGenerator;
class NullGenerator;
class InternalNoiseGenerator;
class WhiteNoiseGenerator;
class SineWaveGenerator;
class AudioSampleBlockGenerator;
typedef union
{
uint64_t value;
struct
{
uint16_t gbaKeys;
uint16_t ndsKeysExt;
uint16_t easyPianoKeys;
uint8_t guitarGripKeys;
uint8_t miscKeys;
};
struct
{
#ifndef MSB_FIRST
uint8_t A:1;
uint8_t B:1;
uint8_t Select:1;
uint8_t Start:1;
uint8_t Right:1;
uint8_t Left:1;
uint8_t Up:1;
uint8_t Down:1;
uint8_t R:1;
uint8_t L:1;
uint8_t :6;
uint8_t X:1;
uint8_t Y:1;
uint8_t :1;
uint8_t Debug:1;
uint8_t :2;
uint8_t Touch:1;
uint8_t Lid:1;
uint8_t :8;
uint8_t PianoC:1;
uint8_t PianoCSharp:1;
uint8_t PianoD:1;
uint8_t PianoDSharp:1;
uint8_t PianoE:1;
uint8_t PianoF:1;
uint8_t PianoFSharp:1;
uint8_t PianoG:1;
uint8_t PianoGSharp:1;
uint8_t PianoA:1;
uint8_t PianoASharp:1;
uint8_t :2;
uint8_t PianoB:1;
uint8_t PianoHighC:1;
uint8_t :1;
uint8_t :3;
uint8_t GuitarGripBlue:1;
uint8_t GuitarGripYellow:1;
uint8_t GuitarGripRed:1;
uint8_t GuitarGripGreen:1;
uint8_t :1;
uint8_t Paddle:1;
uint8_t Microphone:1;
uint8_t Reset:1;
uint8_t :5;
#else
uint8_t Down:1;
uint8_t Up:1;
uint8_t Left:1;
uint8_t Right:1;
uint8_t Start:1;
uint8_t Select:1;
uint8_t B:1;
uint8_t A:1;
uint8_t :6;
uint8_t L:1;
uint8_t R:1;
uint8_t Lid:1;
uint8_t Touch:1;
uint8_t :2;
uint8_t Debug:1;
uint8_t :1;
uint8_t Y:1;
uint8_t X:1;
uint8_t :8;
uint8_t PianoG:1;
uint8_t PianoFSharp:1;
uint8_t PianoF:1;
uint8_t PianoE:1;
uint8_t PianoDSharp:1;
uint8_t PianoD:1;
uint8_t PianoCSharp:1;
uint8_t PianoC:1;
uint8_t :1;
uint8_t PianoHighC:1;
uint8_t PianoB:1;
uint8_t :2;
uint8_t PianoASharp:1;
uint8_t PianoA:1;
uint8_t PianoGSharp:1;
uint8_t :1;
uint8_t GuitarGripGreen:1;
uint8_t GuitarGripRed:1;
uint8_t GuitarGripYellow:1;
uint8_t GuitarGripBlue:1;
uint8_t :3;
uint8_t :5;
uint8_t Reset:1;
uint8_t Microphone:1;
uint8_t Paddle:1;
#endif
};
} NDSInputState; // Each bit represents the Pressed/Released state of a single input. Pressed=0, Released=1
struct ClientInputDeviceProperties
{
char deviceName[INPUT_HANDLER_STRING_LENGTH];
char deviceCode[INPUT_HANDLER_STRING_LENGTH];
char elementName[INPUT_HANDLER_STRING_LENGTH];
char elementCode[INPUT_HANDLER_STRING_LENGTH];
bool isAnalog; // This is an analog input, as opposed to being a digital input.
ClientInputDeviceState state; // The input state that is sent on command dispatch
int32_t intCoordX; // The X-coordinate as an int for commands that require a location
int32_t intCoordY; // The Y-coordinate as an int for commands that require a location
float floatCoordX; // The X-coordinate as a float for commands that require a location
float floatCoordY; // The Y-coordinate as a float for commands that require a location
float scalar; // A scalar value for commands that require a scalar
void *object; // An object for commands that require an object
};
typedef struct ClientInputDeviceProperties ClientInputDeviceProperties;
struct ClientInput
{
bool isPressed;
bool turbo;
bool autohold;
uint32_t turboPattern;
uint8_t turboPatternStep;
uint8_t turboPatternLength;
};
typedef struct ClientInput ClientInput;
typedef std::map<NDSInputID, size_t> NDSUserInputMap;
typedef std::map<NDSInputID, NDSInputStateBit> NDSInputStateBitMap;
typedef std::vector<ClientInputDeviceProperties> ClientInputDevicePropertiesList;
class ClientInputDevicePropertiesEncoder
{
public:
virtual ClientInputDeviceProperties EncodeKeyboardInput(const int32_t keyCode, bool keyPressed);
virtual ClientInputDeviceProperties EncodeMouseInput(const int32_t buttonNumber, float touchLocX, float touchLocY, bool buttonPressed);
};
class ClientInputHandler
{
protected:
ClientExecutionControl *_execControl;
NDSUserInputMap _userInputMap;
NDSInputStateBitMap _inputStateBitMap;
AudioGenerator *_softwareMicSampleGeneratorPending;
AudioGenerator *_softwareMicSampleGeneratorProcessing;
AudioGenerator *_softwareMicSampleGeneratorApplied;
NullGenerator *_nullSampleGenerator;
InternalNoiseGenerator *_internalNoiseGenerator;
WhiteNoiseGenerator *_whiteNoiseGenerator;
SineWaveGenerator *_sineWaveGenerator;
AudioSampleBlockGenerator *_selectedAudioFileGenerator;
ClientInput _clientInputPending[NDSInputID_InputCount];
ClientInput _clientInputProcessing[NDSInputID_InputCount];
ClientInput _clientInputApplied[NDSInputID_InputCount];
bool _enableAutohold;
uint8_t _touchLocXPending;
uint8_t _touchLocYPending;
uint8_t _touchPressurePending;
int16_t _paddleValuePending;
int16_t _paddleAdjustPending;
uint8_t _touchLocXProcessing;
uint8_t _touchLocYProcessing;
uint8_t _touchPressureProcessing;
int16_t _paddleValueProcessing;
int16_t _paddleAdjustProcessing;
uint8_t _touchLocXApplied;
uint8_t _touchLocYApplied;
uint8_t _touchPressureApplied;
int16_t _paddleValueApplied;
int16_t _paddleAdjustApplied;
pthread_mutex_t _mutexInputsPending;
public:
ClientInputHandler();
~ClientInputHandler();
ClientExecutionControl* GetClientExecutionController();
void SetClientExecutionController(ClientExecutionControl *execControl);
bool GetEnableAutohold();
void SetEnableAutohold(bool enable);
void ClearAutohold();
void SetClientInputStateUsingID(NDSInputID inputID, bool pressedState);
void SetClientInputStateUsingID(NDSInputID inputID, bool pressedState, bool isTurboEnabled, uint32_t turboPattern, uint32_t turboPatternLength);
void SetClientTouchState(bool pressedState, uint8_t touchLocX, uint8_t touchLocY, uint8_t touchPressure);
double GetSineWaveFrequency();
void SetSineWaveFrequency(double freq);
AudioGenerator* GetClientSoftwareMicSampleGenerator();
AudioGenerator* GetClientSoftwareMicSampleGeneratorApplied();
AudioSampleBlockGenerator* GetClientSelectedAudioFileGenerator();
void SetClientSelectedAudioFileGenerator(AudioSampleBlockGenerator *selectedAudioFileGenerator);
bool GetClientSoftwareMicState();
bool GetClientSoftwareMicStateApplied();
void SetClientSoftwareMicState(bool pressedState, MicrophoneMode micMode);
int16_t GetClientPaddleAdjust();
void SetClientPaddleAdjust(int16_t paddleAdjust);
const ClientInput* GetClientInputsApplied();
uint8_t GetTouchLocXApplied();
uint8_t GetTouchLocYApplied();
uint8_t GetTouchPressureApplied();
int16_t GetPaddleValueApplied();
int16_t GetPaddleAdjustApplied();
void ProcessInputs();
void ApplyInputs();
};
#endif // _CLIENT_INPUT_HANDLER_H_

View File

@ -73,6 +73,10 @@
AB0F29B514BE7213009ABC6F /* Icon_RotateCW_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F29A314BE7213009ABC6F /* Icon_RotateCW_420x420.png */; };
AB0F29B614BE7213009ABC6F /* Icon_ShowHUD_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F29A414BE7213009ABC6F /* Icon_ShowHUD_420x420.png */; };
AB0F29B714BE7213009ABC6F /* Icon_Speaker_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */; };
AB11AD891F6757F800CB298E /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */; };
AB11AD8A1F6757F800CB298E /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */; };
AB11AD8B1F6757F800CB298E /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */; };
AB11AD8C1F6757F800CB298E /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */; };
AB15CA7214A29EE500B8A6A4 /* cpu_detect_x86_gcc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6613AF1D6D00502E1E /* cpu_detect_x86_gcc.cpp */; };
AB1773FD182ECA8A009F29DD /* slot2_passme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1773FC182ECA8A009F29DD /* slot2_passme.cpp */; };
AB1773FE182ECA8A009F29DD /* slot2_passme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1773FC182ECA8A009F29DD /* slot2_passme.cpp */; };
@ -1265,6 +1269,8 @@
AB0F29A314BE7213009ABC6F /* Icon_RotateCW_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_RotateCW_420x420.png; path = images/Icon_RotateCW_420x420.png; sourceTree = "<group>"; };
AB0F29A414BE7213009ABC6F /* Icon_ShowHUD_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_ShowHUD_420x420.png; path = images/Icon_ShowHUD_420x420.png; sourceTree = "<group>"; };
AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speaker_420x420.png; path = images/Icon_Speaker_420x420.png; sourceTree = "<group>"; };
AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientInputHandler.cpp; sourceTree = "<group>"; };
AB11AD881F6757F800CB298E /* ClientInputHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientInputHandler.h; sourceTree = "<group>"; };
AB1773FC182ECA8A009F29DD /* slot2_passme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_passme.cpp; sourceTree = "<group>"; };
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreaudiosound.cpp; sourceTree = "<group>"; };
AB1B9E601501A78000464647 /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ringbuffer.cpp; sourceTree = "<group>"; };
@ -2000,6 +2006,7 @@
ABD10AE51715FCDD00B5729D /* audiosamplegenerator.cpp */,
ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */,
ABB1C9461F5281AE0004844F /* ClientExecutionControl.cpp */,
AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */,
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */,
AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */,
ABD10AE61715FCDD00B5729D /* mic_ext.cpp */,
@ -2010,6 +2017,7 @@
ABD10AE31715FCDD00B5729D /* audiosamplegenerator.h */,
ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */,
ABB1C9471F5281AE0004844F /* ClientExecutionControl.h */,
AB11AD881F6757F800CB298E /* ClientInputHandler.h */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
ABD103FE1346652500AF11D1 /* cocoa_core.h */,
AB58F32B1364F44B0074C376 /* cocoa_file.h */,
@ -3881,6 +3889,7 @@
ABD1FEFD1345AC8400AF11D1 /* version.cpp in Sources */,
ABD1FF681345ACBF00AF11D1 /* vfat.cpp in Sources */,
ABE5DE95143F781900835AD8 /* videofilter.cpp in Sources */,
AB11AD8B1F6757F800CB298E /* ClientInputHandler.cpp in Sources */,
AB1773FE182ECA8A009F29DD /* slot2_passme.cpp in Sources */,
ABAD3E7B13AF1D6D00502E1E /* WavFile.cpp in Sources */,
ABD1FEFE1345AC8400AF11D1 /* wifi.cpp in Sources */,
@ -4101,6 +4110,7 @@
AB2ABA3B1C9F9CFA00173B15 /* async_job.c in Sources */,
AB796D3D15CDCBA200C59155 /* thumb_instructions.cpp in Sources */,
AB9038A617C5ECFD00F410BD /* advanscene.cpp in Sources */,
AB11AD891F6757F800CB298E /* ClientInputHandler.cpp in Sources */,
AB796D3E15CDCBA200C59155 /* Timestretcher.cpp in Sources */,
ABFEA81F1BB4EC1000B08C25 /* ftgasp.c in Sources */,
AB796D3F15CDCBA200C59155 /* tinystr.cpp in Sources */,
@ -4324,6 +4334,7 @@
AB8F3CC11A53AC2600A80BF6 /* slot1_retail_auto.cpp in Sources */,
AB8F3CC21A53AC2600A80BF6 /* SPU.cpp in Sources */,
AB000DD71CCC6B4200413F02 /* retro_stat.c in Sources */,
AB11AD8A1F6757F800CB298E /* ClientInputHandler.cpp in Sources */,
AB8F3CC31A53AC2600A80BF6 /* sse_optimized.cpp in Sources */,
AB8F3CC41A53AC2600A80BF6 /* task.cpp in Sources */,
AB8F3CC51A53AC2600A80BF6 /* TDStretch.cpp in Sources */,
@ -4488,6 +4499,7 @@
ABB3C69C1501C04F00E0C22E /* directory.cpp in Sources */,
ABB3C69D1501C04F00E0C22E /* disc.cpp in Sources */,
ABB3C69E1501C04F00E0C22E /* fatdir.cpp in Sources */,
AB11AD8C1F6757F800CB298E /* ClientInputHandler.cpp in Sources */,
ABB3C69F1501C04F00E0C22E /* fatfile.cpp in Sources */,
ABB3C6A01501C04F00E0C22E /* file_allocation_table.cpp in Sources */,
ABB3C6A11501C04F00E0C22E /* filetime.cpp in Sources */,

View File

@ -1446,6 +1446,16 @@
ABBFDFB51898EE4B00A3FFA5 /* Icon_FrameJump_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = ABBFDFAD1898EE4B00A3FFA5 /* Icon_FrameJump_420x420.png */; };
ABBFDFB61898EE4B00A3FFA5 /* Icon_FrameAdvance_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = ABBFDFAC1898EE4B00A3FFA5 /* Icon_FrameAdvance_420x420.png */; };
ABBFDFB71898EE4B00A3FFA5 /* Icon_FrameJump_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = ABBFDFAD1898EE4B00A3FFA5 /* Icon_FrameJump_420x420.png */; };
ABC04DA31F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */; };
ABC04DA41F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */; };
ABC04DA51F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */; };
ABC04DA61F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */; };
ABC04DA71F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */; };
ABC04DCA1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */; };
ABC04DCB1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */; };
ABC04DCC1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */; };
ABC04DCD1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */; };
ABC04DCE1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */; };
ABC3AF3314B7F06900D5B13D /* Icon_VolumeFull_16x16.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC3AF2B14B7F06900D5B13D /* Icon_VolumeFull_16x16.png */; };
ABC3AF3414B7F06900D5B13D /* Icon_VolumeMute_16x16.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC3AF2C14B7F06900D5B13D /* Icon_VolumeMute_16x16.png */; };
ABC3AF3514B7F06900D5B13D /* Icon_VolumeOneThird_16x16.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC3AF2D14B7F06900D5B13D /* Icon_VolumeOneThird_16x16.png */; };
@ -1996,6 +2006,9 @@
ABBFDFA61898EE3200A3FFA5 /* Icon_DisplayToggle_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DisplayToggle_420x420.png; path = images/Icon_DisplayToggle_420x420.png; sourceTree = "<group>"; };
ABBFDFAC1898EE4B00A3FFA5 /* Icon_FrameAdvance_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameAdvance_420x420.png; path = images/Icon_FrameAdvance_420x420.png; sourceTree = "<group>"; };
ABBFDFAD1898EE4B00A3FFA5 /* Icon_FrameJump_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_FrameJump_420x420.png; path = images/Icon_FrameJump_420x420.png; sourceTree = "<group>"; };
ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientInputHandler.cpp; sourceTree = "<group>"; };
ABC04DA21F67A20500EA6ED7 /* ClientInputHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientInputHandler.h; sourceTree = "<group>"; };
ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macosx_10_5_compat.cpp; sourceTree = "<group>"; };
ABC3AF2B14B7F06900D5B13D /* Icon_VolumeFull_16x16.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_VolumeFull_16x16.png; path = images/Icon_VolumeFull_16x16.png; sourceTree = "<group>"; };
ABC3AF2C14B7F06900D5B13D /* Icon_VolumeMute_16x16.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_VolumeMute_16x16.png; path = images/Icon_VolumeMute_16x16.png; sourceTree = "<group>"; };
ABC3AF2D14B7F06900D5B13D /* Icon_VolumeOneThird_16x16.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_VolumeOneThird_16x16.png; path = images/Icon_VolumeOneThird_16x16.png; sourceTree = "<group>"; };
@ -2386,7 +2399,9 @@
AB2145221714DFF4006DDB0F /* audiosamplegenerator.cpp */,
AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */,
ABD4F2711F54A51000D75A1F /* ClientExecutionControl.cpp */,
ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */,
ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */,
ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */,
ABD9A46413DB99B300777194 /* mic_ext.cpp */,
ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */,
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */,
@ -2394,6 +2409,7 @@
AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */,
AB0F13901E1B7C320075684F /* ClientDisplayView.h */,
ABD4F2721F54A51000D75A1F /* ClientExecutionControl.h */,
ABC04DA21F67A20500EA6ED7 /* ClientInputHandler.h */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
ABD103FE1346652500AF11D1 /* cocoa_core.h */,
AB58F32B1364F44B0074C376 /* cocoa_file.h */,
@ -4581,6 +4597,8 @@
AB3E69111E231E9900D4CC75 /* MacOGLDisplayView.mm in Sources */,
AB3E69841E25FBBF00D4CC75 /* DisplayViewCALayer.mm in Sources */,
ABD4F2741F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */,
ABC04DA41F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */,
ABC04DCB1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4766,6 +4784,8 @@
AB3E69121E231E9900D4CC75 /* MacOGLDisplayView.mm in Sources */,
AB3E69851E25FBBF00D4CC75 /* DisplayViewCALayer.mm in Sources */,
ABD4F2751F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */,
ABC04DA51F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */,
ABC04DCC1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4981,6 +5001,8 @@
AB3E69101E231E9900D4CC75 /* MacOGLDisplayView.mm in Sources */,
AB3E69831E25FBBF00D4CC75 /* DisplayViewCALayer.mm in Sources */,
ABD4F2731F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */,
ABC04DA31F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */,
ABC04DCA1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5196,6 +5218,8 @@
AB3E69141E231E9900D4CC75 /* MacOGLDisplayView.mm in Sources */,
AB3E69871E25FBBF00D4CC75 /* DisplayViewCALayer.mm in Sources */,
ABD4F2771F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */,
ABC04DA71F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */,
ABC04DCE1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5381,6 +5405,8 @@
AB3E69131E231E9900D4CC75 /* MacOGLDisplayView.mm in Sources */,
AB3E69861E25FBBF00D4CC75 /* DisplayViewCALayer.mm in Sources */,
ABD4F2761F54A51000D75A1F /* ClientExecutionControl.cpp in Sources */,
ABC04DA61F67A20500EA6ED7 /* ClientInputHandler.cpp in Sources */,
ABC04DCD1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -23,7 +23,7 @@
#include "audiosamplegenerator.h"
#include <math.h>
#include <string.h>
#include "ClientExecutionControl.h"
#include "ClientInputHandler.h"
#define NUM_INTERNAL_NOISE_SAMPLES 32

View File

@ -21,9 +21,9 @@
#include <libkern/OSAtomic.h>
#include <string>
#import "cocoa_util.h"
#include "ClientExecutionControl.h"
class ClientExecutionControl;
@class CocoaDSCore;
@class CocoaDSController;
@class CocoaDSFirmware;

View File

@ -26,6 +26,7 @@
#import "cocoa_util.h"
#include "ClientExecutionControl.h"
#include "ClientInputHandler.h"
#include "../../movie.h"
#include "../../NDSSystem.h"
@ -154,11 +155,15 @@ volatile bool execute = true;
_fpsTimer = nil;
_isTimerAtSecond = NO;
cdsController = nil;
cdsFirmware = nil;
cdsGPU = [[[[CocoaDSGPU alloc] init] autorelease] retain];
cdsController = [[[[CocoaDSController alloc] init] autorelease] retain];
cdsOutputList = [[[[NSMutableArray alloc] initWithCapacity:32] autorelease] retain];
ClientInputHandler *inputHandler = [cdsController inputHandler];
inputHandler->SetClientExecutionController(execControl);
execControl->SetClientInputHandler(inputHandler);
slot1StatusText = NSSTRING_STATUS_EMULATION_NOT_RUNNING;
spinlockMasterExecute = OS_SPINLOCK_INIT;
@ -989,6 +994,7 @@ static void* RunCoreThread(void *arg)
CoreThreadParam *param = (CoreThreadParam *)arg;
CocoaDSCore *cdsCore = (CocoaDSCore *)param->cdsCore;
ClientExecutionControl *execControl = [cdsCore execControl];
ClientInputHandler *inputHandler = execControl->GetClientInputHandler();
NSMutableArray *cdsOutputList = [cdsCore cdsOutputList];
const NDSFrameInfo &ndsFrameInfo = execControl->GetNDSFrameInfo();
@ -1018,8 +1024,8 @@ static void* RunCoreThread(void *arg)
frameTime = execControl->GetFrameTime();
frameJumpTarget = execControl->GetFrameJumpTargetApplied();
execControl->ProcessInputs();
execControl->ApplyInputs();
inputHandler->ProcessInputs();
inputHandler->ApplyInputs();
execControl->ApplySettingsOnNDSExec();
// Execute the frame and increment the frame counter.

View File

@ -20,9 +20,8 @@
#include <libkern/OSAtomic.h>
#include <vector>
#include "ClientExecutionControl.h"
@class CocoaDSController;
class ClientInputHandler;
class CoreAudioInput;
struct CoreAudioInputDeviceInfo;
class AudioGenerator;
@ -43,7 +42,7 @@ class AudioSampleBlockGenerator;
@interface CocoaDSController : NSObject
{
id <CocoaDSControllerDelegate> delegate;
ClientExecutionControl *execControl;
ClientInputHandler *inputHandler;
NSInteger stylusPressure;
@ -63,7 +62,7 @@ class AudioSampleBlockGenerator;
}
@property (retain) id <CocoaDSControllerDelegate> delegate;
@property (assign) ClientExecutionControl *execControl;
@property (readonly, nonatomic) ClientInputHandler *inputHandler;
@property (assign) BOOL autohold;
@property (assign) NSInteger paddleAdjust;
@property (assign) NSInteger stylusPressure;

View File

@ -26,11 +26,13 @@
#include "../../slot2.h"
#undef BOOL
#include "ClientInputHandler.h"
@implementation CocoaDSController
@synthesize delegate;
@synthesize execControl;
@dynamic inputHandler;
@dynamic autohold;
@dynamic paddleAdjust;
@synthesize stylusPressure;
@ -60,7 +62,7 @@
}
delegate = nil;
execControl = NULL;
inputHandler = new ClientInputHandler;
_availableMicSamples = 0;
micLevel = 0.0f;
@ -95,6 +97,11 @@
[super dealloc];
}
- (ClientInputHandler *) inputHandler
{
return inputHandler;
}
- (BOOL) isHardwareMicAvailable
{
return ( CAInputDevice->IsHardwareEnabled() &&
@ -157,83 +164,83 @@
- (void) setSoftwareMicState:(BOOL)theState mode:(NSInteger)micMode
{
execControl->SetClientSoftwareMicState((theState) ? true : false, (MicrophoneMode)micMode);
inputHandler->SetClientSoftwareMicState((theState) ? true : false, (MicrophoneMode)micMode);
}
- (BOOL) softwareMicState
{
return (execControl->GetClientSoftwareMicState()) ? YES : NO;
return (inputHandler->GetClientSoftwareMicState()) ? YES : NO;
}
- (AudioGenerator *) softwareMicSampleGenerator
{
return execControl->GetClientSoftwareMicSampleGenerator();
return inputHandler->GetClientSoftwareMicSampleGenerator();
}
- (void) setSelectedAudioFileGenerator:(AudioSampleBlockGenerator *)audioGenerator
{
execControl->SetClientSelectedAudioFileGenerator(audioGenerator);
inputHandler->SetClientSelectedAudioFileGenerator(audioGenerator);
}
- (AudioSampleBlockGenerator *) selectedAudioFileGenerator
{
return execControl->GetClientSelectedAudioFileGenerator();
return inputHandler->GetClientSelectedAudioFileGenerator();
}
- (void) setAutohold:(BOOL)theState
{
execControl->SetEnableAutohold((theState) ? true: false);
inputHandler->SetEnableAutohold((theState) ? true: false);
}
- (BOOL) autohold
{
return (execControl->GetEnableAutohold()) ? YES : NO;
return (inputHandler->GetEnableAutohold()) ? YES : NO;
}
- (void) setPaddleAdjust:(NSInteger)paddleAdjust
{
execControl->SetClientPaddleAdjust((int16_t)paddleAdjust);
inputHandler->SetClientPaddleAdjust((int16_t)paddleAdjust);
}
- (NSInteger) paddleAdjust
{
return (NSInteger)execControl->GetClientPaddleAdjust();
return (NSInteger)inputHandler->GetClientPaddleAdjust();
}
- (void) setControllerState:(BOOL)theState controlID:(const NSUInteger)controlID
{
execControl->SetClientInputStateUsingID((NDSInputID)controlID,
(theState) ? true : false,
false,
0,
0);
inputHandler->SetClientInputStateUsingID((NDSInputID)controlID,
(theState) ? true : false,
false,
0,
0);
}
- (void) setControllerState:(BOOL)theState controlID:(const NSUInteger)controlID turbo:(const BOOL)isTurboEnabled turboPattern:(uint32_t)turboPattern turboPatternLength:(uint32_t)turboPatternLength
{
execControl->SetClientInputStateUsingID((NDSInputID)controlID,
(theState) ? true : false,
(isTurboEnabled) ? true : false,
turboPattern,
turboPatternLength);
inputHandler->SetClientInputStateUsingID((NDSInputID)controlID,
(theState) ? true : false,
(isTurboEnabled) ? true : false,
turboPattern,
turboPatternLength);
}
- (void) setTouchState:(BOOL)theState location:(const NSPoint)theLocation
{
execControl->SetClientTouchState((theState) ? true : false,
(uint8_t)(theLocation.x + 0.3f),
(uint8_t)(theLocation.y + 0.3f),
(uint8_t)[self stylusPressure]);
inputHandler->SetClientTouchState((theState) ? true : false,
(uint8_t)(theLocation.x + 0.3f),
(uint8_t)(theLocation.y + 0.3f),
(uint8_t)[self stylusPressure]);
}
- (void) setSineWaveGeneratorFrequency:(const double)freq
{
execControl->SetSineWaveFrequency(freq);
inputHandler->SetSineWaveFrequency(freq);
}
- (void) clearAutohold
{
execControl->ClearAutohold();
inputHandler->ClearAutohold();
}
- (void) reset
@ -270,7 +277,7 @@
{
uint8_t theSample = MIC_NULL_SAMPLE_VALUE;
if (!execControl->GetClientSoftwareMicStateApplied() && (caInput != NULL))
if (!inputHandler->GetClientSoftwareMicStateApplied() && (caInput != NULL))
{
if (caInput->GetPauseState())
{

View File

@ -18,7 +18,7 @@
#include "coreaudiosound.h"
#include <CoreAudio/CoreAudio.h>
#include "ClientExecutionControl.h"
#include "ClientInputHandler.h"
#include "utilities.h"
#import "cocoa_globals.h"

View File

@ -16,7 +16,7 @@
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ClientExecutionControl.h"
#include "ClientInputHandler.h"
#include "mic_ext.h"
#include "../../emufile.h"
#include "../../readwrite.h"

View File

@ -2141,23 +2141,24 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
BOOL isHandled = NO;
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue, [hidManager inputManager], false);
MacInputDevicePropertiesEncoder *inputEncoder = [[hidManager inputManager] inputEncoder];
ClientInputDevicePropertiesList inputPropertyList = inputEncoder->EncodeHIDQueue(hidQueue, [hidManager inputManager], false);
NSString *newStatusText = nil;
const size_t inputCount = inputList.size();
const size_t inputCount = inputPropertyList.size();
for (size_t i = 0; i < inputCount; i++)
{
const InputAttributes &inputAttr = inputList[i];
const ClientInputDeviceProperties &inputProperty = inputPropertyList[i];
if (inputAttr.isAnalog)
if (inputProperty.isAnalog)
{
newStatusText = [NSString stringWithFormat:@"%s:%s (%1.2f)", inputAttr.deviceName, inputAttr.elementName, inputAttr.scalar];
newStatusText = [NSString stringWithFormat:@"%s:%s (%1.2f)", inputProperty.deviceName, inputProperty.elementName, inputProperty.scalar];
break;
}
else if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
else if (inputProperty.state == ClientInputDeviceState_On)
{
newStatusText = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName];
newStatusText = [NSString stringWithFormat:@"%s:%s", inputProperty.deviceName, inputProperty.elementName];
break;
}
}
@ -2167,7 +2168,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
[[windowController emuControl] setStatusText:newStatusText];
}
CommandAttributesList cmdList = [inputManager generateCommandListUsingInputList:&inputList];
CommandAttributesList cmdList = [inputManager generateCommandListUsingInputList:&inputPropertyList];
if (cmdList.empty())
{
return isHandled;
@ -2184,15 +2185,16 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
BOOL isHandled = NO;
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
const InputAttributes inputAttr = InputManagerEncodeKeyboardInput([theEvent keyCode], keyPressed);
MacInputDevicePropertiesEncoder *inputEncoder = [inputManager inputEncoder];
const ClientInputDeviceProperties inputProperty = inputEncoder->EncodeKeyboardInput((int32_t)[theEvent keyCode], (keyPressed) ? true : false);
if (keyPressed && [theEvent window] != nil)
{
NSString *newStatusText = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName];
NSString *newStatusText = [NSString stringWithFormat:@"%s:%s", inputProperty.deviceName, inputProperty.elementName];
[[windowController emuControl] setStatusText:newStatusText];
}
isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr];
isHandled = [inputManager dispatchCommandUsingInputProperties:&inputProperty];
return isHandled;
}
@ -2205,7 +2207,7 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
// Convert the clicked location from window coordinates, to view coordinates,
// and finally to DS touchscreen coordinates.
const NSInteger buttonNumber = [theEvent buttonNumber];
const int32_t buttonNumber = (int32_t)[theEvent buttonNumber];
uint8_t x = 0;
uint8_t y = 0;
@ -2219,15 +2221,16 @@ static std::unordered_map<NSScreen *, DisplayWindowController *> _screenMap; //
cdv->GetNDSPoint((int)buttonNumber, isInitialMouseDown, clientLoc.x, clientLoc.y, x, y);
}
const InputAttributes inputAttr = InputManagerEncodeMouseButtonInput(buttonNumber, NSMakePoint(x, y), buttonPressed);
MacInputDevicePropertiesEncoder *inputEncoder = [inputManager inputEncoder];
const ClientInputDeviceProperties inputProperty = inputEncoder->EncodeMouseInput(buttonNumber, (float)x, (float)y, (buttonPressed) ? true : false);
if (buttonPressed && [theEvent window] != nil)
{
NSString *newStatusText = (displayMode == ClientDisplayMode_Main) ? [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName] : [NSString stringWithFormat:@"%s:%s X:%i Y:%i", inputAttr.deviceName, inputAttr.elementName, (int)inputAttr.intCoordX, (int)inputAttr.intCoordY];
NSString *newStatusText = (displayMode == ClientDisplayMode_Main) ? [NSString stringWithFormat:@"%s:%s", inputProperty.deviceName, inputProperty.elementName] : [NSString stringWithFormat:@"%s:%s X:%i Y:%i", inputProperty.deviceName, inputProperty.elementName, (int)inputProperty.intCoordX, (int)inputProperty.intCoordY];
[[windowController emuControl] setStatusText:newStatusText];
}
isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr];
isHandled = [inputManager dispatchCommandUsingInputProperties:&inputProperty];
return isHandled;
}

View File

@ -1003,7 +1003,7 @@
{
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
const NSUInteger controlID = cmdAttr.intValue[0];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
@ -1025,7 +1025,7 @@
{
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
const NSUInteger controlID = cmdAttr.intValue[0];
const BOOL isTurboEnabled = (BOOL)cmdAttr.intValue[1];
const uint32_t turboPattern = (uint32_t)cmdAttr.intValue[2];
@ -1050,7 +1050,7 @@
{
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
const NSPoint touchLoc = (cmdAttr.useInputForIntCoord) ? NSMakePoint(cmdAttr.input.intCoordX, cmdAttr.input.intCoordY) : NSMakePoint(cmdAttr.intValue[1], cmdAttr.intValue[2]);
if (touchLoc.x >= 0.0 && touchLoc.y >= 0.0)
@ -1075,7 +1075,7 @@
{
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
CocoaDSController *cdsController = [cdsCore cdsController];
@ -1119,7 +1119,7 @@
}
else
{
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
const NSInteger paddleAdjust = (theState) ? cmdAttr.intValue[1] : 0;
[[cdsCore cdsController] setPaddleAdjust:paddleAdjust];
}
@ -1129,7 +1129,7 @@
{
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
const BOOL theState = (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_ON) ? YES : NO;
const BOOL theState = (cmdAttr.input.state == ClientInputDeviceState_On) ? YES : NO;
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
[[cdsCore cdsController] setAutohold:theState];
@ -1141,7 +1141,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1157,7 +1157,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1195,7 +1195,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1245,7 +1245,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1260,7 +1260,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1305,7 +1305,7 @@
const float inputSpeedScalar = (cmdAttr.useInputForScalar) ? cmdAttr.input.scalar : cmdAttr.floatValue[0];
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
[cdsCore setSpeedScalar:(cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) ? lastSetSpeedScalar : inputSpeedScalar];
[cdsCore setSpeedScalar:(cmdAttr.input.state == ClientInputDeviceState_Off) ? lastSetSpeedScalar : inputSpeedScalar];
[self setVerticalSyncForNonLayerBackedViews:nil];
}
@ -1314,7 +1314,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1342,7 +1342,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1370,7 +1370,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1396,7 +1396,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) || ([self currentRom] == nil) )
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) || ([self currentRom] == nil) )
{
return;
}
@ -1418,7 +1418,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) || ([self currentRom] == nil) )
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) || ([self currentRom] == nil) )
{
return;
}
@ -1431,7 +1431,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) || ([self currentRom] == nil) )
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) || ([self currentRom] == nil) )
{
return;
}
@ -1446,7 +1446,7 @@
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) ||
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) ||
([cdsCore coreState] != ExecutionBehavior_Pause) ||
([self currentRom] == nil) )
{
@ -1461,7 +1461,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) || ([self currentRom] == nil) )
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) || ([self currentRom] == nil) )
{
return;
}
@ -1477,7 +1477,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if ( (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF) || ([self currentRom] == nil) )
if ( (cmdAttr.input.state == ClientInputDeviceState_Off) || ([self currentRom] == nil) )
{
return;
}
@ -1513,7 +1513,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}
@ -1541,7 +1541,7 @@
CommandAttributes cmdAttr;
[cmdAttrValue getValue:&cmdAttr];
if (cmdAttr.input.state == INPUT_ATTRIBUTE_STATE_OFF)
if (cmdAttr.input.state == ClientInputDeviceState_Off)
{
return;
}

View File

@ -31,16 +31,10 @@
#include <vector>
#include "../audiosamplegenerator.h"
#include "../ClientInputHandler.h"
#define INPUT_HANDLER_STRING_LENGTH 256
enum InputAttributeState
{
INPUT_ATTRIBUTE_STATE_OFF = 0,
INPUT_ATTRIBUTE_STATE_ON,
INPUT_ATTRIBUTE_STATE_MIXED
};
struct ClientInputDeviceProperties;
class MacInputDevicePropertiesEncoder;
@class EmuControllerDelegate;
@class InputManager;
@class InputHIDManager;
@ -52,41 +46,23 @@ enum InputAttributeState
@end
typedef struct
{
char deviceName[INPUT_HANDLER_STRING_LENGTH];
char deviceCode[INPUT_HANDLER_STRING_LENGTH];
char elementName[INPUT_HANDLER_STRING_LENGTH];
char elementCode[INPUT_HANDLER_STRING_LENGTH];
bool isAnalog; // This is an analog input, as opposed to being a digital input.
InputAttributeState state; // The input state that is sent on command dispatch
int32_t intCoordX; // The X-coordinate as an int for commands that require a location
int32_t intCoordY; // The Y-coordinate as an int for commands that require a location
float floatCoordX; // The X-coordinate as a float for commands that require a location
float floatCoordY; // The Y-coordinate as a float for commands that require a location
float scalar; // A scalar value for commands that require a scalar
void *object; // An object for commands that require an object
} InputAttributes;
typedef struct
{
char tag[INPUT_HANDLER_STRING_LENGTH]; // A string identifier for these attributes
SEL selector; // The selector that is called on command dispatch
int32_t intValue[4]; // Context dependent int values
float floatValue[4]; // Context dependent float values
void *object[4]; // Context dependent objects
SEL selector; // The selector that is called on command dispatch
int32_t intValue[4]; // Context dependent int values
float floatValue[4]; // Context dependent float values
void *object[4]; // Context dependent objects
bool useInputForIntCoord; // The command will prefer the input device's int coordinate
bool useInputForFloatCoord; // The command will prefer the input device's float coordinate
bool useInputForScalar; // The command will prefer the input device's scalar
bool useInputForSender; // The command will prefer the input device's sender
bool useInputForIntCoord; // The command will prefer the input device's int coordinate
bool useInputForFloatCoord; // The command will prefer the input device's float coordinate
bool useInputForScalar; // The command will prefer the input device's scalar
bool useInputForSender; // The command will prefer the input device's sender
InputAttributes input; // The input device's attributes
bool allowAnalogInput; // Flag for allowing a command to accept analog inputs
ClientInputDeviceProperties input; // The input device's properties
bool allowAnalogInput; // Flag for allowing a command to accept analog inputs
} CommandAttributes;
typedef std::vector<InputAttributes> InputAttributesList;
typedef std::vector<CommandAttributes> CommandAttributesList;
#if defined(__ppc__) || defined(__ppc64__)
@ -94,16 +70,19 @@ typedef std::map<std::string, CommandAttributes> InputCommandMap; // Key = Input
typedef std::map<std::string, CommandAttributes> CommandAttributesMap; // Key = Command Tag, Value = CommandAttributes
typedef std::map<std::string, SEL> CommandSelectorMap; // Key = Command Tag, Value = Obj-C Selector
typedef std::map<std::string, AudioSampleBlockGenerator> AudioFileSampleGeneratorMap; // Key = File path to audio file, Value = AudioSampleBlockGenerator
typedef std::map<int32_t, std::string> KeyboardKeyNameMap; // Key = Key code, Value = Key name
#elif !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_6)
typedef std::tr1::unordered_map<std::string, CommandAttributes> InputCommandMap; // Key = Input key in deviceCode:elementCode format, Value = CommandAttributes
typedef std::tr1::unordered_map<std::string, CommandAttributes> CommandAttributesMap; // Key = Command Tag, Value = CommandAttributes
typedef std::tr1::unordered_map<std::string, SEL> CommandSelectorMap; // Key = Command Tag, Value = Obj-C Selector
typedef std::tr1::unordered_map<std::string, AudioSampleBlockGenerator> AudioFileSampleGeneratorMap; // Key = File path to audio file, Value = AudioSampleBlockGenerator
typedef std::tr1::unordered_map<int32_t, std::string> KeyboardKeyNameMap; // Key = Key code, Value = Key name
#else
typedef std::unordered_map<std::string, CommandAttributes> InputCommandMap; // Key = Input key in deviceCode:elementCode format, Value = CommandAttributes
typedef std::unordered_map<std::string, CommandAttributes> CommandAttributesMap; // Key = Command Tag, Value = CommandAttributes
typedef std::unordered_map<std::string, SEL> CommandSelectorMap; // Key = Command Tag, Value = Obj-C Selector
typedef std::unordered_map<std::string, AudioSampleBlockGenerator> AudioFileSampleGeneratorMap; // Key = File path to audio file, Value = AudioSampleBlockGenerator
typedef std::unordered_map<int32_t, std::string> KeyboardKeyNameMap; // Key = Key code, Value = Key name
#endif
#pragma mark -
@ -153,8 +132,8 @@ bool InputElementCodeFromHIDElement(const IOHIDElementRef hidElementRef, char *c
bool InputElementNameFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer);
bool InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer);
bool InputDeviceNameFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer);
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef);
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput);
ClientInputDeviceProperties InputAttributesOfHIDValue(IOHIDValueRef hidValueRef);
ClientInputDevicePropertiesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput);
size_t ClearHIDQueue(const IOHIDQueueRef hidQueue);
void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender);
@ -188,6 +167,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
@interface InputManager : NSObject
{
EmuControllerDelegate *emuControl;
MacInputDevicePropertiesEncoder *inputEncoder;
id<InputHIDManagerTarget> hidInputTarget;
InputHIDManager *hidManager;
NSMutableDictionary *inputMappings;
@ -201,6 +181,7 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
}
@property (readonly) IBOutlet EmuControllerDelegate *emuControl;
@property (readonly) MacInputDevicePropertiesEncoder *inputEncoder;
@property (retain) id<InputHIDManagerTarget> hidInputTarget;
@property (readonly) InputHIDManager *hidManager;
@property (readonly) NSMutableDictionary *inputMappings;
@ -209,17 +190,17 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
- (void) setMappingsWithMappings:(NSDictionary *)mappings;
- (void) addMappingUsingDeviceInfoDictionary:(NSDictionary *)deviceDict commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingUsingInputList:(const InputAttributesList *)inputList commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingUsingInputAttributes:(const ClientInputDeviceProperties *)inputProperty commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingUsingInputList:(const ClientInputDevicePropertiesList *)inputPropertyList commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingForIBAction:(const SEL)theSelector commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) addMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode commandAttributes:(const CommandAttributes *)cmdAttr;
- (void) removeMappingUsingDeviceCode:(const char *)deviceCode elementCode:(const char *)elementCode;
- (void) removeAllMappingsForCommandTag:(const char *)commandTag;
- (CommandAttributesList) generateCommandListUsingInputList:(const InputAttributesList *)inputList;
- (CommandAttributesList) generateCommandListUsingInputList:(const ClientInputDevicePropertiesList *)inputPropertyList;
- (void) dispatchCommandList:(const CommandAttributesList *)cmdList;
- (BOOL) dispatchCommandUsingInputAttributes:(const InputAttributes *)inputAttr;
- (BOOL) dispatchCommandUsingInputProperties:(const ClientInputDeviceProperties *)inputProperty;
- (BOOL) dispatchCommandUsingIBAction:(const SEL)theSelector sender:(id)sender;
- (void) writeDefaultsInputMappings;
@ -235,9 +216,11 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
- (AudioSampleBlockGenerator *) audioFileGeneratorFromFilePath:(NSString *)filePath;
- (void) updateAudioFileGenerators;
@end
CommandAttributes NewDefaultCommandAttributes(const char *commandTag);
CommandAttributes NewCommandAttributesForSelector(const char *commandTag, const SEL theSelector);
CommandAttributes NewCommandAttributesForDSControl(const char *commandTag, const NSUInteger controlID);
CommandAttributes NewCommandAttributesForDSControl(const char *commandTag, const NDSInputID controlID);
void UpdateCommandAttributesWithDeviceInfoDictionary(CommandAttributes *cmdAttr, NSDictionary *deviceInfo);
NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttributes *cmdAttr,
@ -246,9 +229,16 @@ NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttr
NSString *elementCode,
NSString *elementName);
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput);
InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BOOL keyPressed);
InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber, const NSPoint touchLoc, BOOL buttonPressed);
InputAttributes InputManagerEncodeIBAction(const SEL theSelector, id sender);
@end
class MacInputDevicePropertiesEncoder : public ClientInputDevicePropertiesEncoder
{
private:
KeyboardKeyNameMap _keyboardNameTable;
public:
MacInputDevicePropertiesEncoder();
virtual ClientInputDeviceProperties EncodeKeyboardInput(const int32_t keyCode, bool keyPressed);
virtual ClientInputDeviceProperties EncodeMouseInput(const int32_t buttonNumber, float touchLocX, float touchLocY, bool buttonPressed);
virtual ClientInputDeviceProperties EncodeIBAction(const SEL theSelector, id sender);
virtual ClientInputDevicePropertiesList EncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput);
};

View File

@ -415,31 +415,31 @@ static NSDictionary *hidUsageTable = nil;
hidValueRef - The IOHIDValueRef to parse.
Returns:
An InputAttributes struct with the parsed input attributes.
A ClientInputDeviceProperties struct with the parsed input device's properties.
Details:
None.
********************************************************************************************/
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef)
ClientInputDeviceProperties InputAttributesOfHIDValue(IOHIDValueRef hidValueRef)
{
InputAttributes inputAttr;
ClientInputDeviceProperties inputProperty;
if (hidValueRef == NULL)
{
return inputAttr;
return inputProperty;
}
const IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
const IOHIDDeviceRef hidDeviceRef = IOHIDElementGetDevice(hidElementRef);
InputElementCodeFromHIDElement(hidElementRef, inputAttr.elementCode);
InputDeviceCodeFromHIDDevice(hidDeviceRef, inputAttr.deviceCode);
InputElementCodeFromHIDElement(hidElementRef, inputProperty.elementCode);
InputDeviceCodeFromHIDDevice(hidDeviceRef, inputProperty.deviceCode);
strncpy(inputAttr.elementName, inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH);
InputElementNameFromHIDElement(hidElementRef, inputAttr.elementName);
strncpy(inputProperty.elementName, inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH);
InputElementNameFromHIDElement(hidElementRef, inputProperty.elementName);
strncpy(inputAttr.deviceName, inputAttr.deviceCode, INPUT_HANDLER_STRING_LENGTH);
InputDeviceNameFromHIDDevice(hidDeviceRef, inputAttr.deviceName);
strncpy(inputProperty.deviceName, inputProperty.deviceCode, INPUT_HANDLER_STRING_LENGTH);
InputDeviceNameFromHIDDevice(hidDeviceRef, inputProperty.deviceName);
const NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef);
const NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef);
@ -447,23 +447,23 @@ InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef)
const NSInteger elementType = IOHIDElementGetType(hidElementRef);
const NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
inputAttr.isAnalog = (elementType != kIOHIDElementTypeInput_Button) && !(logicalMin == 0 && logicalMax == 1);
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;
inputAttr.floatCoordX = 0.0f;
inputAttr.floatCoordY = 0.0f;
inputAttr.scalar = (float)(logicalValue - logicalMin) / (float)(logicalMax - logicalMin);
inputAttr.object = nil;
inputProperty.isAnalog = (elementType != kIOHIDElementTypeInput_Button) && !(logicalMin == 0 && logicalMax == 1);
inputProperty.intCoordX = 0;
inputProperty.intCoordY = 0;
inputProperty.floatCoordX = 0.0f;
inputProperty.floatCoordY = 0.0f;
inputProperty.scalar = (float)(logicalValue - logicalMin) / (float)(logicalMax - logicalMin);
inputProperty.object = NULL;
if (!inputAttr.isAnalog)
if (!inputProperty.isAnalog)
{
inputAttr.state = (logicalValue == 1) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputProperty.state = (logicalValue == 1) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
}
else if (elementUsage == kHIDUsage_GD_Hatswitch)
{
// For hatswitch inputs, use the intCoord fields to store the axis information.
inputAttr.state = (logicalValue >= logicalMin && logicalValue <= logicalMax) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
inputProperty.state = (logicalValue >= logicalMin && logicalValue <= logicalMax) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
if (inputProperty.state == ClientInputDeviceState_On)
{
struct IntCoord
{
@ -491,31 +491,31 @@ InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef)
if (logicalMax == 3) // For a 4-way hatswitch
{
inputAttr.intCoordX = coords4Way[logicalValue].x;
inputAttr.intCoordY = coords4Way[logicalValue].y;
inputProperty.intCoordX = coords4Way[logicalValue].x;
inputProperty.intCoordY = coords4Way[logicalValue].y;
}
else if (logicalMax == 7) // For an 8-way hatswitch
{
inputAttr.intCoordX = coords8Way[logicalValue].x;
inputAttr.intCoordY = coords8Way[logicalValue].y;
inputProperty.intCoordX = coords8Way[logicalValue].x;
inputProperty.intCoordY = coords8Way[logicalValue].y;
}
}
}
else // Some generic analog input
{
inputAttr.state = (inputAttr.scalar <= 0.30f || inputAttr.scalar >= 0.7f) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputProperty.state = (inputProperty.scalar <= 0.30f || inputProperty.scalar >= 0.7f) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
}
return inputAttr;
return inputProperty;
}
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput)
ClientInputDevicePropertiesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput)
{
InputAttributesList inputList;
ClientInputDevicePropertiesList inputPropertyList;
if (hidValueRef == NULL)
{
return inputList;
return inputPropertyList;
}
// IOHIDValueGetIntegerValue() will crash if the value length is too large.
@ -523,18 +523,18 @@ InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManage
// controller usable, since it returns a length of 39 on some elements.
if(IOHIDValueGetLength(hidValueRef) > 2)
{
return inputList;
return inputPropertyList;
}
InputAttributes inputAttr = InputAttributesOfHIDValue(hidValueRef);
if (inputAttr.deviceCode[0] == '\0' || inputAttr.elementCode[0] == '\0')
ClientInputDeviceProperties inputProperty = InputAttributesOfHIDValue(hidValueRef);
if (inputProperty.deviceCode[0] == '\0' || inputProperty.elementCode[0] == '\0')
{
return inputList;
return inputPropertyList;
}
if (!inputAttr.isAnalog)
if (!inputProperty.isAnalog)
{
inputList.push_back(inputAttr);
inputPropertyList.push_back(inputProperty);
}
else
{
@ -543,75 +543,75 @@ InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManage
if (elementUsage == kHIDUsage_GD_Hatswitch)
{
InputAttributes hatUp = inputAttr;
ClientInputDeviceProperties hatUp = inputProperty;
hatUp.isAnalog = false;
strncat(hatUp.elementName, "/Up", 4);
strncat(hatUp.elementCode, "/Up", 4);
InputAttributes hatRight = inputAttr;
ClientInputDeviceProperties hatRight = inputProperty;
hatRight.isAnalog = false;
strncat(hatRight.elementName, "/Right", 7);
strncat(hatRight.elementCode, "/Right", 7);
InputAttributes hatDown = inputAttr;
ClientInputDeviceProperties hatDown = inputProperty;
hatDown.isAnalog = false;
strncat(hatDown.elementName, "/Down", 6);
strncat(hatDown.elementCode, "/Down", 6);
InputAttributes hatLeft = inputAttr;
ClientInputDeviceProperties hatLeft = inputProperty;
hatLeft.isAnalog = false;
strncat(hatLeft.elementName, "/Left", 6);
strncat(hatLeft.elementCode, "/Left", 6);
if (inputAttr.intCoordX == -1)
if (inputProperty.intCoordX == -1)
{
hatRight.state = INPUT_ATTRIBUTE_STATE_OFF;
hatLeft.state = INPUT_ATTRIBUTE_STATE_ON;
hatRight.state = ClientInputDeviceState_Off;
hatLeft.state = ClientInputDeviceState_On;
}
else if (inputAttr.intCoordX == 1)
else if (inputProperty.intCoordX == 1)
{
hatRight.state = INPUT_ATTRIBUTE_STATE_ON;
hatLeft.state = INPUT_ATTRIBUTE_STATE_OFF;
hatRight.state = ClientInputDeviceState_On;
hatLeft.state = ClientInputDeviceState_Off;
}
else
{
hatRight.state = INPUT_ATTRIBUTE_STATE_OFF;
hatLeft.state = INPUT_ATTRIBUTE_STATE_OFF;
hatRight.state = ClientInputDeviceState_Off;
hatLeft.state = ClientInputDeviceState_Off;
}
if (inputAttr.intCoordY == -1)
if (inputProperty.intCoordY == -1)
{
hatDown.state = INPUT_ATTRIBUTE_STATE_OFF;
hatUp.state = INPUT_ATTRIBUTE_STATE_ON;
hatDown.state = ClientInputDeviceState_Off;
hatUp.state = ClientInputDeviceState_On;
}
else if (inputAttr.intCoordY == 1)
else if (inputProperty.intCoordY == 1)
{
hatDown.state = INPUT_ATTRIBUTE_STATE_ON;
hatUp.state = INPUT_ATTRIBUTE_STATE_OFF;
hatDown.state = ClientInputDeviceState_On;
hatUp.state = ClientInputDeviceState_Off;
}
else
{
hatDown.state = INPUT_ATTRIBUTE_STATE_OFF;
hatUp.state = INPUT_ATTRIBUTE_STATE_OFF;
hatDown.state = ClientInputDeviceState_Off;
hatUp.state = ClientInputDeviceState_Off;
}
inputList.resize(4);
inputList.push_back(hatUp);
inputList.push_back(hatRight);
inputList.push_back(hatDown);
inputList.push_back(hatLeft);
inputPropertyList.resize(4);
inputPropertyList.push_back(hatUp);
inputPropertyList.push_back(hatRight);
inputPropertyList.push_back(hatDown);
inputPropertyList.push_back(hatLeft);
}
else
{
CommandAttributes cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:inputAttr.elementCode];
CommandAttributes cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputProperty.deviceCode elementCode:inputProperty.elementCode];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
std::string tempElementCode = std::string(inputAttr.elementCode) + "/LowerThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:tempElementCode.c_str()];
std::string tempElementCode = std::string(inputProperty.elementCode) + "/LowerThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputProperty.deviceCode elementCode:tempElementCode.c_str()];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
tempElementCode = std::string(inputAttr.elementCode) + "/UpperThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:tempElementCode.c_str()];
tempElementCode = std::string(inputProperty.elementCode) + "/UpperThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputProperty.deviceCode elementCode:tempElementCode.c_str()];
}
}
@ -619,44 +619,44 @@ InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManage
if (useAnalog)
{
inputList.push_back(inputAttr);
inputPropertyList.push_back(inputProperty);
}
else
{
InputAttributes loInputAttr = inputAttr;
loInputAttr.isAnalog = false;
strncat(loInputAttr.elementName, "-", 2);
strncat(loInputAttr.elementCode, "/LowerThreshold", 16);
ClientInputDeviceProperties loInputProperty = inputProperty;
loInputProperty.isAnalog = false;
strncat(loInputProperty.elementName, "-", 2);
strncat(loInputProperty.elementCode, "/LowerThreshold", 16);
InputAttributes hiInputAttr = inputAttr;
hiInputAttr.isAnalog = false;
strncat(hiInputAttr.elementName, "+", 2);
strncat(hiInputAttr.elementCode, "/UpperThreshold", 16);
ClientInputDeviceProperties hiInputProperty = inputProperty;
hiInputProperty.isAnalog = false;
strncat(hiInputProperty.elementName, "+", 2);
strncat(hiInputProperty.elementCode, "/UpperThreshold", 16);
if (loInputAttr.scalar <= 0.30f)
if (loInputProperty.scalar <= 0.30f)
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
loInputProperty.state = ClientInputDeviceState_On;
hiInputProperty.state = ClientInputDeviceState_Off;
}
else if (loInputAttr.scalar >= 0.70f)
else if (loInputProperty.scalar >= 0.70f)
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
loInputProperty.state = ClientInputDeviceState_Off;
hiInputProperty.state = ClientInputDeviceState_On;
}
else
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
loInputProperty.state = ClientInputDeviceState_Off;
hiInputProperty.state = ClientInputDeviceState_Off;
}
inputList.resize(2);
inputList.push_back(loInputAttr);
inputList.push_back(hiInputAttr);
inputPropertyList.resize(2);
inputPropertyList.push_back(loInputProperty);
inputPropertyList.push_back(hiInputProperty);
}
}
}
return inputList;
return inputPropertyList;
}
bool InputElementCodeFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer)
@ -976,20 +976,13 @@ void HandleDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSen
@implementation InputManager
@synthesize emuControl;
@synthesize inputEncoder;
@dynamic hidInputTarget;
@synthesize hidManager;
@synthesize inputMappings;
@synthesize commandTagList;
@synthesize commandIcon;
#if defined(__ppc__) || defined(__ppc64__)
static std::map<unsigned short, std::string> keyboardNameTable; // Key = Key code, Value = Key name
#elif !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_6)
static std::tr1::unordered_map<unsigned short, std::string> keyboardNameTable; // Key = Key code, Value = Key name
#else
static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key = Key code, Value = Key name
#endif
- (id)init
{
self = [super init];
@ -998,18 +991,7 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
return self;
}
if (keyboardNameTable.empty())
{
NSDictionary *keyboardNameDict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"KeyNames" ofType:@"plist"]];
NSArray *keyboardDictKeyList = [keyboardNameDict allKeys];
for (NSString *dKey in keyboardDictKeyList)
{
unsigned short keyCode = (unsigned short)[dKey intValue];
keyboardNameTable[keyCode] = std::string([(NSString *)[keyboardNameDict valueForKey:dKey] cStringUsingEncoding:NSUTF8StringEncoding]);
}
}
inputEncoder = new MacInputDevicePropertiesEncoder;
hidManager = [[InputHIDManager alloc] initWithInputManager:self];
inputMappings = [[NSMutableDictionary alloc] initWithCapacity:128];
commandTagList = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DefaultKeyMappings" ofType:@"plist"]] valueForKey:@"CommandTagList"];
@ -1285,6 +1267,8 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
[commandTagList release];
[commandIcon release];
delete inputEncoder;
[super dealloc];
}
@ -1396,41 +1380,41 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
}
}
- (void) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandAttributes:(const CommandAttributes *)cmdAttr
- (void) addMappingUsingInputAttributes:(const ClientInputDeviceProperties *)inputProperty commandAttributes:(const CommandAttributes *)cmdAttr
{
if (inputAttr == NULL)
if (inputProperty == NULL)
{
return;
}
NSMutableDictionary *deviceInfo = DeviceInfoDictionaryWithCommandAttributes(cmdAttr,
[NSString stringWithCString:inputAttr->deviceCode encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputAttr->deviceName encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputAttr->elementCode encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputAttr->elementName encoding:NSUTF8StringEncoding]);
[NSString stringWithCString:inputProperty->deviceCode encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputProperty->deviceName encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputProperty->elementCode encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputProperty->elementName encoding:NSUTF8StringEncoding]);
[deviceInfo setValue:[NSNumber numberWithBool:(cmdAttr->allowAnalogInput) ? inputAttr->isAnalog : NO] forKey:@"isInputAnalog"];
[deviceInfo setValue:[NSNumber numberWithBool:(cmdAttr->allowAnalogInput) ? inputProperty->isAnalog : NO] forKey:@"isInputAnalog"];
[self addMappingUsingDeviceInfoDictionary:deviceInfo commandAttributes:cmdAttr];
}
- (void) addMappingUsingInputList:(const InputAttributesList *)inputList commandAttributes:(const CommandAttributes *)cmdAttr
- (void) addMappingUsingInputList:(const ClientInputDevicePropertiesList *)inputPropertyList commandAttributes:(const CommandAttributes *)cmdAttr
{
if (inputList == NULL)
if (inputPropertyList == NULL)
{
return;
}
const size_t inputCount = inputList->size();
const size_t inputCount = inputPropertyList->size();
for (size_t i = 0; i < inputCount; i++)
{
const InputAttributes &inputAttr = (*inputList)[i];
if (inputAttr.state != INPUT_ATTRIBUTE_STATE_ON)
const ClientInputDeviceProperties &inputProperty = (*inputPropertyList)[i];
if (inputProperty.state != ClientInputDeviceState_On)
{
continue;
}
[self addMappingUsingInputAttributes:&inputAttr commandAttributes:cmdAttr];
[self addMappingUsingInputAttributes:&inputProperty commandAttributes:cmdAttr];
}
}
@ -1515,31 +1499,31 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
[inputList removeAllObjects];
}
- (CommandAttributesList) generateCommandListUsingInputList:(const InputAttributesList *)inputList
- (CommandAttributesList) generateCommandListUsingInputList:(const ClientInputDevicePropertiesList *)inputPropertyList
{
CommandAttributesList cmdList;
const size_t inputCount = inputList->size();
const size_t inputCount = inputPropertyList->size();
for (size_t i = 0; i < inputCount; i++)
{
const InputAttributes &inputAttr = (*inputList)[i];
const ClientInputDeviceProperties &inputProperty = (*inputPropertyList)[i];
// All inputs require a device code and element code for mapping. If one or both are
// not present, reject the input.
if (inputAttr.deviceCode[0] == '\0' || inputAttr.elementCode[0] == '\0')
if (inputProperty.deviceCode[0] == '\0' || inputProperty.elementCode[0] == '\0')
{
continue;
}
// Look up the command attributes using the input key.
const std::string inputKey = std::string(inputAttr.deviceCode) + ":" + std::string(inputAttr.elementCode);
const std::string inputKey = std::string(inputProperty.deviceCode) + ":" + std::string(inputProperty.elementCode);
CommandAttributes cmdAttr = commandMap[inputKey];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
continue;
}
cmdAttr.input = inputAttr; // Copy the input state to the command attributes.
cmdAttr.input = inputProperty; // Copy the input state to the command attributes.
cmdList.push_back(cmdAttr); // Add the command attributes to the list.
}
@ -1562,19 +1546,19 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
}
}
- (BOOL) dispatchCommandUsingInputAttributes:(const InputAttributes *)inputAttr
- (BOOL) dispatchCommandUsingInputProperties:(const ClientInputDeviceProperties *)inputProperty
{
BOOL didCommandDispatch = NO;
// All inputs require a device code and element code for mapping. If one or both are
// not present, reject the input.
if (inputAttr->deviceCode[0] == '\0' || inputAttr->elementCode[0] == '\0')
if (inputProperty->deviceCode[0] == '\0' || inputProperty->elementCode[0] == '\0')
{
return didCommandDispatch;
}
// Look up the command key using the input key.
const std::string inputKey = std::string(inputAttr->deviceCode) + ":" + std::string(inputAttr->elementCode);
const std::string inputKey = std::string(inputProperty->deviceCode) + ":" + std::string(inputProperty->elementCode);
CommandAttributes cmdAttr = commandMap[inputKey];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
@ -1582,7 +1566,7 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
}
// Copy the input state to the command attributes.
cmdAttr.input = *inputAttr;
cmdAttr.input = *inputProperty;
if ([emuControl respondsToSelector:cmdAttr.selector])
{
@ -1597,8 +1581,8 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
- (BOOL) dispatchCommandUsingIBAction:(const SEL)theSelector sender:(id)sender
{
const InputAttributes inputAttr = InputManagerEncodeIBAction(theSelector, sender);
return [self dispatchCommandUsingInputAttributes:&inputAttr];
const ClientInputDeviceProperties inputProperty = inputEncoder->EncodeIBAction(theSelector, sender);
return [self dispatchCommandUsingInputProperties:&inputProperty];
}
- (void) writeDefaultsInputMappings
@ -1990,6 +1974,8 @@ static std::unordered_map<unsigned short, std::string> keyboardNameTable; // Key
}
}
@end
CommandAttributes NewDefaultCommandAttributes(const char *commandTag)
{
CommandAttributes cmdAttr;
@ -2004,10 +1990,10 @@ CommandAttributes NewDefaultCommandAttributes(const char *commandTag)
cmdAttr.floatValue[1] = 0;
cmdAttr.floatValue[2] = 0;
cmdAttr.floatValue[3] = 0;
cmdAttr.object[0] = nil;
cmdAttr.object[1] = nil;
cmdAttr.object[2] = nil;
cmdAttr.object[3] = nil;
cmdAttr.object[0] = NULL;
cmdAttr.object[1] = NULL;
cmdAttr.object[2] = NULL;
cmdAttr.object[3] = NULL;
cmdAttr.useInputForIntCoord = false;
cmdAttr.useInputForFloatCoord = false;
@ -2026,7 +2012,7 @@ CommandAttributes NewCommandAttributesForSelector(const char *commandTag, const
return cmdAttr;
}
CommandAttributes NewCommandAttributesForDSControl(const char *commandTag, const NSUInteger controlID)
CommandAttributes NewCommandAttributesForDSControl(const char *commandTag, const NDSInputID controlID)
{
CommandAttributes cmdAttr = NewCommandAttributesForSelector(commandTag, @selector(cmdUpdateDSController:));
@ -2164,12 +2150,104 @@ NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttr
return newDeviceInfo;
}
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput)
MacInputDevicePropertiesEncoder::MacInputDevicePropertiesEncoder()
{
InputAttributesList inputList;
NSDictionary *keyboardNameDict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"KeyNames" ofType:@"plist"]];
NSArray *keyboardDictKeyList = [keyboardNameDict allKeys];
for (NSString *dKey in keyboardDictKeyList)
{
int32_t keyCode = (int32_t)[dKey intValue];
_keyboardNameTable[keyCode] = std::string([(NSString *)[keyboardNameDict valueForKey:dKey] cStringUsingEncoding:NSUTF8StringEncoding]);
}
}
ClientInputDeviceProperties MacInputDevicePropertiesEncoder::EncodeKeyboardInput(const int32_t keyCode, bool keyPressed)
{
std::string elementName = this->_keyboardNameTable[keyCode];
ClientInputDeviceProperties inputProperty;
strncpy(inputProperty.deviceCode, "NSEventKeyboard", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.deviceName, "Keyboard", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH, "%i", (int)keyCode);
strncpy(inputProperty.elementName, (elementName.empty()) ? inputProperty.elementCode : elementName.c_str(), INPUT_HANDLER_STRING_LENGTH);
inputProperty.isAnalog = false;
inputProperty.state = (keyPressed) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
inputProperty.intCoordX = 0;
inputProperty.intCoordY = 0;
inputProperty.floatCoordX = 0.0f;
inputProperty.floatCoordY = 0.0f;
inputProperty.scalar = (keyPressed) ? 1.0f : 0.0f;
inputProperty.object = NULL;
return inputProperty;
}
ClientInputDeviceProperties MacInputDevicePropertiesEncoder::EncodeMouseInput(const int32_t buttonNumber, float touchLocX, float touchLocY, bool buttonPressed)
{
ClientInputDeviceProperties inputProperty;
strncpy(inputProperty.deviceCode, "NSEventMouse", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.deviceName, "Mouse", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH, "%i", (int)buttonNumber);
switch (buttonNumber)
{
case kCGMouseButtonLeft:
strncpy(inputProperty.elementName, "Primary Button", INPUT_HANDLER_STRING_LENGTH);
break;
case kCGMouseButtonRight:
strncpy(inputProperty.elementName, "Secondary Button", INPUT_HANDLER_STRING_LENGTH);
break;
case kCGMouseButtonCenter:
strncpy(inputProperty.elementName, "Center Button", INPUT_HANDLER_STRING_LENGTH);
break;
default:
snprintf(inputProperty.elementName, INPUT_HANDLER_STRING_LENGTH, "Button %i", (int)buttonNumber);
break;
}
inputProperty.isAnalog = false;
inputProperty.state = (buttonPressed) ? ClientInputDeviceState_On : ClientInputDeviceState_Off;
inputProperty.intCoordX = (int32_t)touchLocX;
inputProperty.intCoordY = (int32_t)touchLocY;
inputProperty.floatCoordX = touchLocX;
inputProperty.floatCoordY = touchLocY;
inputProperty.scalar = (buttonPressed) ? 1.0f : 0.0f;
inputProperty.object = NULL;
return inputProperty;
}
ClientInputDeviceProperties MacInputDevicePropertiesEncoder::EncodeIBAction(const SEL theSelector, id sender)
{
ClientInputDeviceProperties inputProperty;
strncpy(inputProperty.deviceCode, "IBAction", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.deviceName, "Application", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.elementCode, sel_getName(theSelector), INPUT_HANDLER_STRING_LENGTH);
strncpy(inputProperty.elementName, inputProperty.elementCode, INPUT_HANDLER_STRING_LENGTH);
inputProperty.isAnalog = false;
inputProperty.state = ClientInputDeviceState_On;
inputProperty.intCoordX = 0;
inputProperty.intCoordY = 0;
inputProperty.floatCoordX = 0.0f;
inputProperty.floatCoordY = 0.0f;
inputProperty.scalar = 1.0f;
inputProperty.object = sender;
return inputProperty;
}
ClientInputDevicePropertiesList MacInputDevicePropertiesEncoder::EncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput)
{
ClientInputDevicePropertiesList inputPropertyList;
if (hidQueue == nil)
{
return inputList;
return inputPropertyList;
}
do
@ -2179,105 +2257,23 @@ InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue, Inp
{
break;
}
InputAttributesList hidInputList = InputListFromHIDValue(hidValueRef, inputManager, forceDigitalInput);
ClientInputDevicePropertiesList hidInputList = InputListFromHIDValue(hidValueRef, inputManager, forceDigitalInput);
const size_t hidInputCount = hidInputList.size();
for (size_t i = 0; i < hidInputCount; i++)
{
inputList.push_back(hidInputList[i]);
inputPropertyList.push_back(hidInputList[i]);
}
CFRelease(hidValueRef);
} while (1);
if (!inputList.empty())
if (!inputPropertyList.empty())
{
// HID input devices don't register events, so we need to manually prevent
// sleep and screensaver whenever we detect an input.
UpdateSystemActivity(UsrActivity);
}
return inputList;
return inputPropertyList;
}
InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BOOL keyPressed)
{
std::string elementName = keyboardNameTable[keyCode];
InputAttributes inputAttr;
strncpy(inputAttr.deviceCode, "NSEventKeyboard", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.deviceName, "Keyboard", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH, "%d", keyCode);
strncpy(inputAttr.elementName, (elementName.empty()) ? inputAttr.elementCode : elementName.c_str(), INPUT_HANDLER_STRING_LENGTH);
inputAttr.isAnalog = false;
inputAttr.state = (keyPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;
inputAttr.floatCoordX = 0.0f;
inputAttr.floatCoordY = 0.0f;
inputAttr.scalar = (keyPressed) ? 1.0f : 0.0f;
inputAttr.object = nil;
return inputAttr;
}
InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber, const NSPoint touchLoc, BOOL buttonPressed)
{
InputAttributes inputAttr;
strncpy(inputAttr.deviceCode, "NSEventMouse", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.deviceName, "Mouse", INPUT_HANDLER_STRING_LENGTH);
snprintf(inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH, "%i", (const int)buttonNumber);
switch (buttonNumber)
{
case kCGMouseButtonLeft:
strncpy(inputAttr.elementName, "Primary Button", INPUT_HANDLER_STRING_LENGTH);
break;
case kCGMouseButtonRight:
strncpy(inputAttr.elementName, "Secondary Button", INPUT_HANDLER_STRING_LENGTH);
break;
case kCGMouseButtonCenter:
strncpy(inputAttr.elementName, "Center Button", INPUT_HANDLER_STRING_LENGTH);
break;
default:
snprintf(inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH, "Button %i", (const int)buttonNumber);
break;
}
inputAttr.isAnalog = false;
inputAttr.state = (buttonPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputAttr.intCoordX = (int32_t)touchLoc.x;
inputAttr.intCoordY = (int32_t)touchLoc.y;
inputAttr.floatCoordX = touchLoc.x;
inputAttr.floatCoordY = touchLoc.y;
inputAttr.scalar = (buttonPressed) ? 1.0f : 0.0f;
inputAttr.object = nil;
return inputAttr;
}
InputAttributes InputManagerEncodeIBAction(const SEL theSelector, id sender)
{
InputAttributes inputAttr;
strncpy(inputAttr.deviceCode, "IBAction", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.deviceName, "Application", INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.elementCode, sel_getName(theSelector), INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.elementName, inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH);
inputAttr.isAnalog = false;
inputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;
inputAttr.floatCoordX = 0.0f;
inputAttr.floatCoordY = 0.0f;
inputAttr.scalar = 1.0f;
inputAttr.object = sender;
return inputAttr;
}
@end

View File

@ -191,11 +191,8 @@
}
// Init the DS controller.
CocoaDSController *newController = [[[CocoaDSController alloc] init] autorelease];
[newCore setCdsController:newController];
[newController setDelegate:emuControl];
[newController setExecControl:[newCore execControl]];
[newController setHardwareMicEnabled:YES];
[[newCore cdsController] setDelegate:emuControl];
[[newCore cdsController] setHardwareMicEnabled:YES];
// Init the DS speakers.
CocoaDSSpeaker *newSpeaker = [[[CocoaDSSpeaker alloc] init] autorelease];

View File

@ -94,7 +94,7 @@
- (BOOL) handleKeyboardEvent:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed;
- (BOOL) handleMouseButtonEvent:(NSEvent *)mouseEvent buttonPressed:(BOOL)buttonPressed;
- (BOOL) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(NSString *)commandTag;
- (BOOL) addMappingUsingInputAttributes:(const ClientInputDeviceProperties *)inputProperty commandTag:(NSString *)commandTag;
- (void) setMappingUsingDeviceInfoDictionary:(NSMutableDictionary *)deviceInfo;
- (BOOL) doesProfileNameExist:(NSString *)profileName;
- (void) updateSelectedProfileName;

View File

@ -277,17 +277,19 @@
- (BOOL) handleKeyboardEvent:(NSEvent *)theEvent keyPressed:(BOOL)keyPressed
{
const InputAttributes inputAttr = InputManagerEncodeKeyboardInput([theEvent keyCode], keyPressed);
return [self addMappingUsingInputAttributes:&inputAttr commandTag:[self configInputTargetID]];
MacInputDevicePropertiesEncoder *inputEncoder = [inputManager inputEncoder];
const ClientInputDeviceProperties inputProperty = inputEncoder->EncodeKeyboardInput((int32_t)[theEvent keyCode], (keyPressed) ? true : false);
return [self addMappingUsingInputAttributes:&inputProperty commandTag:[self configInputTargetID]];
}
- (BOOL) handleMouseButtonEvent:(NSEvent *)mouseEvent buttonPressed:(BOOL)buttonPressed
{
const InputAttributes inputAttr = InputManagerEncodeMouseButtonInput([mouseEvent buttonNumber], NSMakePoint(0.0f, 0.0f), buttonPressed);
return [self addMappingUsingInputAttributes:&inputAttr commandTag:[self configInputTargetID]];
MacInputDevicePropertiesEncoder *inputEncoder = [inputManager inputEncoder];
const ClientInputDeviceProperties inputProperty = inputEncoder->EncodeMouseInput((int32_t)[mouseEvent buttonNumber], 0.0f, 0.0f, (buttonPressed) ? true : false);
return [self addMappingUsingInputAttributes:&inputProperty commandTag:[self configInputTargetID]];
}
- (BOOL) addMappingUsingInputAttributes:(const InputAttributes *)inputAttr commandTag:(NSString *)commandTag
- (BOOL) addMappingUsingInputAttributes:(const ClientInputDeviceProperties *)inputProperty commandTag:(NSString *)commandTag
{
BOOL didMap = NO;
@ -304,7 +306,7 @@
// Add the input mapping.
const CommandAttributes cmdAttr = [inputManager defaultCommandAttributesForCommandTag:cmdTag];
[inputManager addMappingUsingInputAttributes:inputAttr commandAttributes:&cmdAttr];
[inputManager addMappingUsingInputAttributes:inputProperty commandAttributes:&cmdAttr];
[inputManager writeDefaultsInputMappings];
// If we're dealing with a Microphone command, update the audio file generators list.
@ -450,16 +452,18 @@
CommandAttributes cmdAttr = [[hidManager inputManager] defaultCommandAttributesForCommandTag:[cmdTagTarget cStringUsingEncoding:NSUTF8StringEncoding]];
bool forceDigitalInput = !cmdAttr.allowAnalogInput;
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue, [hidManager inputManager], forceDigitalInput);
const size_t inputCount = inputList.size();
MacInputDevicePropertiesEncoder *inputEncoder = [[hidManager inputManager] inputEncoder];
ClientInputDevicePropertiesList inputPropertyList = inputEncoder->EncodeHIDQueue(hidQueue, [hidManager inputManager], forceDigitalInput);
const size_t inputCount = inputPropertyList.size();
for (size_t i = 0; i < inputCount; i++)
{
const InputAttributes &inputAttr = inputList[i];
NSString *inputKey = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceCode, inputAttr.elementCode];
const ClientInputDeviceProperties &inputProperty = inputPropertyList[i];
NSString *inputKey = [NSString stringWithFormat:@"%s:%s", inputProperty.deviceCode, inputProperty.elementCode];
NSDate *inputOnDate = [configInputList valueForKey:inputKey];
if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
if (inputProperty.state == ClientInputDeviceState_On)
{
if (inputOnDate == nil)
{
@ -477,7 +481,7 @@
}
else
{
isHandled = [self addMappingUsingInputAttributes:&inputAttr commandTag:cmdTagTarget];
isHandled = [self addMappingUsingInputAttributes:&inputProperty commandTag:cmdTagTarget];
break;
}
}