2013-10-05 21:29:52 -07:00
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
2012-11-04 23:01:49 +01:00
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
2012-11-01 16:19:01 +01:00
|
|
|
|
|
|
|
// This program 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 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official git repository and contact information can be found at
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
2013-04-17 22:53:38 -06:00
|
|
|
#include <math.h>
|
2016-03-06 13:30:31 -08:00
|
|
|
#include "base/mutex.h"
|
2014-04-19 21:43:27 -07:00
|
|
|
#include "Globals.h"
|
2013-08-28 23:15:13 -07:00
|
|
|
#include "Core/HLE/HLE.h"
|
2014-03-15 11:22:19 -07:00
|
|
|
#include "Core/HLE/FunctionWrappers.h"
|
2013-08-28 23:15:13 -07:00
|
|
|
#include "Core/MIPS/MIPS.h"
|
|
|
|
#include "Core/CoreTiming.h"
|
2015-04-05 18:09:35 -07:00
|
|
|
#include "Core/MemMapHelpers.h"
|
2013-08-28 23:15:13 -07:00
|
|
|
#include "Common/ChunkFile.h"
|
|
|
|
#include "Core/HLE/sceCtrl.h"
|
|
|
|
#include "Core/HLE/sceDisplay.h"
|
|
|
|
#include "Core/HLE/sceKernel.h"
|
|
|
|
#include "Core/HLE/sceKernelThread.h"
|
|
|
|
#include "Core/HLE/sceKernelInterrupt.h"
|
2012-11-01 16:19:01 +01:00
|
|
|
|
|
|
|
/* Index for the two analog directions */
|
|
|
|
#define CTRL_ANALOG_X 0
|
|
|
|
#define CTRL_ANALOG_Y 1
|
2013-07-06 19:02:28 -07:00
|
|
|
#define CTRL_ANALOG_CENTER 128
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2012-11-11 15:09:27 -08:00
|
|
|
#define CTRL_MODE_DIGITAL 0
|
|
|
|
#define CTRL_MODE_ANALOG 1
|
|
|
|
|
2013-02-18 09:04:43 -08:00
|
|
|
const u32 NUM_CTRL_BUFFERS = 64;
|
2012-12-02 21:07:17 -08:00
|
|
|
|
2013-09-07 21:19:21 +02:00
|
|
|
enum {
|
2012-12-02 17:03:13 -08:00
|
|
|
CTRL_WAIT_POSITIVE = 1,
|
|
|
|
CTRL_WAIT_NEGATIVE = 2,
|
|
|
|
};
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
// Returned control data
|
|
|
|
struct _ctrl_data
|
|
|
|
{
|
2013-07-27 15:30:36 -07:00
|
|
|
u32_le frame;
|
|
|
|
u32_le buttons;
|
2013-07-06 19:02:28 -07:00
|
|
|
// The PSP has only one stick, but has space for more info.
|
|
|
|
// The second stick is populated for HD remasters and possibly in the PSP emulator on PS3/Vita.
|
2013-07-27 15:30:36 -07:00
|
|
|
u8 analog[2][2];
|
|
|
|
u8 unused[4];
|
2012-11-01 16:19:01 +01:00
|
|
|
};
|
|
|
|
|
2012-11-08 16:28:45 +01:00
|
|
|
struct CtrlLatch {
|
2013-07-27 15:30:36 -07:00
|
|
|
u32_le btnMake;
|
|
|
|
u32_le btnBreak;
|
|
|
|
u32_le btnPress;
|
|
|
|
u32_le btnRelease;
|
2012-11-08 16:28:45 +01:00
|
|
|
};
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// STATE BEGIN
|
|
|
|
static bool analogEnabled = false;
|
2012-11-25 22:10:25 -08:00
|
|
|
static int ctrlLatchBufs = 0;
|
|
|
|
static u32 ctrlOldButtons = 0;
|
2012-11-09 19:04:57 +01:00
|
|
|
|
2012-12-02 21:07:17 -08:00
|
|
|
static _ctrl_data ctrlBufs[NUM_CTRL_BUFFERS];
|
2012-12-02 15:44:23 -08:00
|
|
|
static _ctrl_data ctrlCurrent;
|
2013-02-18 09:04:43 -08:00
|
|
|
static u32 ctrlBuf = 0;
|
|
|
|
static u32 ctrlBufRead = 0;
|
2012-11-09 19:04:57 +01:00
|
|
|
static CtrlLatch latch;
|
2013-09-29 16:21:30 +08:00
|
|
|
static u32 dialogBtnMake = 0;
|
2012-11-09 19:04:57 +01:00
|
|
|
|
2012-12-22 18:41:49 -08:00
|
|
|
static int ctrlIdleReset = -1;
|
|
|
|
static int ctrlIdleBack = -1;
|
|
|
|
|
2012-12-22 21:23:28 -08:00
|
|
|
static int ctrlCycle = 0;
|
2012-12-22 20:31:22 -08:00
|
|
|
|
2012-12-02 17:03:13 -08:00
|
|
|
static std::vector<SceUID> waitingThreads;
|
2016-03-06 13:30:31 -08:00
|
|
|
static recursive_mutex ctrlMutex;
|
2012-11-09 19:04:57 +01:00
|
|
|
|
2012-12-22 21:23:28 -08:00
|
|
|
static int ctrlTimer = -1;
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
// STATE END
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-07-06 18:54:33 -07:00
|
|
|
// Not savestated, this is emu state.
|
|
|
|
// Not related to sceCtrl*RapidFire(), although it may do the same thing.
|
|
|
|
static bool emuRapidFire = false;
|
|
|
|
static u32 emuRapidFireFrames = 0;
|
|
|
|
|
|
|
|
// These buttons are not affected by rapid fire (neither is analog.)
|
|
|
|
const u32 CTRL_EMU_RAPIDFIRE_MASK = CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static void __CtrlUpdateLatch()
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2016-08-28 00:20:03 -04:00
|
|
|
|
2013-07-06 18:54:33 -07:00
|
|
|
// Copy in the current data to the current buffer.
|
|
|
|
ctrlBufs[ctrlBuf] = ctrlCurrent;
|
|
|
|
u32 buttons = ctrlCurrent.buttons;
|
|
|
|
if (emuRapidFire && (emuRapidFireFrames % 10) < 5)
|
|
|
|
{
|
|
|
|
ctrlBufs[ctrlBuf].buttons &= CTRL_EMU_RAPIDFIRE_MASK;
|
|
|
|
buttons &= CTRL_EMU_RAPIDFIRE_MASK;
|
|
|
|
}
|
2012-11-25 22:10:25 -08:00
|
|
|
|
2013-07-06 18:54:33 -07:00
|
|
|
u32 changed = buttons ^ ctrlOldButtons;
|
|
|
|
latch.btnMake |= buttons & changed;
|
2012-11-25 22:10:25 -08:00
|
|
|
latch.btnBreak |= ctrlOldButtons & changed;
|
2013-07-06 18:54:33 -07:00
|
|
|
latch.btnPress |= buttons;
|
2013-11-16 15:27:19 -08:00
|
|
|
latch.btnRelease |= ~buttons;
|
2013-09-29 16:21:30 +08:00
|
|
|
dialogBtnMake |= buttons & changed;
|
2012-11-25 22:10:25 -08:00
|
|
|
ctrlLatchBufs++;
|
2016-08-28 00:20:03 -04:00
|
|
|
|
2013-07-06 18:54:33 -07:00
|
|
|
ctrlOldButtons = buttons;
|
2012-12-02 15:44:23 -08:00
|
|
|
|
2013-10-24 01:10:09 -07:00
|
|
|
ctrlBufs[ctrlBuf].frame = (u32) CoreTiming::GetGlobalTimeUs();
|
2012-12-02 15:44:23 -08:00
|
|
|
if (!analogEnabled)
|
2013-07-06 19:02:28 -07:00
|
|
|
memset(ctrlBufs[ctrlBuf].analog, CTRL_ANALOG_CENTER, sizeof(ctrlBufs[ctrlBuf].analog));
|
2012-12-02 15:44:23 -08:00
|
|
|
|
2012-12-02 21:07:17 -08:00
|
|
|
ctrlBuf = (ctrlBuf + 1) % NUM_CTRL_BUFFERS;
|
2012-12-02 15:44:23 -08:00
|
|
|
|
|
|
|
// If we wrapped around, push the read head forward.
|
|
|
|
// TODO: Is this right?
|
|
|
|
if (ctrlBufRead == ctrlBuf)
|
2012-12-02 21:07:17 -08:00
|
|
|
ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS;
|
2012-11-09 19:04:57 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int __CtrlResetLatch()
|
2012-11-25 22:10:25 -08:00
|
|
|
{
|
|
|
|
int oldBufs = ctrlLatchBufs;
|
|
|
|
memset(&latch, 0, sizeof(CtrlLatch));
|
|
|
|
ctrlLatchBufs = 0;
|
|
|
|
return oldBufs;
|
|
|
|
}
|
2012-11-18 17:51:14 +01:00
|
|
|
|
|
|
|
u32 __CtrlPeekButtons()
|
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2012-11-25 20:59:52 -08:00
|
|
|
|
2012-12-02 15:44:23 -08:00
|
|
|
return ctrlCurrent.buttons;
|
2012-11-18 17:51:14 +01:00
|
|
|
}
|
|
|
|
|
2013-07-20 12:54:33 +02:00
|
|
|
void __CtrlPeekAnalog(int stick, float *x, float *y)
|
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2013-07-20 12:54:33 +02:00
|
|
|
|
2013-07-20 12:11:35 -07:00
|
|
|
*x = (ctrlCurrent.analog[stick][CTRL_ANALOG_X] - 127.5f) / 127.5f;
|
|
|
|
*y = -(ctrlCurrent.analog[stick][CTRL_ANALOG_Y] - 127.5f) / 127.5f;
|
2013-07-20 12:54:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-23 08:59:34 -08:00
|
|
|
u32 __CtrlReadLatch()
|
|
|
|
{
|
2013-09-29 16:21:30 +08:00
|
|
|
u32 ret = dialogBtnMake;
|
|
|
|
dialogBtnMake = 0;
|
2012-12-23 08:59:34 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
// Functions so that the rest of the emulator can control what the sceCtrl interface should return
|
|
|
|
// to the game:
|
|
|
|
|
|
|
|
void __CtrlButtonDown(u32 buttonBit)
|
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2012-12-02 15:44:23 -08:00
|
|
|
ctrlCurrent.buttons |= buttonBit;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void __CtrlButtonUp(u32 buttonBit)
|
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2012-12-02 15:44:23 -08:00
|
|
|
ctrlCurrent.buttons &= ~buttonBit;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2013-07-06 19:08:59 +02:00
|
|
|
void __CtrlSetAnalogX(float x, int stick)
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
2015-05-15 18:49:54 +02:00
|
|
|
u8 scaled = clamp_u8((int)ceilf(x * 127.5f + 127.5f));
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2015-05-15 18:49:54 +02:00
|
|
|
ctrlCurrent.analog[stick][CTRL_ANALOG_X] = scaled;
|
2013-07-06 19:08:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void __CtrlSetAnalogY(float y, int stick)
|
|
|
|
{
|
2015-05-15 18:49:54 +02:00
|
|
|
u8 scaled = clamp_u8((int)ceilf(-y * 127.5f + 127.5f));
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2015-05-15 18:49:54 +02:00
|
|
|
ctrlCurrent.analog[stick][CTRL_ANALOG_Y] = scaled;
|
2012-12-02 15:44:23 -08:00
|
|
|
}
|
2012-11-25 22:10:25 -08:00
|
|
|
|
2013-07-06 18:54:33 -07:00
|
|
|
void __CtrlSetRapidFire(bool state)
|
|
|
|
{
|
|
|
|
emuRapidFire = state;
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int __CtrlReadSingleBuffer(PSPPointer<_ctrl_data> data, bool negative)
|
2012-12-02 17:03:13 -08:00
|
|
|
{
|
2013-07-06 18:54:33 -07:00
|
|
|
if (data.IsValid())
|
2012-12-02 17:03:13 -08:00
|
|
|
{
|
2013-07-06 18:54:33 -07:00
|
|
|
*data = ctrlBufs[ctrlBufRead];
|
2012-12-02 21:07:17 -08:00
|
|
|
ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS;
|
2012-12-02 17:03:13 -08:00
|
|
|
|
|
|
|
if (negative)
|
2013-07-06 18:54:33 -07:00
|
|
|
data->buttons = ~data->buttons;
|
2012-12-02 17:03:13 -08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek)
|
2012-12-02 17:03:13 -08:00
|
|
|
{
|
2012-12-02 21:07:17 -08:00
|
|
|
if (nBufs > NUM_CTRL_BUFFERS)
|
2013-01-05 15:30:31 -08:00
|
|
|
return SCE_KERNEL_ERROR_INVALID_SIZE;
|
2012-12-02 17:03:13 -08:00
|
|
|
|
2013-08-27 23:19:53 -07:00
|
|
|
if (!peek && !__KernelIsDispatchEnabled())
|
|
|
|
return SCE_KERNEL_ERROR_CAN_NOT_WAIT;
|
2013-08-28 23:15:13 -07:00
|
|
|
if (!peek && __IsInInterrupt())
|
|
|
|
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
|
2013-08-27 23:19:53 -07:00
|
|
|
|
2013-02-18 09:04:43 -08:00
|
|
|
u32 resetRead = ctrlBufRead;
|
2012-12-02 17:03:13 -08:00
|
|
|
|
2012-12-02 21:07:17 -08:00
|
|
|
u32 availBufs;
|
|
|
|
// Peeks always work, they just go go from now X buffers.
|
|
|
|
if (peek)
|
2012-12-02 19:53:20 -08:00
|
|
|
availBufs = nBufs;
|
2012-12-02 21:07:17 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
availBufs = (ctrlBuf - ctrlBufRead + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS;
|
|
|
|
if (availBufs > nBufs)
|
|
|
|
availBufs = nBufs;
|
|
|
|
}
|
|
|
|
ctrlBufRead = (ctrlBuf - availBufs + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS;
|
2012-12-02 19:53:20 -08:00
|
|
|
|
2012-12-02 17:03:13 -08:00
|
|
|
int done = 0;
|
2013-12-16 23:47:34 -08:00
|
|
|
auto data = PSPPointer<_ctrl_data>::Create(ctrlDataPtr);
|
2012-12-02 21:07:17 -08:00
|
|
|
for (u32 i = 0; i < availBufs; ++i)
|
2013-11-16 14:00:42 -08:00
|
|
|
done += __CtrlReadSingleBuffer(data++, negative);
|
2012-12-02 17:03:13 -08:00
|
|
|
|
|
|
|
if (peek)
|
|
|
|
ctrlBufRead = resetRead;
|
|
|
|
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static void __CtrlDoSample()
|
2012-12-02 15:44:23 -08:00
|
|
|
{
|
2012-12-22 21:23:28 -08:00
|
|
|
// This samples the ctrl data into the buffers and updates the latch.
|
2012-11-25 22:10:25 -08:00
|
|
|
__CtrlUpdateLatch();
|
2012-12-02 17:03:13 -08:00
|
|
|
|
|
|
|
// Wake up a single thread that was waiting for the buffer.
|
|
|
|
retry:
|
|
|
|
if (!waitingThreads.empty() && ctrlBuf != ctrlBufRead)
|
|
|
|
{
|
|
|
|
SceUID threadID = waitingThreads[0];
|
|
|
|
waitingThreads.erase(waitingThreads.begin());
|
|
|
|
|
|
|
|
u32 error;
|
|
|
|
SceUID wVal = __KernelGetWaitID(threadID, WAITTYPE_CTRL, error);
|
|
|
|
// Make sure it didn't get woken or something.
|
|
|
|
if (wVal == 0)
|
|
|
|
goto retry;
|
|
|
|
|
2013-11-16 14:00:42 -08:00
|
|
|
PSPPointer<_ctrl_data> ctrlDataPtr;
|
|
|
|
ctrlDataPtr = __KernelGetWaitValue(threadID, error);
|
2012-12-02 17:03:13 -08:00
|
|
|
int retVal = __CtrlReadSingleBuffer(ctrlDataPtr, wVal == CTRL_WAIT_NEGATIVE);
|
|
|
|
__KernelResumeThreadFromWait(threadID, retVal);
|
2014-06-24 00:44:40 -07:00
|
|
|
__KernelReSchedule("ctrl buffers updated");
|
2012-12-02 17:03:13 -08:00
|
|
|
}
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static void __CtrlVblank()
|
2012-12-22 21:23:28 -08:00
|
|
|
{
|
2013-07-06 18:54:33 -07:00
|
|
|
emuRapidFireFrames++;
|
|
|
|
|
2012-12-22 21:23:28 -08:00
|
|
|
// This always runs, so make sure we're in vblank mode.
|
|
|
|
if (ctrlCycle == 0)
|
|
|
|
__CtrlDoSample();
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static void __CtrlTimerUpdate(u64 userdata, int cyclesLate)
|
2012-12-22 21:23:28 -08:00
|
|
|
{
|
|
|
|
// This only runs in timer mode (ctrlCycle > 0.)
|
2013-09-07 21:19:21 +02:00
|
|
|
_dbg_assert_msg_(SCECTRL, ctrlCycle > 0, "Ctrl: sampling cycle should be > 0");
|
2012-12-22 21:23:28 -08:00
|
|
|
|
2014-07-06 01:08:44 -07:00
|
|
|
CoreTiming::ScheduleEvent(usToCycles(ctrlCycle) - cyclesLate, ctrlTimer, 0);
|
2014-07-01 00:25:20 -07:00
|
|
|
|
|
|
|
__CtrlDoSample();
|
2012-12-22 21:23:28 -08:00
|
|
|
}
|
|
|
|
|
2012-12-02 15:44:23 -08:00
|
|
|
void __CtrlInit()
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
2012-12-23 21:27:26 -08:00
|
|
|
ctrlTimer = CoreTiming::RegisterEvent("CtrlSampleTimer", __CtrlTimerUpdate);
|
|
|
|
__DisplayListenVblank(__CtrlVblank);
|
2012-11-25 20:59:52 -08:00
|
|
|
|
2012-12-23 21:27:26 -08:00
|
|
|
ctrlIdleReset = -1;
|
|
|
|
ctrlIdleBack = -1;
|
|
|
|
ctrlCycle = 0;
|
|
|
|
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2012-12-02 15:44:23 -08:00
|
|
|
|
2012-12-02 17:04:57 -08:00
|
|
|
ctrlBuf = 1;
|
2012-12-02 15:44:23 -08:00
|
|
|
ctrlBufRead = 0;
|
|
|
|
ctrlOldButtons = 0;
|
|
|
|
ctrlLatchBufs = 0;
|
2013-09-29 16:21:30 +08:00
|
|
|
dialogBtnMake = 0;
|
2012-12-02 15:44:23 -08:00
|
|
|
|
2012-11-25 22:10:25 -08:00
|
|
|
memset(&latch, 0, sizeof(latch));
|
2012-12-02 12:44:33 -08:00
|
|
|
// Start with everything released.
|
|
|
|
latch.btnRelease = 0xffffffff;
|
|
|
|
|
2012-12-02 15:44:23 -08:00
|
|
|
memset(&ctrlCurrent, 0, sizeof(ctrlCurrent));
|
2013-07-06 19:02:28 -07:00
|
|
|
memset(ctrlCurrent.analog, CTRL_ANALOG_CENTER, sizeof(ctrlCurrent.analog));
|
2013-09-17 08:23:35 -07:00
|
|
|
analogEnabled = false;
|
2012-12-02 21:07:17 -08:00
|
|
|
|
2013-03-02 14:58:58 -08:00
|
|
|
for (u32 i = 0; i < NUM_CTRL_BUFFERS; i++)
|
2012-12-02 21:07:17 -08:00
|
|
|
memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data));
|
2012-11-17 19:56:28 +01:00
|
|
|
}
|
|
|
|
|
2012-12-27 23:00:04 -08:00
|
|
|
void __CtrlDoState(PointerWrap &p)
|
|
|
|
{
|
2016-03-06 13:30:31 -08:00
|
|
|
lock_guard guard(ctrlMutex);
|
2016-08-28 00:20:03 -04:00
|
|
|
|
2013-11-19 18:33:17 -08:00
|
|
|
auto s = p.Section("sceCtrl", 1, 3);
|
2013-09-14 20:23:03 -07:00
|
|
|
if (!s)
|
|
|
|
return;
|
2012-12-28 00:05:54 -08:00
|
|
|
|
2012-12-27 23:00:04 -08:00
|
|
|
p.Do(analogEnabled);
|
|
|
|
p.Do(ctrlLatchBufs);
|
|
|
|
p.Do(ctrlOldButtons);
|
|
|
|
|
|
|
|
p.DoVoid(ctrlBufs, sizeof(ctrlBufs));
|
2013-11-19 18:33:17 -08:00
|
|
|
if (s <= 2) {
|
|
|
|
_ctrl_data dummy = {0};
|
|
|
|
p.Do(dummy);
|
|
|
|
}
|
2012-12-27 23:00:04 -08:00
|
|
|
p.Do(ctrlBuf);
|
|
|
|
p.Do(ctrlBufRead);
|
|
|
|
p.Do(latch);
|
2013-09-29 17:30:17 +08:00
|
|
|
if (s == 1) {
|
|
|
|
dialogBtnMake = 0;
|
|
|
|
} else {
|
|
|
|
p.Do(dialogBtnMake);
|
|
|
|
}
|
2012-12-27 23:00:04 -08:00
|
|
|
|
|
|
|
p.Do(ctrlIdleReset);
|
|
|
|
p.Do(ctrlIdleBack);
|
|
|
|
|
|
|
|
p.Do(ctrlCycle);
|
|
|
|
|
2012-12-28 13:01:46 -08:00
|
|
|
SceUID dv = 0;
|
|
|
|
p.Do(waitingThreads, dv);
|
2012-12-27 23:00:04 -08:00
|
|
|
|
|
|
|
p.Do(ctrlTimer);
|
|
|
|
CoreTiming::RestoreRegisterEvent(ctrlTimer, "CtrlSampleTimer", __CtrlTimerUpdate);
|
|
|
|
}
|
|
|
|
|
2012-12-24 01:41:15 -08:00
|
|
|
void __CtrlShutdown()
|
|
|
|
{
|
|
|
|
waitingThreads.clear();
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static u32 sceCtrlSetSamplingCycle(u32 cycle)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlSetSamplingCycle(%u)", cycle);
|
2012-12-22 20:31:22 -08:00
|
|
|
|
|
|
|
if ((cycle > 0 && cycle < 5555) || cycle > 20000)
|
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
WARN_LOG(SCECTRL, "SCE_KERNEL_ERROR_INVALID_VALUE=sceCtrlSetSamplingCycle(%u)", cycle);
|
2012-12-22 20:31:22 -08:00
|
|
|
return SCE_KERNEL_ERROR_INVALID_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 prev = ctrlCycle;
|
|
|
|
ctrlCycle = cycle;
|
|
|
|
|
2012-12-22 21:23:28 -08:00
|
|
|
if (prev > 0)
|
|
|
|
CoreTiming::UnscheduleEvent(ctrlTimer, 0);
|
|
|
|
if (cycle > 0)
|
|
|
|
CoreTiming::ScheduleEvent(usToCycles(ctrlCycle), ctrlTimer, 0);
|
|
|
|
|
2012-12-22 20:31:22 -08:00
|
|
|
return prev;
|
2012-11-25 20:59:52 -08:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlGetSamplingCycle(u32 cyclePtr)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2013-09-19 00:28:57 -07:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlGetSamplingCycle(%08x)", cyclePtr);
|
2012-12-22 20:31:22 -08:00
|
|
|
if (Memory::IsValidAddress(cyclePtr))
|
|
|
|
Memory::Write_U32(ctrlCycle, cyclePtr);
|
2012-11-25 20:59:52 -08:00
|
|
|
return 0;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static u32 sceCtrlSetSamplingMode(u32 mode)
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
2012-11-11 15:09:27 -08:00
|
|
|
u32 retVal = 0;
|
|
|
|
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlSetSamplingMode(%i)", mode);
|
2012-11-25 20:59:52 -08:00
|
|
|
if (mode > 1)
|
2013-03-31 23:42:56 -07:00
|
|
|
return SCE_KERNEL_ERROR_INVALID_MODE;
|
2012-11-11 15:09:27 -08:00
|
|
|
|
2012-11-25 20:59:52 -08:00
|
|
|
retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL;
|
|
|
|
analogEnabled = mode == CTRL_MODE_ANALOG ? true : false;
|
2012-11-11 15:09:27 -08:00
|
|
|
return retVal;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlGetSamplingMode(u32 modePtr)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
|
|
|
u32 retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL;
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "%d=sceCtrlGetSamplingMode(%08x)", retVal, modePtr);
|
2012-11-25 20:59:52 -08:00
|
|
|
|
|
|
|
if (Memory::IsValidAddress(modePtr))
|
|
|
|
Memory::Write_U32(retVal, modePtr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlSetIdleCancelThreshold(int idleReset, int idleBack)
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "FAKE sceCtrlSetIdleCancelThreshold(%d, %d)", idleReset, idleBack);
|
2012-12-22 18:41:49 -08:00
|
|
|
|
|
|
|
if (idleReset < -1 || idleBack < -1 || idleReset > 128 || idleBack > 128)
|
|
|
|
return SCE_KERNEL_ERROR_INVALID_VALUE;
|
|
|
|
|
|
|
|
ctrlIdleReset = idleReset;
|
|
|
|
ctrlIdleBack = idleBack;
|
2012-12-22 18:30:14 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlGetIdleCancelThreshold(u32 idleResetPtr, u32 idleBackPtr)
|
2012-12-22 18:30:14 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlSetIdleCancelThreshold(%08x, %08x)", idleResetPtr, idleBackPtr);
|
2012-12-22 18:41:49 -08:00
|
|
|
|
|
|
|
if (idleResetPtr && !Memory::IsValidAddress(idleResetPtr))
|
2014-04-03 18:12:22 +02:00
|
|
|
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
|
2012-12-22 18:41:49 -08:00
|
|
|
if (idleBackPtr && !Memory::IsValidAddress(idleBackPtr))
|
2014-04-03 18:12:22 +02:00
|
|
|
return SCE_KERNEL_ERROR_PRIV_REQUIRED;
|
2012-12-22 18:41:49 -08:00
|
|
|
|
|
|
|
if (idleResetPtr)
|
|
|
|
Memory::Write_U32(ctrlIdleReset, idleResetPtr);
|
|
|
|
if (idleBackPtr)
|
|
|
|
Memory::Write_U32(ctrlIdleBack, idleBackPtr);
|
|
|
|
|
2012-12-22 18:30:14 -08:00
|
|
|
return 0;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2013-10-05 21:29:52 -07:00
|
|
|
static int sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2012-12-02 17:03:13 -08:00
|
|
|
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, false);
|
2013-05-28 01:35:46 -07:00
|
|
|
hleEatCycles(330);
|
2012-12-02 17:03:13 -08:00
|
|
|
if (done != 0)
|
2012-12-02 19:53:20 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "%d=sceCtrlReadBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs);
|
2012-12-02 19:53:20 -08:00
|
|
|
}
|
2012-12-02 17:03:13 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
waitingThreads.push_back(__KernelGetCurThread());
|
2013-01-26 10:44:04 -08:00
|
|
|
__KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_POSITIVE, ctrlDataPtr, 0, false, "ctrl buffer waited");
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlReadBufferPositive(%08x, %i) - waiting", ctrlDataPtr, nBufs);
|
2012-12-02 17:03:13 -08:00
|
|
|
}
|
2013-10-05 21:29:52 -07:00
|
|
|
return done;
|
2012-12-02 15:44:23 -08:00
|
|
|
}
|
2012-11-25 20:59:52 -08:00
|
|
|
|
2013-10-05 21:29:52 -07:00
|
|
|
static int sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs)
|
2012-12-02 15:44:23 -08:00
|
|
|
{
|
2012-12-02 17:03:13 -08:00
|
|
|
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, false);
|
2013-05-28 01:35:46 -07:00
|
|
|
hleEatCycles(330);
|
2012-12-02 17:03:13 -08:00
|
|
|
if (done != 0)
|
2012-12-02 19:53:20 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "%d=sceCtrlReadBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs);
|
2012-12-02 19:53:20 -08:00
|
|
|
}
|
2012-12-02 17:03:13 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
waitingThreads.push_back(__KernelGetCurThread());
|
2013-01-26 10:44:04 -08:00
|
|
|
__KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_NEGATIVE, ctrlDataPtr, 0, false, "ctrl buffer waited");
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlReadBufferNegative(%08x, %i) - waiting", ctrlDataPtr, nBufs);
|
2012-12-02 17:03:13 -08:00
|
|
|
}
|
2013-10-05 21:29:52 -07:00
|
|
|
return done;
|
2012-12-02 15:44:23 -08:00
|
|
|
}
|
2012-11-25 21:44:01 -08:00
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs)
|
2012-12-02 15:44:23 -08:00
|
|
|
{
|
2012-12-02 19:53:20 -08:00
|
|
|
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true);
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "%d=sceCtrlPeekBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs);
|
2013-05-28 01:35:46 -07:00
|
|
|
hleEatCycles(330);
|
2012-12-02 19:53:20 -08:00
|
|
|
return done;
|
2012-12-02 15:44:23 -08:00
|
|
|
}
|
2012-11-25 20:59:52 -08:00
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs)
|
2012-12-02 15:44:23 -08:00
|
|
|
{
|
2012-12-02 19:53:20 -08:00
|
|
|
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true);
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "%d=sceCtrlPeekBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs);
|
2013-05-28 01:35:46 -07:00
|
|
|
hleEatCycles(330);
|
2012-12-02 19:53:20 -08:00
|
|
|
return done;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static u32 sceCtrlPeekLatch(u32 latchDataPtr)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlPeekLatch(%08x)", latchDataPtr);
|
2012-11-25 22:10:25 -08:00
|
|
|
|
2012-11-09 19:04:57 +01:00
|
|
|
if (Memory::IsValidAddress(latchDataPtr))
|
|
|
|
Memory::WriteStruct(latchDataPtr, &latch);
|
2012-12-02 15:44:23 -08:00
|
|
|
|
2012-11-25 22:10:25 -08:00
|
|
|
return ctrlLatchBufs;
|
2012-11-08 16:28:45 +01:00
|
|
|
}
|
|
|
|
|
2014-12-08 04:40:08 -05:00
|
|
|
static u32 sceCtrlReadLatch(u32 latchDataPtr)
|
2012-11-25 20:59:52 -08:00
|
|
|
{
|
2013-09-07 21:19:21 +02:00
|
|
|
DEBUG_LOG(SCECTRL, "sceCtrlReadLatch(%08x)", latchDataPtr);
|
2012-11-09 19:04:57 +01:00
|
|
|
|
|
|
|
if (Memory::IsValidAddress(latchDataPtr))
|
|
|
|
Memory::WriteStruct(latchDataPtr, &latch);
|
2012-11-08 16:28:45 +01:00
|
|
|
|
2012-11-25 22:10:25 -08:00
|
|
|
return __CtrlResetLatch();
|
2012-11-08 16:28:45 +01:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:03 -04:00
|
|
|
static const HLEFunction sceCtrl[] =
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
2015-03-22 16:57:56 -07:00
|
|
|
{0X3E65A0EA, nullptr, "sceCtrlInit", '?', "" }, //(int unknown), init with 0
|
|
|
|
{0X1F4011E6, &WrapU_U<sceCtrlSetSamplingMode>, "sceCtrlSetSamplingMode", 'x', "x" },
|
|
|
|
{0X6A2774F3, &WrapU_U<sceCtrlSetSamplingCycle>, "sceCtrlSetSamplingCycle", 'x', "x" },
|
|
|
|
{0X02BAAD91, &WrapI_U<sceCtrlGetSamplingCycle>, "sceCtrlGetSamplingCycle", 'i', "x" },
|
|
|
|
{0XDA6B76A1, &WrapI_U<sceCtrlGetSamplingMode>, "sceCtrlGetSamplingMode", 'i', "x" },
|
2013-10-05 21:29:52 -07:00
|
|
|
{0X1F803938, &WrapI_UU<sceCtrlReadBufferPositive>, "sceCtrlReadBufferPositive", 'i', "xx"},
|
2015-03-22 16:57:56 -07:00
|
|
|
{0X3A622550, &WrapI_UU<sceCtrlPeekBufferPositive>, "sceCtrlPeekBufferPositive", 'i', "xx"},
|
|
|
|
{0XC152080A, &WrapI_UU<sceCtrlPeekBufferNegative>, "sceCtrlPeekBufferNegative", 'i', "xx"},
|
2013-10-05 21:29:52 -07:00
|
|
|
{0X60B81F86, &WrapI_UU<sceCtrlReadBufferNegative>, "sceCtrlReadBufferNegative", 'i', "xx"},
|
2015-03-22 16:57:56 -07:00
|
|
|
{0XB1D0E5CD, &WrapU_U<sceCtrlPeekLatch>, "sceCtrlPeekLatch", 'x', "x" },
|
|
|
|
{0X0B588501, &WrapU_U<sceCtrlReadLatch>, "sceCtrlReadLatch", 'x', "x" },
|
|
|
|
{0X348D99D4, nullptr, "sceCtrlSetSuspendingExtraSamples", '?', "" },
|
|
|
|
{0XAF5960F3, nullptr, "sceCtrlGetSuspendingExtraSamples", '?', "" },
|
|
|
|
{0XA68FD260, nullptr, "sceCtrlClearRapidFire", '?', "" },
|
|
|
|
{0X6841BE1A, nullptr, "sceCtrlSetRapidFire", '?', "" },
|
|
|
|
{0XA7144800, &WrapI_II<sceCtrlSetIdleCancelThreshold>, "sceCtrlSetIdleCancelThreshold", 'i', "ii"},
|
|
|
|
{0X687660FA, &WrapI_UU<sceCtrlGetIdleCancelThreshold>, "sceCtrlGetIdleCancelThreshold", 'i', "xx"},
|
2016-08-28 00:20:03 -04:00
|
|
|
};
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2012-11-25 20:59:52 -08:00
|
|
|
void Register_sceCtrl()
|
|
|
|
{
|
|
|
|
RegisterModule("sceCtrl", ARRAY_SIZE(sceCtrl), sceCtrl);
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
2014-02-17 20:46:57 +08:00
|
|
|
|
|
|
|
void Register_sceCtrl_driver()
|
|
|
|
{
|
|
|
|
RegisterModule("sceCtrl_driver", ARRAY_SIZE(sceCtrl), sceCtrl);
|
|
|
|
}
|