mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-10 00:05:07 +00:00
Merge branch 'master' of github.com:hrydgard/ppsspp
Conflicts: pspautotests test.py
This commit is contained in:
commit
1ba3b005cf
@ -99,6 +99,11 @@ template<int func(int, int, int)> void WrapI_III() {
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, int, u32)> void WrapI_IIU() {
|
||||
int retval = func(PARAM(0), PARAM(1), PARAM(2));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<void func(int, u32)> void WrapV_IU() {
|
||||
func(PARAM(0), PARAM(1));
|
||||
}
|
||||
@ -137,6 +142,10 @@ template<void func(int, u32, u32)> void WrapV_IUU() {
|
||||
func(PARAM(0), PARAM(1), PARAM(2));
|
||||
}
|
||||
|
||||
template<void func(int, int, u32)> void WrapV_IIU() {
|
||||
func(PARAM(0), PARAM(1), PARAM(2));
|
||||
}
|
||||
|
||||
template<void func(int, u32, u32, u32, u32)> void WrapV_IUUUU() {
|
||||
func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4));
|
||||
}
|
||||
|
@ -66,48 +66,6 @@ void SampleControls() {
|
||||
_ctrl_data &data = ctrl;
|
||||
data.frame=1;//frame;
|
||||
frame++;
|
||||
#ifdef _WIN32
|
||||
// TODO: Move this outta here!
|
||||
data.buttons = 0;
|
||||
int analogX = 128;
|
||||
int analogY = 128;
|
||||
if (GetAsyncKeyState(VK_SPACE))
|
||||
data.buttons|=CTRL_START;
|
||||
if (GetAsyncKeyState('V'))
|
||||
data.buttons|=CTRL_SELECT;
|
||||
if (GetAsyncKeyState('A'))
|
||||
data.buttons|=CTRL_SQUARE;
|
||||
if (GetAsyncKeyState('S'))
|
||||
data.buttons|=CTRL_TRIANGLE;
|
||||
if (GetAsyncKeyState('X'))
|
||||
data.buttons|=CTRL_CIRCLE;
|
||||
if (GetAsyncKeyState('Z'))
|
||||
data.buttons|=CTRL_CROSS;
|
||||
if (GetAsyncKeyState('Q'))
|
||||
data.buttons|=CTRL_LTRIGGER;
|
||||
if (GetAsyncKeyState('W'))
|
||||
data.buttons|=CTRL_RTRIGGER;
|
||||
if (GetAsyncKeyState(VK_UP)) {
|
||||
data.buttons|=CTRL_UP;
|
||||
analogY -= 100;
|
||||
}
|
||||
if (GetAsyncKeyState(VK_DOWN)) {
|
||||
data.buttons|=CTRL_DOWN;
|
||||
analogY += 100;
|
||||
}
|
||||
if (GetAsyncKeyState(VK_LEFT)) {
|
||||
data.buttons|=CTRL_LEFT;
|
||||
analogX -= 100;
|
||||
}
|
||||
if (GetAsyncKeyState(VK_RIGHT))
|
||||
{
|
||||
data.buttons|=CTRL_RIGHT;
|
||||
analogX += 100;
|
||||
}
|
||||
|
||||
data.analog[0] = analogX;
|
||||
data.analog[1] = analogY;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,9 +19,24 @@
|
||||
#include "FunctionWrappers.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
|
||||
static u32 iLanguage = 0;
|
||||
|
||||
const int PSP_LANGUAGE_JAPANESE = 0;
|
||||
const int PSP_LANGUAGE_ENGLISH = 1;
|
||||
const int PSP_LANGUAGE_FRENCH = 2;
|
||||
const int PSP_LANGUAGE_SPANISH = 3;
|
||||
const int PSP_LANGUAGE_GERMAN = 4;
|
||||
const int PSP_LANGUAGE_ITALIAN = 5;
|
||||
const int PSP_LANGUAGE_DUTCH = 6;
|
||||
const int PSP_LANGUAGE_PORTUGUESE = 7;
|
||||
const int PSP_LANGUAGE_RUSSIAN = 8;
|
||||
const int PSP_LANGUAGE_KOREAN = 9;
|
||||
const int PSP_LANGUAGE_TRADITIONAL_CHINESE = 10;
|
||||
const int PSP_LANGUAGE_SIMPLIFIED_CHINESE = 11;
|
||||
|
||||
static u32 iLanguage = PSP_LANGUAGE_ENGLISH;
|
||||
static u32 iButtonValue = 0;
|
||||
|
||||
|
||||
u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr)
|
||||
{
|
||||
DEBUG_LOG(HLE,"%i=sceImposeGetBatteryIconStatus(%08x, %08x)", chargingPtr, iconStatusPtr);
|
||||
@ -40,10 +55,6 @@ u32 sceImposeSetLanguageMode(u32 languageVal, u32 buttonVal)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
u32 sceImposeGetLanguageMode(u32 languagePtr, u32 btnPtr)
|
||||
{
|
||||
DEBUG_LOG(HLE,"%i=sceImposeGetLanguageMode(%08x, %08x)", languagePtr, btnPtr);
|
||||
|
@ -327,14 +327,14 @@ const HLEFunction ThreadManForUser[] =
|
||||
{0xCD203292,&WrapU_V<sceKernelCancelEventFlag>, "sceKernelCancelEventFlag"},
|
||||
{0xA66B0120,&WrapU_IU<sceKernelReferEventFlagStatus>, "sceKernelReferEventFlagStatus"},
|
||||
|
||||
{0x8FFDF9A2,sceKernelCancelSema, "sceKernelCancelSema"},
|
||||
{0xD6DA4BA1,sceKernelCreateSema, "sceKernelCreateSema"},
|
||||
{0x28b6489c,sceKernelDeleteSema, "sceKernelDeleteSema"},
|
||||
{0x58b1f937,sceKernelPollSema, "sceKernelPollSema"},
|
||||
{0xBC6FEBC5,sceKernelReferSemaStatus,"sceKernelReferSemaStatus"},
|
||||
{0x3F53E640,sceKernelSignalSema, "sceKernelSignalSema"},
|
||||
{0x4E3A1105,sceKernelWaitSema, "sceKernelWaitSema"},
|
||||
{0x6d212bac,sceKernelWaitSemaCB, "sceKernelWaitSemaCB"},
|
||||
{0x8FFDF9A2,&WrapV_IIU<sceKernelCancelSema>, "sceKernelCancelSema"},
|
||||
{0xD6DA4BA1,sceKernelCreateSema, "sceKernelCreateSema"},
|
||||
{0x28b6489c,&WrapV_I<sceKernelDeleteSema>, "sceKernelDeleteSema"},
|
||||
{0x58b1f937,&WrapI_II<sceKernelPollSema>, "sceKernelPollSema"},
|
||||
{0xBC6FEBC5,&WrapI_IU<sceKernelReferSemaStatus>, "sceKernelReferSemaStatus"},
|
||||
{0x3F53E640,&WrapV_II<sceKernelSignalSema>, "sceKernelSignalSema"},
|
||||
{0x4E3A1105,&WrapV_IIU<sceKernelWaitSema>, "sceKernelWaitSema"},
|
||||
{0x6d212bac,&WrapV_IIU<sceKernelWaitSemaCB>, "sceKernelWaitSemaCB"},
|
||||
|
||||
{0x60107536,0,"sceKernelDeleteLwMutex"},
|
||||
{0x19CFF145,0,"sceKernelCreateLwMutex"},
|
||||
|
@ -57,11 +57,60 @@ struct Semaphore : public KernelObject
|
||||
std::vector<SceUID> waitingThreads;
|
||||
};
|
||||
|
||||
void sceKernelCancelSema()
|
||||
// Resume all waiting threads (for delete / cancel.)
|
||||
// Returns true if it woke any threads.
|
||||
bool __KernelClearSemaThreads(Semaphore *s, int reason)
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
ERROR_LOG(HLE,"UNIMPL sceKernelCancelSema(%i)", id);
|
||||
RETURN(0);
|
||||
bool wokeThreads = false;
|
||||
|
||||
std::vector<SceUID>::iterator iter;
|
||||
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); iter++)
|
||||
{
|
||||
SceUID threadID = *iter;
|
||||
|
||||
// TODO: Set returnValue = reason?
|
||||
__KernelResumeThreadFromWait(threadID);
|
||||
wokeThreads = true;
|
||||
}
|
||||
s->waitingThreads.empty();
|
||||
|
||||
return wokeThreads;
|
||||
}
|
||||
|
||||
// int sceKernelCancelSema(SceUID id, int newCount, int *numWaitThreads);
|
||||
// void because it changes threads.
|
||||
void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelCancelSema(%i)", id);
|
||||
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
if (numWaitThreadsPtr)
|
||||
{
|
||||
u32* numWaitThreads = (u32*)Memory::GetPointer(numWaitThreadsPtr);
|
||||
*numWaitThreads = s->ns.numWaitThreads;
|
||||
}
|
||||
|
||||
if (newCount == -1)
|
||||
s->ns.currentCount = s->ns.initCount;
|
||||
else
|
||||
s->ns.currentCount = newCount;
|
||||
s->ns.numWaitThreads = 0;
|
||||
|
||||
// We need to set the return value BEFORE rescheduling threads.
|
||||
RETURN(0);
|
||||
|
||||
// TODO: Should this reschedule?
|
||||
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL))
|
||||
__KernelReSchedule("semaphore cancelled");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelCancelSema : Trying to cancel invalid semaphore %i", id);
|
||||
RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
//SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option);
|
||||
@ -72,6 +121,7 @@ void sceKernelCreateSema()
|
||||
Semaphore *s = new Semaphore;
|
||||
SceUID id = kernelObjects.Create(s);
|
||||
|
||||
s->ns.size = sizeof(NativeSemaphore);
|
||||
strncpy(s->ns.name, name, 32);
|
||||
s->ns.attr = PARAM(1);
|
||||
s->ns.initCount = PARAM(2);
|
||||
@ -85,60 +135,82 @@ void sceKernelCreateSema()
|
||||
}
|
||||
|
||||
//int sceKernelDeleteSema(SceUID semaid);
|
||||
void sceKernelDeleteSema()
|
||||
// void because it changes threads.
|
||||
void sceKernelDeleteSema(SceUID id)
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
DEBUG_LOG(HLE,"sceKernelDeleteSema(%i)", id);
|
||||
RETURN(kernelObjects.Destroy<Semaphore>(id));
|
||||
}
|
||||
|
||||
void sceKernelReferSemaStatus()
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, PARAM(1));
|
||||
NativeSemaphore *outptr = (NativeSemaphore*)Memory::GetPointer(PARAM(1));
|
||||
int szToCopy = outptr->size - 4;
|
||||
memcpy((char*)outptr + 4, (char*)s + 4, szToCopy);
|
||||
RETURN(0);
|
||||
if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE))
|
||||
{
|
||||
RETURN(kernelObjects.Destroy<Semaphore>(id));
|
||||
__KernelReSchedule("semaphore deleted");
|
||||
}
|
||||
else
|
||||
RETURN(kernelObjects.Destroy<Semaphore>(id));
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelDeleteSema : Trying to delete invalid semaphore %i", id);
|
||||
RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
int sceKernelReferSemaStatus(SceUID id, u32 infoPtr)
|
||||
{
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, infoPtr);
|
||||
NativeSemaphore *outptr = (NativeSemaphore*)Memory::GetPointer(infoPtr);
|
||||
memcpy((char*)outptr, (char*)&s->ns, s->ns.size);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE,"Error %08x", error);
|
||||
RETURN(error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
//int sceKernelSignalSema(SceUID semaid, int signal);
|
||||
void sceKernelSignalSema()
|
||||
// void because it changes threads.
|
||||
void sceKernelSignalSema(SceUID id, int signal)
|
||||
{
|
||||
//TODO: check that this thing really works :)
|
||||
SceUID id = PARAM(0);
|
||||
u32 signal = PARAM(1);
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
int oldval = s->ns.currentCount;
|
||||
|
||||
s->ns.currentCount += signal;
|
||||
if (s->ns.currentCount + signal > s->ns.maxCount)
|
||||
s->ns.currentCount += s->ns.maxCount;
|
||||
else
|
||||
s->ns.currentCount += signal;
|
||||
DEBUG_LOG(HLE,"sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount);
|
||||
|
||||
|
||||
// We need to set the return value BEFORE processing other threads.
|
||||
RETURN(0);
|
||||
|
||||
bool wokeThreads = false;
|
||||
retry:
|
||||
//TODO: check for threads to wake up - wake them
|
||||
std::vector<SceUID>::iterator iter;
|
||||
for (iter = s->waitingThreads.begin(); iter!=s->waitingThreads.end(); s++)
|
||||
{
|
||||
SceUID id = *iter;
|
||||
int wVal = (int)__KernelGetWaitValue(id, error);
|
||||
SceUID threadID = *iter;
|
||||
int wVal = (int)__KernelGetWaitValue(threadID, error);
|
||||
if (wVal <= s->ns.currentCount)
|
||||
{
|
||||
__KernelResumeThreadFromWait(id);
|
||||
s->ns.currentCount -= wVal;
|
||||
s->ns.numWaitThreads--;
|
||||
|
||||
__KernelResumeThreadFromWait(threadID);
|
||||
wokeThreads = true;
|
||||
s->waitingThreads.erase(iter);
|
||||
goto retry;
|
||||
@ -148,111 +220,87 @@ retry:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// RETURN(0);
|
||||
//pop the thread that were released from waiting
|
||||
|
||||
// I don't think we should reschedule here
|
||||
//if (wokeThreads)
|
||||
// __KernelReSchedule("semaphore signalled");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelSignalSema : Trying to signal invalid semaphore %i", id);
|
||||
RETURN(error;)
|
||||
}
|
||||
}
|
||||
|
||||
void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks)
|
||||
{
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
// We need to set the return value BEFORE processing callbacks / etc.
|
||||
RETURN(0);
|
||||
|
||||
if (s->ns.currentCount >= wantedCount) //TODO fix
|
||||
s->ns.currentCount -= wantedCount;
|
||||
else
|
||||
{
|
||||
s->ns.numWaitThreads++;
|
||||
s->waitingThreads.push_back(__KernelGetCurThread());
|
||||
// TODO: timeoutPtr?
|
||||
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, processCallbacks);
|
||||
if (processCallbacks)
|
||||
__KernelCheckCallbacks();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, badSemaMessage, id);
|
||||
RETURN(error);
|
||||
}
|
||||
}
|
||||
|
||||
//int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout);
|
||||
void sceKernelWaitSema()
|
||||
// void because it changes threads.
|
||||
void sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr)
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
int wantedCount = PARAM(1);
|
||||
u32 timeoutPtr = PARAM(2);
|
||||
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr);
|
||||
if (s->ns.currentCount >= wantedCount) //TODO fix
|
||||
{
|
||||
s->ns.currentCount -= wantedCount;
|
||||
RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->waitingThreads.push_back(__KernelGetCurThread());
|
||||
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelWaitSema : Trying to wait for invalid semaphore %i", id);
|
||||
RETURN(error);
|
||||
}
|
||||
DEBUG_LOG(HLE,"sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr);
|
||||
|
||||
__KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false);
|
||||
}
|
||||
|
||||
//int sceKernelWaitSemaCB(SceUID semaid, int signal, SceUInt *timeout);
|
||||
void sceKernelWaitSemaCB()
|
||||
// void because it changes threads.
|
||||
void sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr)
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
int wantedCount = PARAM(1);
|
||||
int timeout = PARAM(2);
|
||||
DEBUG_LOG(HLE,"sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeout);
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
DEBUG_LOG(HLE,"CurrentCount: %i, Signal: %i", s->ns.currentCount, wantedCount);
|
||||
if (s->ns.currentCount >= wantedCount) //TODO fix
|
||||
{
|
||||
DEBUG_LOG(HLE,"Subtracting");
|
||||
s->ns.currentCount -= wantedCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->waitingThreads.push_back(__KernelGetCurThread());
|
||||
__KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, 0, true);
|
||||
__KernelCheckCallbacks();
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(HLE,"After: CurrentCount: %i, Signal: %i", s->ns.currentCount, wantedCount);
|
||||
RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE,"sceKernelWaitSemaCB - Bad semaphore");
|
||||
RETURN(error);
|
||||
}
|
||||
DEBUG_LOG(HLE,"sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr);
|
||||
|
||||
__KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true);
|
||||
}
|
||||
|
||||
// Should be same as WaitSema but without the wait, instead returning SCE_KERNEL_ERROR_SEMA_ZERO
|
||||
void sceKernelPollSema()
|
||||
int sceKernelPollSema(SceUID id, int wantedCount)
|
||||
{
|
||||
SceUID id = PARAM(0);
|
||||
int wantedCount = PARAM(1);
|
||||
DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount);
|
||||
|
||||
u32 error;
|
||||
Semaphore *s = kernelObjects.Get<Semaphore>(id, error);
|
||||
if (s)
|
||||
{
|
||||
DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount);
|
||||
if (s->ns.currentCount >= wantedCount) //TODO fix
|
||||
{
|
||||
s->ns.currentCount -= wantedCount;
|
||||
RETURN(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN(SCE_KERNEL_ERROR_SEMA_ZERO);
|
||||
return SCE_KERNEL_ERROR_SEMA_ZERO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(HLE, "sceKernelPollSema : Trying to poll invalid semaphore %i", id);
|
||||
RETURN(error);
|
||||
ERROR_LOG(HLE, "sceKernelPollSema: Trying to poll invalid semaphore %i", id);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
void sceKernelCancelSema();
|
||||
void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr);
|
||||
void sceKernelCreateSema();
|
||||
void sceKernelDeleteSema();
|
||||
void sceKernelPollSema();
|
||||
void sceKernelReferSemaStatus();
|
||||
void sceKernelSignalSema();
|
||||
void sceKernelWaitSema();
|
||||
void sceKernelWaitSemaCB();
|
||||
void sceKernelDeleteSema(SceUID id);
|
||||
int sceKernelPollSema(SceUID id, int wantedCount);
|
||||
int sceKernelReferSemaStatus(SceUID id, u32 infoPtr);
|
||||
void sceKernelSignalSema(SceUID id, int signal);
|
||||
void sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr);
|
||||
void sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr);
|
||||
|
@ -859,7 +859,7 @@ u32 sceKernelStartThread()
|
||||
|
||||
startThread->nt.status = THREADSTATUS_READY;
|
||||
u32 sp = startThread->context.r[MIPS_REG_SP];
|
||||
if (argBlockPtr)
|
||||
if (argBlockPtr && argSize > 0)
|
||||
{
|
||||
startThread->context.r[MIPS_REG_A0] = argSize;
|
||||
startThread->context.r[MIPS_REG_A1] = sp;
|
||||
|
13
Windows/InputDevice.cpp
Normal file
13
Windows/InputDevice.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "InputDevice.h"
|
||||
#include "XinputDevice.h"
|
||||
#include "KeyboardDevice.h"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr<InputDevice>(new Cls())); } while (0)
|
||||
std::list<std::shared_ptr<InputDevice>> getInputDevices() {
|
||||
std::list<std::shared_ptr<InputDevice>> list;
|
||||
PUSH_BACK(XinputDevice);
|
||||
PUSH_BACK(KeyboardDevice);
|
||||
return list;
|
||||
}
|
13
Windows/InputDevice.h
Normal file
13
Windows/InputDevice.h
Normal file
@ -0,0 +1,13 @@
|
||||
#include "../Common/CommonTypes.h"
|
||||
#include "../Core/HLE/sceCtrl.h"
|
||||
|
||||
#pragma once
|
||||
class InputDevice
|
||||
{
|
||||
public:
|
||||
virtual int UpdateState() = 0;
|
||||
};
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
std::list<std::shared_ptr<InputDevice>> getInputDevices();
|
46
Windows/KeyboardDevice.cpp
Normal file
46
Windows/KeyboardDevice.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "KeyboardDevice.h"
|
||||
#include "../Common/CommonTypes.h"
|
||||
#include "../Core/HLE/sceCtrl.h"
|
||||
#include "WinUser.h"
|
||||
|
||||
static const unsigned short key_ctrl_map[] = {
|
||||
VK_SPACE, CTRL_START,
|
||||
'V', CTRL_SELECT,
|
||||
'A', CTRL_SQUARE,
|
||||
'S', CTRL_TRIANGLE,
|
||||
'X', CTRL_CIRCLE,
|
||||
'Z', CTRL_CROSS,
|
||||
'Q', CTRL_LTRIGGER,
|
||||
'W', CTRL_RTRIGGER,
|
||||
VK_UP, CTRL_UP,
|
||||
VK_DOWN, CTRL_DOWN,
|
||||
VK_LEFT, CTRL_LEFT,
|
||||
VK_RIGHT, CTRL_RIGHT,
|
||||
};
|
||||
int KeyboardDevice::UpdateState() {
|
||||
float analogX = 0;
|
||||
float analogY = 0;
|
||||
for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) {
|
||||
if (!GetAsyncKeyState(key_ctrl_map[i]))
|
||||
__CtrlButtonUp(key_ctrl_map[i+1]);
|
||||
else {
|
||||
__CtrlButtonDown(key_ctrl_map[i+1]);
|
||||
switch (key_ctrl_map[i]) {
|
||||
case VK_UP:
|
||||
analogY -= .8f;
|
||||
break;
|
||||
case VK_DOWN:
|
||||
analogY += .8f;
|
||||
break;
|
||||
case VK_LEFT:
|
||||
analogX -= .8f;
|
||||
break;
|
||||
case VK_RIGHT:
|
||||
analogX += .8f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
__CtrlSetAnalog(analogX, analogY);
|
||||
return 0;
|
||||
}
|
7
Windows/KeyboardDevice.h
Normal file
7
Windows/KeyboardDevice.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "InputDevice.h"
|
||||
|
||||
class KeyboardDevice : public InputDevice {
|
||||
public:
|
||||
virtual int UpdateState();
|
||||
};
|
@ -141,7 +141,7 @@
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Winmm.lib;Ws2_32.lib;opengl32.lib;glu32.lib;comctl32.lib;dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Winmm.lib;Ws2_32.lib;opengl32.lib;glu32.lib;comctl32.lib;dsound.lib;xinput.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@ -364,6 +364,8 @@
|
||||
<ClCompile Include="Debugger\Debugger_MemoryDlg.cpp" />
|
||||
<ClCompile Include="Debugger\Debugger_VFPUDlg.cpp" />
|
||||
<ClCompile Include="EmuThread.cpp" />
|
||||
<ClCompile Include="InputDevice.cpp" />
|
||||
<ClCompile Include="KeyboardDevice.cpp" />
|
||||
<ClCompile Include="W32Util\DialogManager.cpp" />
|
||||
<ClCompile Include="W32Util\Misc.cpp">
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">$(IntDir)%(Filename)2.obj</ObjectFileName>
|
||||
@ -390,6 +392,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XinputDevice.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\android\jni\EmuScreen.h" />
|
||||
@ -403,6 +406,8 @@
|
||||
<ClInclude Include="Debugger\Debugger_MemoryDlg.h" />
|
||||
<ClInclude Include="Debugger\Debugger_VFPUDlg.h" />
|
||||
<ClInclude Include="EmuThread.h" />
|
||||
<ClInclude Include="InputDevice.h" />
|
||||
<ClInclude Include="KeyboardDevice.h" />
|
||||
<ClInclude Include="W32Util\DialogManager.h" />
|
||||
<ClInclude Include="W32Util\Misc.h" />
|
||||
<ClInclude Include="W32Util\PropertySheet.h" />
|
||||
@ -417,6 +422,7 @@
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="..\stdafx.h" />
|
||||
<ClInclude Include="XinputDevice.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\android\atlasscript.txt" />
|
||||
|
@ -23,6 +23,9 @@
|
||||
<Filter Include="Android">
|
||||
<UniqueIdentifier>{d53d0871-8572-4393-822e-d14db0a88dab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Windows\Input">
|
||||
<UniqueIdentifier>{a1963305-bf88-43ef-8ba2-bb3933584b38}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Debugger\CtrlDisAsmView.cpp">
|
||||
@ -92,6 +95,15 @@
|
||||
<ClCompile Include="..\android\jni\UIShader.cpp">
|
||||
<Filter>Android</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XinputDevice.cpp">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyboardDevice.cpp">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputDevice.cpp">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Debugger\CtrlDisAsmView.h">
|
||||
@ -161,6 +173,15 @@
|
||||
<ClInclude Include="..\android\jni\UIShader.h">
|
||||
<Filter>Android</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InputDevice.h">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XinputDevice.h">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyboardDevice.h">
|
||||
<Filter>Windows\Input</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="icon1.ico">
|
||||
|
@ -85,6 +85,9 @@ void WindowsHost::SetDebugMode(bool mode)
|
||||
|
||||
void WindowsHost::BeginFrame()
|
||||
{
|
||||
for (auto iter = this->input.begin(); iter != this->input.end(); iter++)
|
||||
if ((*iter)->UpdateState() == 0)
|
||||
break; // *iter is std::shared_ptr, **iter is InputDevice
|
||||
GL_BeginFrame();
|
||||
}
|
||||
void WindowsHost::EndFrame()
|
||||
|
@ -1,4 +1,7 @@
|
||||
#include "../Core/Host.h"
|
||||
#include "InputDevice.h"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
class WindowsHost : public Host
|
||||
{
|
||||
@ -6,6 +9,7 @@ public:
|
||||
WindowsHost(HWND _displayWindow)
|
||||
{
|
||||
displayWindow = _displayWindow;
|
||||
input = getInputDevices();
|
||||
}
|
||||
void UpdateMemView();
|
||||
void UpdateDisassembly();
|
||||
@ -30,4 +34,5 @@ public:
|
||||
|
||||
private:
|
||||
HWND displayWindow;
|
||||
std::list<std::shared_ptr<InputDevice>> input;
|
||||
};
|
110
Windows/XinputDevice.cpp
Normal file
110
Windows/XinputDevice.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "stdafx.h"
|
||||
#include "XinputDevice.h"
|
||||
#include <limits.h>
|
||||
#include <iostream>
|
||||
|
||||
XinputDevice::XinputDevice() {
|
||||
ZeroMemory( &this->prevState, sizeof(this->prevState) );
|
||||
this->check_delay = 0;
|
||||
this->gamepad_idx = -1;
|
||||
}
|
||||
|
||||
struct Stick {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state);
|
||||
|
||||
int XinputDevice::UpdateState() {
|
||||
if (this->check_delay-- > 0) return -1;
|
||||
XINPUT_STATE state;
|
||||
ZeroMemory( &state, sizeof(XINPUT_STATE) );
|
||||
|
||||
DWORD dwResult;
|
||||
if (this->gamepad_idx >= 0)
|
||||
dwResult = XInputGetState( this->gamepad_idx, &state );
|
||||
else {
|
||||
// use the first gamepad that responds
|
||||
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
dwResult = XInputGetState( i, &state );
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
this->gamepad_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( dwResult == ERROR_SUCCESS ) {
|
||||
this->ApplyDiff(state);
|
||||
Stick left = NormalizedDeadzoneFilter(state);
|
||||
__CtrlSetAnalog(left.x, left.y);
|
||||
this->prevState = state;
|
||||
this->check_delay = 0;
|
||||
return 0;
|
||||
} else {
|
||||
// wait check_delay frames before polling the controller again
|
||||
this->gamepad_idx = -1;
|
||||
this->check_delay = 100;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// We only filter the left stick since PSP has no analog triggers or right stick
|
||||
static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state) {
|
||||
static const short DEADZONE = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE;
|
||||
Stick left;
|
||||
left.x = state.Gamepad.sThumbLX;
|
||||
left.y = state.Gamepad.sThumbLY;
|
||||
|
||||
float magnitude = sqrt(left.x*left.x + left.y*left.y);
|
||||
|
||||
Stick norm;
|
||||
norm.x = left.x / magnitude;
|
||||
norm.y = left.y / magnitude;
|
||||
|
||||
if (magnitude > DEADZONE) {
|
||||
if (magnitude > 32767) magnitude = 32767;
|
||||
// normalize the magnitude
|
||||
magnitude -= DEADZONE;
|
||||
magnitude /= (32767 - DEADZONE);
|
||||
|
||||
// normalize the axis
|
||||
left.x = norm.x * magnitude;
|
||||
left.y = norm.y * magnitude;
|
||||
} else
|
||||
left.x = left.y = 0;
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static const unsigned short xinput_ctrl_map[] = {
|
||||
XINPUT_GAMEPAD_DPAD_UP, CTRL_UP,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN, CTRL_DOWN,
|
||||
XINPUT_GAMEPAD_DPAD_LEFT, CTRL_LEFT,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT, CTRL_RIGHT,
|
||||
XINPUT_GAMEPAD_START, CTRL_START,
|
||||
XINPUT_GAMEPAD_BACK, CTRL_SELECT,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER, CTRL_LTRIGGER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER, CTRL_RTRIGGER,
|
||||
XINPUT_GAMEPAD_A, CTRL_CROSS,
|
||||
XINPUT_GAMEPAD_B, CTRL_CIRCLE,
|
||||
XINPUT_GAMEPAD_X, CTRL_SQUARE,
|
||||
XINPUT_GAMEPAD_Y, CTRL_TRIANGLE,
|
||||
};
|
||||
static inline u32 CtrlForXinput(int xinput) {
|
||||
for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2)
|
||||
if (xinput_ctrl_map[i] == xinput) return (u32) xinput_ctrl_map[i+1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XinputDevice::ApplyDiff(XINPUT_STATE &state) {
|
||||
unsigned short pressed = state.Gamepad.wButtons & ~this->prevState.Gamepad.wButtons;
|
||||
unsigned short released = ~state.Gamepad.wButtons & this->prevState.Gamepad.wButtons;
|
||||
|
||||
for (int i = 1; i < USHRT_MAX; i <<= 1) {
|
||||
if (pressed & i)
|
||||
__CtrlButtonDown(CtrlForXinput(i));
|
||||
if (released & i)
|
||||
__CtrlButtonUp(CtrlForXinput(i));
|
||||
}
|
||||
}
|
17
Windows/XinputDevice.h
Normal file
17
Windows/XinputDevice.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "InputDevice.h"
|
||||
#include "Xinput.h"
|
||||
|
||||
class XinputDevice :
|
||||
public InputDevice
|
||||
{
|
||||
public:
|
||||
XinputDevice();
|
||||
virtual int UpdateState();
|
||||
private:
|
||||
void ApplyDiff(XINPUT_STATE &state);
|
||||
int gamepad_idx;
|
||||
int check_delay;
|
||||
XINPUT_STATE prevState;
|
||||
};
|
||||
|
12
test.py
12
test.py
@ -31,6 +31,7 @@ tests_good = [
|
||||
"string/string",
|
||||
"gpu/callbacks/ge_callbacks",
|
||||
"threads/mbx/mbx",
|
||||
"threads/semaphores/semaphores",
|
||||
"power/power",
|
||||
"rtc/rtc",
|
||||
"umd/callbacks/umd",
|
||||
@ -58,6 +59,14 @@ tests_next = [
|
||||
"io/iodrv/iodrv",
|
||||
"malloc/malloc",
|
||||
"modules/loadexec/loader",
|
||||
"threads/fpl/fpl",
|
||||
"threads/msgpipe/msgpipe",
|
||||
"threads/mutex/mutex",
|
||||
"threads/scheduling/scheduling",
|
||||
"threads/threads/threads",
|
||||
"threads/vpl/vpl",
|
||||
"threads/vtimers/vtimers",
|
||||
"threads/wakeup/wakeup",
|
||||
"umd/io/umd_io",
|
||||
"umd/raw_access/raw_acess",
|
||||
"utility/systemparam/systemparam",
|
||||
@ -68,9 +77,8 @@ tests_next = [
|
||||
# These should be fixed, but currently hang or crash and are thus inconvenient to have
|
||||
# in the general test.
|
||||
tests_hang = [
|
||||
"audio/atrac/atractest",
|
||||
"threads/events/events",
|
||||
"threads/semaphores/semaphores",
|
||||
"audio/atrac/atractest",
|
||||
]
|
||||
|
||||
# These don't even run (or run correctly) on the real PSP
|
||||
|
Loading…
x
Reference in New Issue
Block a user