Merge branch 'master' of github.com:hrydgard/ppsspp

Conflicts:
	Core/Config.h
This commit is contained in:
Henrik Rydgård 2012-12-05 10:57:30 +07:00
commit 36943db4ec
27 changed files with 700 additions and 375 deletions

View file

@ -69,7 +69,9 @@ if(USING_GLES2)
else()
include(FindOpenGL REQUIRED)
endif()
include(FindSDL)
if (NOT BLACKBERRY AND NOT ANDROID)
include(FindSDL)
endif()
include(FindThreads)
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
@ -370,6 +372,7 @@ if(ANDROID)
endif()
set(nativeExtra)
set(nativeExtraLibs)
if(ANDROID)
set(nativeExtra ${nativeExtra}
native/base/NativeApp.h
@ -381,10 +384,25 @@ if(ANDROID)
native/android/native-audio-so.cpp
native/android/native-audio-so.h)
target_link_libraries(native_audio OpenSLES)
endif()
if(BLACKBERRY)
set(nativeExtra ${nativeExtra}
native/base/BlackberryMain.cpp)
# No target
elseif(BLACKBERRY)
set(nativeExtra ${nativeExtra} native/base/BlackberryMain.cpp)
set(nativeExtraLibs ${nativeExtraLibs} asound bps screen socket EGL)
set(TargetBin PPSSPPBlackberry)
elseif(SDL_FOUND)
# Require SDL
include_directories(${SDL_INCLUDE_DIR})
set(nativeExtra ${nativeExtra} native/base/PCMain.cpp)
set(nativeExtraLibs ${nativeExtraLibs} ${SDL_LIBRARY})
if(APPLE)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY})
endif()
if(NOT IOS) # No target
set(TargetBin PPSSPPSDL)
endif()
else()
message(FATAL_ERROR "Could not find SDL. Failing.")
endif()
if(X86)
@ -414,7 +432,6 @@ add_library(native STATIC
native/base/linked_ptr.h
native/base/logging.h
native/base/mutex.h
# native/base/PCMain.cpp
native/base/scoped_ptr.h
native/base/stats.h
native/base/stringutil.cpp
@ -831,43 +848,23 @@ if(HEADLESS)
setup_target_project(PPSSPPHeadless headless)
endif()
if(SDL_FOUND)
include_directories(${SDL_INCLUDE_DIR})
set(NativeAppSource
android/jni/NativeApp.cpp
android/jni/EmuScreen.cpp
android/jni/MenuScreens.cpp
android/jni/GamepadEmu.cpp
android/jni/UIShader.cpp
android/jni/ui_atlas.cpp)
set(AndroidAssets
android/assets/ui_atlas.zim
android/assets/ppge_atlas.zim)
set(LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT} ${nativeExtraLibs})
set(NativeAppSource
android/jni/NativeApp.cpp
android/jni/EmuScreen.cpp
android/jni/MenuScreens.cpp
android/jni/GamepadEmu.cpp
android/jni/UIShader.cpp
android/jni/ui_atlas.cpp)
set(AndroidAssets
android/assets/ui_atlas.zim
android/assets/ppge_atlas.zim)
set(LinkCommon ${CoreLibName}
${SDL_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
if(BLACKBERRY)
add_executable(PPSSPPBlackberry native/base/BlackberryMain.cpp ${NativeAppSource})
target_link_libraries(PPSSPPBlackberry ${LinkCommon} bps screen socket EGL GLESv2)
elseif(ANDROID)
# no target
elseif(IOS)
# no target
else()
set(SDL_Main native/base/PCMain.cpp)
if(APPLE)
set(SDL_Main ${SDL_Main}
SDL/SDLMain.h
SDL/SDLMain.mm)
set(LinkCommon ${LinkCommon} ${COCOA_LIBRARY})
endif()
add_executable(PPSSPPSDL ${SDL_Main} ${NativeAppSource})
target_link_libraries(PPSSPPSDL ${LinkCommon})
endif()
file(INSTALL ${AndroidAssets} DESTINATION assets)
if (TargetBin)
add_executable(${TargetBin} ${NativeAppSource})
target_link_libraries(${TargetBin} ${LinkCommon})
endif()
file(INSTALL ${AndroidAssets} DESTINATION assets)
#include(CPack)

View file

@ -48,7 +48,7 @@ void CConfig::Load(const char *iniFileName)
general->Get("ConfirmOnQuit", &bConfirmOnQuit, false);
general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true);
general->Get("CurrentDirectory", &currentDirectory, "");
general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false);
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
cpu->Get("Core", &iCpuCore, 0);
@ -80,7 +80,7 @@ void CConfig::Save()
general->Set("ConfirmOnQuit", bConfirmOnQuit);
general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess);
general->Set("CurrentDirectory", currentDirectory);
general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad);
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
cpu->Set("Core", iCpuCore);

View file

@ -45,6 +45,7 @@ public:
bool bBufferedRendering;
bool bShowTouchControls;
bool bShowDebuggerOnLoad;
bool bShowAnalogStick;
bool bShowFPSCounter;
bool bShowDebugStats;
@ -59,6 +60,5 @@ private:
std::string iniFilename_;
};
extern SState g_State;
extern CConfig g_Config;

View file

@ -108,6 +108,10 @@ template<void func(int, int)> void WrapV_II() {
func(PARAM(0), PARAM(1));
}
template<void func(u32, const char *)> void WrapV_UC() {
func(PARAM(0), Memory::GetCharPointer(PARAM(1)));
}
template<u32 func(u32, u32)> void WrapU_UU() {
u32 retval = func(PARAM(0), PARAM(1));
RETURN(retval);

View file

@ -17,8 +17,12 @@
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "../CoreTiming.h"
#include "StdMutex.h"
#include "sceCtrl.h"
#include "sceDisplay.h"
#include "sceKernel.h"
#include "sceKernelThread.h"
/* Index for the two analog directions */
#define CTRL_ANALOG_X 0
@ -27,6 +31,16 @@
#define CTRL_MODE_DIGITAL 0
#define CTRL_MODE_ANALOG 1
const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107;
const int PSP_CTRL_ERROR_INVALID_NUM_BUFFERS = 0x80000104;
const int NUM_CTRL_BUFFERS = 64;
enum
{
CTRL_WAIT_POSITIVE = 1,
CTRL_WAIT_NEGATIVE = 2,
};
// Returned control data
struct _ctrl_data
@ -37,7 +51,6 @@ struct _ctrl_data
u8 unused[6];
};
static u32 oldButtons;
struct CtrlLatch {
u32 btnMake;
u32 btnBreak;
@ -50,38 +63,66 @@ struct CtrlLatch {
// STATE BEGIN
static bool ctrlInited = false;
static bool analogEnabled = false;
static int ctrlLatchBufs = 0;
static u32 ctrlOldButtons = 0;
static _ctrl_data ctrl;
static _ctrl_data ctrlBufs[NUM_CTRL_BUFFERS];
static _ctrl_data ctrlCurrent;
static int ctrlBuf = 0;
static int ctrlBufRead = 0;
static CtrlLatch latch;
static std::vector<SceUID> waitingThreads;
static std::recursive_mutex ctrlMutex;
// STATE END
//////////////////////////////////////////////////////////////////////////
void SampleControls() {
static int frame = 0;
_ctrl_data &data = ctrl;
data.frame=1;//frame;
frame++;
}
void __CtrlUpdateLatch()
{
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
void UpdateLatch() {
u32 changed = ctrl.buttons ^ oldButtons;
latch.btnMake = ctrl.buttons & changed;
latch.btnBreak = oldButtons & changed;
latch.btnPress = ctrl.buttons;
latch.btnRelease = (oldButtons & ~ctrl.buttons) & changed;
u32 changed = ctrlCurrent.buttons ^ ctrlOldButtons;
latch.btnMake |= ctrlCurrent.buttons & changed;
latch.btnBreak |= ctrlOldButtons & changed;
latch.btnPress |= ctrlCurrent.buttons;
latch.btnRelease |= (ctrlOldButtons & ~ctrlCurrent.buttons) & changed;
ctrlLatchBufs++;
oldButtons = ctrl.buttons;
ctrlOldButtons = ctrlCurrent.buttons;
// Copy in the current data to the current buffer.
memcpy(&ctrlBufs[ctrlBuf], &ctrlCurrent, sizeof(_ctrl_data));
ctrlBufs[ctrlBuf].frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz());
if (!analogEnabled)
{
ctrlBufs[ctrlBuf].analog[0] = 128;
ctrlBufs[ctrlBuf].analog[1] = 128;
}
ctrlBuf = (ctrlBuf + 1) % NUM_CTRL_BUFFERS;
// If we wrapped around, push the read head forward.
// TODO: Is this right?
if (ctrlBufRead == ctrlBuf)
ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS;
}
int __CtrlResetLatch()
{
int oldBufs = ctrlLatchBufs;
memset(&latch, 0, sizeof(CtrlLatch));
ctrlLatchBufs = 0;
return oldBufs;
}
u32 __CtrlPeekButtons()
{
return ctrl.buttons;
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
return ctrlCurrent.buttons;
}
// Functions so that the rest of the emulator can control what the sceCtrl interface should return
@ -89,123 +130,274 @@ u32 __CtrlPeekButtons()
void __CtrlButtonDown(u32 buttonBit)
{
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
ctrl.buttons |= buttonBit;
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
ctrlCurrent.buttons |= buttonBit;
}
void __CtrlButtonUp(u32 buttonBit)
{
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
ctrl.buttons &= ~buttonBit;
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
ctrlCurrent.buttons &= ~buttonBit;
}
void __CtrlSetAnalog(float x, float y)
{
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
// TODO: Circle!
if (x > 1.0f) x = 1.0f;
if (y > 1.0f) y = 1.0f;
if (x < -1.0f) x = -1.0f;
if (y < -1.0f) y = -1.0f;
ctrl.analog[0] = (u8)(x * 127.f + 128.f);
ctrl.analog[1] = (u8)(y * 127.f + 128.f);
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
// TODO: Circle!
if (x > 1.0f) x = 1.0f;
if (y > 1.0f) y = 1.0f;
if (x < -1.0f) x = -1.0f;
if (y < -1.0f) y = -1.0f;
ctrlCurrent.analog[0] = (u8)(x * 127.f + 128.f);
ctrlCurrent.analog[1] = (u8)(y * 127.f + 128.f);
}
int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative)
{
_ctrl_data data;
if (Memory::IsValidAddress(ctrlDataPtr))
{
memcpy(&data, &ctrlBufs[ctrlBufRead], sizeof(_ctrl_data));
ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS;
if (negative)
data.buttons = ~data.buttons;
Memory::WriteStruct(ctrlDataPtr, &data);
return 1;
}
return 0;
}
int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek)
{
if (nBufs > NUM_CTRL_BUFFERS)
return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS;
int resetRead = ctrlBufRead;
u32 availBufs;
// Peeks always work, they just go go from now X buffers.
if (peek)
availBufs = nBufs;
else
{
availBufs = (ctrlBuf - ctrlBufRead + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS;
if (availBufs > nBufs)
availBufs = nBufs;
}
ctrlBufRead = (ctrlBuf - availBufs + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS;
int done = 0;
for (u32 i = 0; i < availBufs; ++i)
{
done += __CtrlReadSingleBuffer(ctrlDataPtr, negative);
ctrlDataPtr += sizeof(_ctrl_data);
}
if (peek)
ctrlBufRead = resetRead;
return done;
}
void __CtrlVblank()
{
// When in vblank sampling mode, this samples the ctrl data into the buffers and updates the latch.
__CtrlUpdateLatch();
// 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;
u32 ctrlDataPtr = __KernelGetWaitValue(threadID, error);
int retVal = __CtrlReadSingleBuffer(ctrlDataPtr, wVal == CTRL_WAIT_NEGATIVE);
__KernelResumeThreadFromWait(threadID, retVal);
}
}
void __CtrlInit()
{
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
if (!ctrlInited)
{
__DisplayListenVblank(__CtrlVblank);
ctrlInited = true;
}
ctrlBuf = 1;
ctrlBufRead = 0;
ctrlOldButtons = 0;
ctrlLatchBufs = 0;
memset(&latch, 0, sizeof(latch));
// Start with everything released.
latch.btnRelease = 0xffffffff;
memset(&ctrlCurrent, 0, sizeof(ctrlCurrent));
ctrlCurrent.analog[0] = 128;
ctrlCurrent.analog[1] = 128;
for (int i = 0; i < NUM_CTRL_BUFFERS; i++)
memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data));
}
void sceCtrlInit()
{
ctrlInited = true;
memset(&ctrl, 0, sizeof(ctrl));
ctrl.analog[0] = 128;
ctrl.analog[1] = 128;
__CtrlInit();
DEBUG_LOG(HLE,"sceCtrlInit");
RETURN(0);
}
void sceCtrlSetSamplingCycle() {
ERROR_LOG(HLE,"UNIMPL sceCtrlSetSamplingCycle");
RETURN(0);
u32 sceCtrlSetSamplingCycle(u32 cycle)
{
if (cycle == 0)
{
// TODO: Change to vblank when we support something else.
DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%u)", cycle);
}
else
{
ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%u)", cycle);
}
return 0;
}
int sceCtrlGetSamplingCycle(u32 cyclePtr)
{
ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%08x)", cyclePtr);
return 0;
}
u32 sceCtrlSetSamplingMode(u32 mode)
{
u32 retVal = 0;
DEBUG_LOG(HLE,"sceCtrlSetSamplingMode(%i)", mode);
_assert_msg_(HLE, mode >= 0 && mode <= 1, "sceCtrlSetSamplingMode: mode outside expected range.");
DEBUG_LOG(HLE, "sceCtrlSetSamplingMode(%i)", mode);
if (mode > 1)
return PSP_CTRL_ERROR_INVALID_MODE;
if (ctrlInited)
{
retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL;
analogEnabled = mode == CTRL_MODE_ANALOG ? true : false;
}
retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL;
analogEnabled = mode == CTRL_MODE_ANALOG ? true : false;
return retVal;
}
int sceCtrlGetSamplingMode(u32 modePtr)
{
u32 retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL;
if (Memory::IsValidAddress(modePtr))
Memory::Write_U32(retVal, modePtr);
return 0;
}
void sceCtrlSetIdleCancelThreshold()
{
DEBUG_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold");
ERROR_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold");
RETURN(0);
}
u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs)
void sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs)
{
DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs);
_assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferPositive: trying to read nothing?");
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
// Let's just ignore if ctrl is inited or not; some games don't init it (Super Fruit Fall)
//if (ctrlInited)
//{
SampleControls();
Memory::WriteStruct(ctrlDataPtr, &ctrl);
//}
return 1;
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, false);
if (done != 0)
{
RETURN(done);
DEBUG_LOG(HLE, "%d=sceCtrlReadBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs);
}
else
{
waitingThreads.push_back(__KernelGetCurThread());
__KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_POSITIVE, ctrlDataPtr, 0, false);
DEBUG_LOG(HLE, "sceCtrlReadBufferPositive(%08x, %i) - waiting", ctrlDataPtr, nBufs);
}
}
u32 sceCtrlPeekLatch(u32 latchDataPtr) {
ERROR_LOG(HLE,"FAKE sceCtrlPeekLatch(%08x)", latchDataPtr);
if (Memory::IsValidAddress(latchDataPtr))
Memory::WriteStruct(latchDataPtr, &latch);
return 1;
void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs)
{
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, false);
if (done != 0)
{
RETURN(done);
DEBUG_LOG(HLE, "%d=sceCtrlReadBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs);
}
else
{
waitingThreads.push_back(__KernelGetCurThread());
__KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_NEGATIVE, ctrlDataPtr, 0, false);
DEBUG_LOG(HLE, "sceCtrlReadBufferNegative(%08x, %i) - waiting", ctrlDataPtr, nBufs);
}
}
u32 sceCtrlReadLatch(u32 latchDataPtr) {
ERROR_LOG(HLE,"FAKE sceCtrlReadLatch(%08x)", latchDataPtr);
int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs)
{
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true);
DEBUG_LOG(HLE, "%d=sceCtrlPeekBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs);
return done;
}
// Hackery to do it here.
SampleControls();
UpdateLatch();
int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs)
{
int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true);
DEBUG_LOG(HLE, "%d=sceCtrlPeekBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs);
return done;
}
u32 sceCtrlPeekLatch(u32 latchDataPtr)
{
DEBUG_LOG(HLE, "sceCtrlPeekLatch(%08x)", latchDataPtr);
if (Memory::IsValidAddress(latchDataPtr))
Memory::WriteStruct(latchDataPtr, &latch);
return 1;
return ctrlLatchBufs;
}
u32 sceCtrlReadLatch(u32 latchDataPtr)
{
DEBUG_LOG(HLE, "sceCtrlReadLatch(%08x)", latchDataPtr);
if (Memory::IsValidAddress(latchDataPtr))
Memory::WriteStruct(latchDataPtr, &latch);
return __CtrlResetLatch();
}
static const HLEFunction sceCtrl[] =
{
{0x6a2774f3, sceCtrlInit, "sceCtrlInit"}, //(int unknown), init with 0
{0x1f4011e6, &WrapU_U<sceCtrlSetSamplingMode>, "sceCtrlSetSamplingMode"}, //(int on);
{0x1f803938, &WrapU_UU<sceCtrlReadBufferPositive>, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1
{0x6A2774F3, 0, "sceCtrlSetSamplingCycle"}, //?
{0x6A2774F3,sceCtrlSetSamplingCycle,"sceCtrlSetSamplingCycle"},
{0x02BAAD91,0,"sceCtrlGetSamplingCycle"},
{0xDA6B76A1,0,"sceCtrlGetSamplingMode"},
{0x3A622550,&WrapU_UU<sceCtrlReadBufferPositive>, "sceCtrlPeekBufferPositive"},
{0xC152080A,0,"sceCtrlPeekBufferNegative"},
{0x60B81F86,0,"sceCtrlReadBufferNegative"},
{0xB1D0E5CD,&WrapU_U<sceCtrlPeekLatch>,"sceCtrlPeekLatch"},
{0x0B588501,&WrapU_U<sceCtrlReadLatch>,"sceCtrlReadLatch"},
{0x348D99D4,0,"sceCtrl_348D99D4"},
{0xAF5960F3,0,"sceCtrl_AF5960F3"},
{0xA68FD260,0,"sceCtrlClearRapidFire"},
{0x6841BE1A,0,"sceCtrlSetRapidFire"},
{0xa7144800,sceCtrlSetIdleCancelThreshold,"sceCtrlSetIdleCancelThreshold"},
{0x687660fa,0,"sceCtrlGetIdleCancelThreshold"},
{0x3E65A0EA, WrapV_V<sceCtrlInit>, "sceCtrlInit"}, //(int unknown), init with 0
{0x1f4011e6, WrapU_U<sceCtrlSetSamplingMode>, "sceCtrlSetSamplingMode"}, //(int on);
{0x6A2774F3, WrapU_U<sceCtrlSetSamplingCycle>, "sceCtrlSetSamplingCycle"},
{0x02BAAD91, WrapI_U<sceCtrlGetSamplingCycle>,"sceCtrlGetSamplingCycle"},
{0xDA6B76A1, WrapI_U<sceCtrlGetSamplingMode>, "sceCtrlGetSamplingMode"},
{0x1f803938, WrapV_UU<sceCtrlReadBufferPositive>, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1
{0x3A622550, WrapI_UU<sceCtrlPeekBufferPositive>, "sceCtrlPeekBufferPositive"},
{0xC152080A, WrapI_UU<sceCtrlPeekBufferNegative>, "sceCtrlPeekBufferNegative"},
{0x60B81F86, WrapV_UU<sceCtrlReadBufferNegative>, "sceCtrlReadBufferNegative"},
{0xB1D0E5CD, WrapU_U<sceCtrlPeekLatch>, "sceCtrlPeekLatch"},
{0x0B588501, WrapU_U<sceCtrlReadLatch>, "sceCtrlReadLatch"},
{0x348D99D4, 0, "sceCtrl_348D99D4"},
{0xAF5960F3, 0, "sceCtrl_AF5960F3"},
{0xA68FD260, 0, "sceCtrlClearRapidFire"},
{0x6841BE1A, 0, "sceCtrlSetRapidFire"},
{0xa7144800, WrapV_V<sceCtrlSetIdleCancelThreshold>, "sceCtrlSetIdleCancelThreshold"},
{0x687660fa, 0, "sceCtrlGetIdleCancelThreshold"},
};
void Register_sceCtrl() {
RegisterModule("sceCtrl",ARRAY_SIZE(sceCtrl),sceCtrl);
void Register_sceCtrl()
{
RegisterModule("sceCtrl", ARRAY_SIZE(sceCtrl), sceCtrl);
}

View file

@ -32,6 +32,8 @@ void Register_sceCtrl();
#define CTRL_LTRIGGER 0x0100
#define CTRL_RTRIGGER 0x0200
void __CtrlInit();
void __CtrlButtonDown(u32 buttonBit);
void __CtrlButtonUp(u32 buttonBit);
// -1 to 1, try to keep it in the circle

View file

@ -72,6 +72,8 @@ double lastFrameTime = 0;
// STATE END
std::vector<VblankCallback> vblankListeners;
// The vblank period is 731.5 us (0.7315 ms)
const double vblankMs = 0.7315;
const double frameMs = 1000.0 / 60.0;
@ -116,6 +118,20 @@ void __DisplayShutdown()
ShutdownGfxState();
}
void __DisplayListenVblank(VblankCallback callback)
{
vblankListeners.push_back(callback);
}
void __DisplayFireVblank()
{
for (std::vector<VblankCallback>::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter)
{
VblankCallback cb = *iter;
cb();
}
}
void hleEnterVblank(u64 userdata, int cyclesLate)
{
int vbCount = userdata;
@ -124,6 +140,9 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
isVblank = 1;
// Fire the vblank listeners before we wake threads.
__DisplayFireVblank();
// Wake up threads waiting for VBlank
__KernelTriggerWait(WAITTYPE_VBLANK, 0, true);

View file

@ -23,3 +23,6 @@ void Register_sceDisplay();
// will return true once after every end-of-frame.
bool __DisplayFrameDone();
typedef void (*VblankCallback)();
void __DisplayListenVblank(VblankCallback callback);

View file

@ -29,6 +29,7 @@
#include "__sceAudio.h"
#include "sceAudio.h"
#include "sceCtrl.h"
#include "sceDisplay.h"
#include "sceGe.h"
#include "sceIo.h"
@ -80,6 +81,7 @@ void __KernelInit()
__PowerInit();
__UtilityInit();
__UmdInit();
__CtrlInit();
// "Internal" PSP libraries
__PPGeInit();

View file

@ -374,8 +374,15 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr)
if (timeoutPtr == 0 || mutexWaitTimer == 0)
return;
// This should call __KernelMutexTimeout() later, unless we cancel it.
int micro = (int) Memory::Read_U32(timeoutPtr);
// This happens to be how the hardware seems to time things.
if (micro <= 3)
micro = 15;
else if (micro <= 249)
micro = 250;
// This should call __KernelMutexTimeout() later, unless we cancel it.
CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread());
}
@ -701,7 +708,7 @@ void __KernelWaitLwMutex(LwMutex *mutex, u32 timeoutPtr)
else if (micro <= 249)
micro = 250;
// This should call __KernelMutexTimeout() later, unless we cancel it.
// This should call __KernelLwMutexTimeout() later, unless we cancel it.
CoreTiming::ScheduleEvent(usToCycles(micro), lwMutexWaitTimer, __KernelGetCurThread());
}

View file

@ -73,6 +73,7 @@ const char *waitTypeStrings[] =
"Vblank",
"Mutex",
"LwMutex",
"Ctrl",
};
struct SceKernelSysClock {
@ -608,7 +609,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, int retval)
// Only run when you can safely accept a context switch
// Triggers a waitable event, that is, it wakes up all threads that waits for it
// If any changes were made, it will context switch
bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch)
bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool dontSwitch)
{
bool doneAnything = false;
@ -621,6 +622,8 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch)
{
// This thread was waiting for the triggered object.
__KernelResumeThreadFromWait(t);
if (useRetVal)
t->setReturnValue(retVal);
doneAnything = true;
}
}
@ -639,6 +642,16 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch)
return true;
}
bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch)
{
return __KernelTriggerWait(type, id, false, 0, dontSwitch);
}
bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch)
{
return __KernelTriggerWait(type, id, true, retVal, dontSwitch);
}
// makes the current thread wait for an event
void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr, bool processCallbacks)
{
@ -1799,7 +1812,8 @@ bool __KernelCheckCallbacks() {
return processed;
}
void sceKernelCheckCallback() {
bool __KernelForceCallbacks()
{
Thread *curThread = __GetCurrentThread();
// This thread can now process callbacks.
@ -1810,6 +1824,14 @@ void sceKernelCheckCallback() {
// Note - same thread as above - checking callbacks may switch threads.
curThread->isProcessingCallbacks = false;
return callbacksProcessed;
}
void sceKernelCheckCallback() {
Thread *curThread = __GetCurrentThread();
bool callbacksProcessed = __KernelForceCallbacks();
if (callbacksProcessed) {
curThread->setReturnValue(1);
ERROR_LOG(HLE,"sceKernelCheckCallback() - processed a callback.");
@ -1856,7 +1878,7 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID
Callback *cb = kernelObjects.Get<Callback>(cbId, error);
if (!cb) {
// Yeah, we're screwed, this shouldn't happen.
ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback 0");
ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback %08x", cbId);
return;
}
cb->nc.notifyCount++;

View file

@ -70,6 +70,7 @@ enum WaitType //probably not the real values
WAITTYPE_VBLANK = 12, // fake
WAITTYPE_MUTEX = 13,
WAITTYPE_LWMUTEX = 14,
WAITTYPE_CTRL = 15,
// Remember to update sceKernelThread.cpp's waitTypeStrings to match.
};
@ -104,6 +105,7 @@ void __KernelLoadContext(ThreadContext *ctx);
// TODO: Replace this with __KernelResumeThread over time as it's misguided.
bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch = false);
bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch);
u32 __KernelResumeThreadFromWait(SceUID threadID); // can return an error value
u32 __KernelResumeThreadFromWait(SceUID threadID, int retval);
@ -163,6 +165,7 @@ bool __KernelInCallback();
// Should be called by (nearly) all ...CB functions.
bool __KernelCheckCallbacks();
bool __KernelForceCallbacks();
class Thread;
void __KernelSwitchContext(Thread *target, const char *reason);
bool __KernelExecutePendingMipsCalls();

View file

@ -17,9 +17,12 @@
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "../../Core/CoreTiming.h"
#include "sceUmd.h"
#include "sceKernelThread.h"
const int PSP_ERROR_UMD_INVALID_PARAM = 0x80010016;
#define UMD_NOT_PRESENT 0x01
#define UMD_PRESENT 0x02
#define UMD_CHANGED 0x04
@ -32,6 +35,7 @@ u8 umdActivated = 1;
u32 umdStatus = 0;
u32 umdErrorStat = 0;
static int driveCBId= -1;
int umdStatTimer = 0;
#define PSP_UMD_TYPE_GAME 0x10
@ -39,7 +43,8 @@ static int driveCBId= -1;
#define PSP_UMD_TYPE_AUDIO 0x40
struct PspUmdInfo {
int type;
u32 size;
u32 type;
};
@ -76,68 +81,121 @@ void __KernelUmdDeactivate()
//int sceUmdCheckMedium(int a);
void sceUmdCheckMedium()
int sceUmdCheckMedium()
{
DEBUG_LOG(HLE,"1=sceUmdCheckMedium(?)");
//ignore PARAM(0)
RETURN(1); //non-zero: disc in drive
return 1; //non-zero: disc in drive
}
void sceUmdGetDiscInfo()
u32 sceUmdGetDiscInfo(u32 infoAddr)
{
u32 infoAddr = PARAM(0);
ERROR_LOG(HLE,"sceUmdGetDiscInfo(%08x)", infoAddr);
PspUmdInfo info;
info.type = PSP_UMD_TYPE_GAME;
DEBUG_LOG(HLE, "sceUmdGetDiscInfo(%08x)", infoAddr);
if (Memory::IsValidAddress(infoAddr))
{
PspUmdInfo info;
Memory::ReadStruct(infoAddr, &info);
if (info.size != 8)
return PSP_ERROR_UMD_INVALID_PARAM;
info.type = PSP_UMD_TYPE_GAME;
Memory::WriteStruct(infoAddr, &info);
return 0;
}
RETURN(0);
else
return PSP_ERROR_UMD_INVALID_PARAM;
}
u32 sceUmdActivate(u32 unknown, const char *name)
void sceUmdActivate(u32 unknown, const char *name)
{
u32 retVal = 0;
if (unknown < 1 || unknown > 2)
{
RETURN(PSP_ERROR_UMD_INVALID_PARAM);
return;
}
bool changed = umdActivated == 0;
__KernelUmdActivate();
DEBUG_LOG(HLE,"%i=sceUmdActivate(%08x, %s)", retVal, unknown, name);
if (unknown == 1)
{
DEBUG_LOG(HLE, "0=sceUmdActivate(%d, %s)", unknown, name);
}
else
{
ERROR_LOG(HLE, "UNTESTED 0=sceUmdActivate(%d, %s)", unknown, name);
}
u32 notifyArg = UMD_PRESENT | UMD_READABLE;
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
return retVal;
RETURN(0);
if (changed)
__KernelReSchedule("umd activated");
}
u32 sceUmdDeactivate(u32 unknown, const char *name)
void sceUmdDeactivate(u32 unknown, const char *name)
{
DEBUG_LOG(HLE,"sceUmdDeactivate()");
u8 triggerCallback = umdActivated;
// Why 18? No idea.
if (unknown < 0 || unknown > 18)
{
RETURN(PSP_ERROR_UMD_INVALID_PARAM);
return;
}
bool changed = umdActivated != 0;
__KernelUmdDeactivate();
if (triggerCallback) {
u32 notifyArg = UMD_PRESENT | UMD_READY;
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
if (unknown == 1)
{
DEBUG_LOG(HLE, "0=sceUmdDeactivate(%d, %s)", unknown, name);
}
return 0;
else
{
ERROR_LOG(HLE, "UNTESTED 0=sceUmdDeactivate(%d, %s)", unknown, name);
}
u32 notifyArg = UMD_PRESENT | UMD_READY;
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg);
RETURN(0);
if (changed)
__KernelReSchedule("umd deactivated");
}
u32 sceUmdRegisterUMDCallBack(u32 cbId)
{
DEBUG_LOG(HLE,"0=sceUmdRegisterUMDCallback(id=%i)",PARAM(0));
if (driveCBId == -1)
{
driveCBId = cbId;
}
int retVal;
// TODO: If the callback is invalid, return PSP_ERROR_UMD_INVALID_PARAM.
if (cbId == 0)
retVal = PSP_ERROR_UMD_INVALID_PARAM;
else
{
ERROR_LOG(HLE," 0=sceUmdRegisterUMDCallback(id=%i) callback overwrite attempt",PARAM(0));
retVal = __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId);
driveCBId = cbId;
}
return __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId);
DEBUG_LOG(HLE, "%d=sceUmdRegisterUMDCallback(id=%08x)", retVal, cbId);
return retVal;
}
u32 sceUmdUnRegisterUMDCallBack(u32 cbId)
{
DEBUG_LOG(HLE,"0=sceUmdUnRegisterUMDCallBack(id=%i)",PARAM(0));
driveCBId = -1;
return __KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId);
u32 retVal;
if (cbId != driveCBId)
retVal = PSP_ERROR_UMD_INVALID_PARAM;
else
{
retVal = cbId;
driveCBId = -1;
__KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId);
}
DEBUG_LOG(HLE, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId);
return retVal;
}
u32 sceUmdGetDriveStat()
@ -148,6 +206,31 @@ u32 sceUmdGetDriveStat()
return retVal;
}
void __UmdStatTimeout(u64 userdata, int cyclesLate)
{
SceUID threadID = (SceUID)userdata;
u32 error;
SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_UMD, error);
// Assuming it's still waiting.
if (waitID == 1)
__KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT);
}
void __UmdWaitStat(u32 timeout)
{
if (umdStatTimer == 0)
umdStatTimer = CoreTiming::RegisterEvent("MutexTimeout", &__UmdStatTimeout);
// This happens to be how the hardware seems to time things.
if (timeout <= 4)
timeout = 15;
else if (timeout <= 215)
timeout = 250;
CoreTiming::ScheduleEvent(usToCycles((int) timeout), umdStatTimer, __KernelGetCurThread());
}
/**
* Wait for a drive to reach a certain state
*
@ -155,48 +238,64 @@ u32 sceUmdGetDriveStat()
* @return < 0 on error
*
*/
void sceUmdWaitDriveStat()
void sceUmdWaitDriveStat(u32 stat)
{
u32 stat = PARAM(0);
DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat);
if ((stat & __KernelUmdGetState()) != stat)
__KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0);
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStat(stat = %08x)", stat);
RETURN(0);
if ((stat & __KernelUmdGetState()) == 0)
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0);
}
void sceUmdWaitDriveStatWithTimer()
void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout)
{
u32 stat = PARAM(0);
u32 timeout = PARAM(1);
DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x)", stat);
if ((stat & __KernelUmdGetState()) != stat)
__KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0);
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout);
RETURN(0);
if ((stat & __KernelUmdGetState()) == 0)
{
__UmdWaitStat(timeout);
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0);
}
}
void sceUmdWaitDriveStatCB()
void sceUmdWaitDriveStatCB(u32 stat, u32 timeout)
{
u32 stat = PARAM(0);
DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x)", stat);
// Immediately notify
RETURN(0);
RETURN(0);
if (driveCBId != -1)
{
__KernelNotifyCallbackType(THREAD_CALLBACK_UMD, driveCBId, __KernelUmdGetState()&stat);
DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout);
bool callbacksProcessed = __KernelForceCallbacks();
if (callbacksProcessed)
__KernelExecutePendingMipsCalls();
}
else
{
ERROR_LOG(HLE, "HACK 0=sceUmdWaitDriveStatCB(stat = %08x) attempting to call unset callback", stat);
WARN_LOG(HLE, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d) without callback", stat, timeout);
}
if ((stat & __KernelUmdGetState()) == 0)
{
if (timeout == 0)
timeout = 8000;
__UmdWaitStat(timeout);
__KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true);
__KernelCheckCallbacks();
}
RETURN(0);
}
void sceUmdCancelWaitDriveStat()
{
u32 stat = PARAM(0);
ERROR_LOG(HLE,"UNIMPL 0=sceUmdCancelWaitDriveStat(stat = %08x)", stat);
DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()");
RETURN(0);
__KernelTriggerWait(WAITTYPE_UMD, 1, SCE_KERNEL_ERROR_WAIT_CANCEL, false);
// TODO: We should call UnscheduleEvent() event here?
// But it's not often used anyway, and worst-case it will just do nothing unless it waits again.
}
u32 sceUmdGetErrorStat()
@ -208,17 +307,17 @@ u32 sceUmdGetErrorStat()
const HLEFunction sceUmdUser[] =
{
{0xC6183D47,&WrapU_UC<sceUmdActivate>,"sceUmdActivate"},
{0xC6183D47,WrapV_UC<sceUmdActivate>,"sceUmdActivate"},
{0x6B4A146C,&WrapU_V<sceUmdGetDriveStat>,"sceUmdGetDriveStat"},
{0x46EBB729,sceUmdCheckMedium,"sceUmdCheckMedium"},
{0xE83742BA,&WrapU_UC<sceUmdDeactivate>,"sceUmdDeactivate"},
{0x8EF08FCE,sceUmdWaitDriveStat,"sceUmdWaitDriveStat"},
{0x56202973,sceUmdWaitDriveStatWithTimer,"sceUmdWaitDriveStatWithTimer"},
{0x4A9E5E29,sceUmdWaitDriveStatCB,"sceUmdWaitDriveStatCB"},
{0x46EBB729,WrapI_V<sceUmdCheckMedium>,"sceUmdCheckMedium"},
{0xE83742BA,WrapV_UC<sceUmdDeactivate>,"sceUmdDeactivate"},
{0x8EF08FCE,WrapV_U<sceUmdWaitDriveStat>,"sceUmdWaitDriveStat"},
{0x56202973,WrapV_UU<sceUmdWaitDriveStatWithTimer>,"sceUmdWaitDriveStatWithTimer"},
{0x4A9E5E29,WrapV_UU<sceUmdWaitDriveStatCB>,"sceUmdWaitDriveStatCB"},
{0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"},
{0x6B4A146C,&WrapU_V<sceUmdGetDriveStat>,"sceUmdGetDriveStat"},
{0x20628E6F,&WrapU_V<sceUmdGetErrorStat>,"sceUmdGetErrorStat"},
{0x340B7686,sceUmdGetDiscInfo,"sceUmdGetDiscInfo"},
{0x340B7686,WrapU_U<sceUmdGetDiscInfo>,"sceUmdGetDiscInfo"},
{0xAEE7404D,&WrapU_U<sceUmdRegisterUMDCallBack>,"sceUmdRegisterUMDCallBack"},
{0xBD2BDE07,&WrapU_U<sceUmdUnRegisterUMDCallBack>,"sceUmdUnRegisterUMDCallBack"},
{0x87533940,0,"sceUmdReplaceProhibit"}, // ??? sounds bogus

View file

@ -442,7 +442,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
case GE_CMD_RET:
//TODO : debug!
{
u32 target = dcontext.pc & 0xF0000000 | (stack[--stackptr] & 0x0FFFFFFF);
u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF);
DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target);
dcontext.pc = target - 4;
}

View file

@ -19,6 +19,12 @@
#define GLSL_ES_1_0
#else
#define GLSL_1_3
// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs
// special treatment in the shader generator.
#if defined(__APPLE__)
#define FORCE_OPENGL_2_0
#endif
#endif
#include "FragmentShaderGenerator.h"
@ -29,13 +35,6 @@
// TODO: remove
static char buffer[16384];
// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs
// special treatment in the shader generator.
#ifdef __APPLE__
#define FORCE_OPENGL_2_0
#endif
#define WRITE p+=sprintf
// GL_NV_shader_framebuffer_fetch looks interesting....

View file

@ -3,7 +3,7 @@
<id>com.Qtness.PPSSPP</id>
<name>PPSSPP</name>
<filename>PPSSPPBlackberry</filename>
<versionNumber>0.31</versionNumber>
<versionNumber>0.4</versionNumber>
<buildId>1</buildId>
<description>Playstation portable emulator.</description>
@ -20,8 +20,6 @@
<asset path="PPSSPPBlackberry" entry="true" type="Qnx/Elf">PPSSPPBlackberry</asset>
<asset path="icon-114.png">icon-114.png</asset>
<asset path="../android/assets">assets</asset>
<asset path="../../SDL12/Device-Release/libSDL12.so">lib/libSDL12.so</asset>
<asset path="../../TouchControlOverlay/Device-Release/libTouchControlOverlay.so">lib/libTouchControlOverlay.so</asset>
<category>core.games</category>
<icon>
@ -33,6 +31,4 @@
<action system="true">run_native</action>
<action>access_shared</action>
<action>play_audio</action>
<env var="LD_LIBRARY_PATH" value="app/native/lib"/>
</qnx>

View file

@ -7,45 +7,8 @@ if [ -z "$BB_OS" ]; then
fi
echo "Building for Blackberry ${BB_OS}"
PPSSPP_ROOT=${PWD}/..
if [ -z "$PROJECT_ROOT" ]; then
PROJECT_ROOT=${PPSSPP_ROOT}/..
fi
if [ -z "$SDL_PROJECT" ]; then
SDL_PROJECT="$PROJECT_ROOT/SDL"
fi
if [ -z "$TCO_PROJECT" ]; then
TCO_PROJECT="$PROJECT_ROOT/TouchControlOverlay"
fi
while true; do
case "$1" in
-h | --help )
echo "Build script for BlackBerry"
echo
echo "Options: "
echo " -h, --help Show this help message."
echo " -p, --project-root PATH Specify the root directory containing all projects. (default is PPSSPP's parent)"
echo "Dependency Paths (defaults are under project root): "
echo " --sdl PATH SDL 1.2 project directory (default is SDL)"
echo " --tco PATH TouchControlOverlay project directory (default is TouchControlOverlay)"
exit 0
;;
-p | --project-root ) PROJECT_ROOT="$2"; shift 2 ;;
--sdl ) SDL_PROJECT="$2"; shift 2 ;;
--tco ) TCO_PROJECT="$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
cmake \
-DCMAKE_C_COMPILER="${QNX_HOST}/usr/bin/ntoarmv7-gcc" \
-DCMAKE_CXX_COMPILER="${QNX_HOST}/usr/bin/ntoarmv7-g++" \
-DSDL_INCLUDE_DIR="${SDL_PROJECT}/include" \
-DSDL_LIBRARY="${SDL_PROJECT}/Device-Release/libSDL12.so;${TCO_PROJECT}/Device-Release/libTouchControlOverlay.so" \
-DBLACKBERRY=${BB_OS} \
${PPSSPP_ROOT}
# Set up cmake with GCC 4.6.3 cross-compiler from PATH
CC=ntoarmv7-gcc CXX=ntoarmv7-g++ cmake -DBLACKBERRY=${BB_OS} ..
# Compile and create unsigned PPSSPP.bar with debugtoken
DEBUG="-devMode -debugToken ${HOME}/debugtoken.bar"

View file

@ -17,30 +17,46 @@ static const unsigned short key_ctrl_map[] = {
VK_LEFT, CTRL_LEFT,
VK_RIGHT, CTRL_RIGHT,
};
static const unsigned short analog_ctrl_map[] = {
'I', CTRL_UP,
'K', CTRL_DOWN,
'J', CTRL_LEFT,
'L', 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;
}
}
}
float analogX = 0;
float analogY = 0;
for (int i = 0; i < sizeof(analog_ctrl_map)/sizeof(analog_ctrl_map[0]); i += 2) {
if (!GetAsyncKeyState(analog_ctrl_map[i])) {
continue;
}
switch (analog_ctrl_map[i + 1]) {
case CTRL_UP:
analogY -= .8f;
break;
case CTRL_DOWN:
analogY += .8f;
break;
case CTRL_LEFT:
analogX -= .8f;
break;
case CTRL_RIGHT:
analogX += .8f;
break;
}
}
__CtrlSetAnalog(analogX, analogY);
return 0;
}

View file

@ -40,7 +40,28 @@ void WindowsHost::SetWindowTitle(const char *message)
// Really need a better way to deal with versions.
std::string title = "PPSSPP v0.4 - ";
title += message;
SetWindowText(mainWindow_, title.c_str());
int size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), NULL, 0);
if (size > 0)
{
wchar_t *utf16_title = new wchar_t[size + 1];
if (utf16_title)
size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), utf16_title, size);
else
size = 0;
if (size > 0)
{
utf16_title[size] = 0;
// Don't use SetWindowTextW because it will internally use DefWindowProcA.
DefWindowProcW(mainWindow_, WM_SETTEXT, 0, (LPARAM) utf16_title);
delete[] utf16_title;
}
}
// Something went wrong, fall back to using the local codepage.
if (size <= 0)
SetWindowTextA(mainWindow_, title.c_str());
}
void WindowsHost::InitSound(PMixer *mixer)

View file

@ -580,7 +580,7 @@ namespace MainWindow
case WM_USER+1:
disasmWindow[0] = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
DialogManager::AddDlg(disasmWindow[0]);
disasmWindow[0]->Show(TRUE);
disasmWindow[0]->Show(g_Config.bShowDebuggerOnLoad);
memoryWindow[0] = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
DialogManager::AddDlg(memoryWindow[0]);
if (disasmWindow[0])

View file

@ -73,7 +73,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
comm.dwSize = sizeof(comm);
comm.dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES;
InitCommonControlsEx(&comm);
timeBeginPeriod(1);
MainWindow::Init(_hInstance);
HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
@ -132,6 +132,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
LogManager::Shutdown();
DialogManager::DestroyAll();
timeEndPeriod(1);
g_Config.Save();
delete host;
return 0;

View file

@ -235,6 +235,62 @@ END
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Swedish (Sweden) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)
LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_POPUPMENUS MENU
BEGIN
POPUP "memview"
BEGIN
MENUITEM "Go to in &Disasm", ID_MEMVIEW_GOTOINDISASM
MENUITEM SEPARATOR
MENUITEM "&Copy value", ID_MEMVIEW_COPYVALUE
MENUITEM "&Dump...", ID_MEMVIEW_DUMP
END
POPUP "disasm"
BEGIN
MENUITEM "Copy &address", ID_DISASM_COPYADDRESS
MENUITEM "Copy instruction (&hex)", ID_DISASM_COPYINSTRUCTIONHEX
MENUITEM "Copy instruction (&disasm)", ID_DISASM_COPYINSTRUCTIONDISASM
MENUITEM SEPARATOR
MENUITEM "&Run to here", ID_DISASM_RUNTOHERE
MENUITEM "&Set Next Statement", ID_DISASM_SETPCTOHERE
MENUITEM "&Toggle breakpoint", ID_DISASM_TOGGLEBREAKPOINT
MENUITEM "&Follow branch", ID_DISASM_FOLLOWBRANCH
MENUITEM SEPARATOR
MENUITEM "&Show Dynarec Results", ID_DISASM_DYNARECRESULTS
MENUITEM "Go to in &Memory View", ID_DISASM_GOTOINMEMORYVIEW
MENUITEM SEPARATOR
MENUITEM "&Kill function", ID_DISASM_ADDHLE
MENUITEM "&Rename function...", ID_DISASM_RENAMEFUNCTION
END
POPUP "funclist"
BEGIN
MENUITEM "&Kill function", ID_FUNCLIST_KILLFUNCTION
END
POPUP "reglist"
BEGIN
MENUITEM "Go to in &memory view", ID_REGLIST_GOTOINMEMORYVIEW
MENUITEM "Go to in &disasm", ID_REGLIST_GOTOINDISASM
MENUITEM SEPARATOR
MENUITEM "&Copy value", ID_REGLIST_COPYVALUE
MENUITEM "C&hange...", ID_REGLIST_CHANGE
END
END
/////////////////////////////////////////////////////////////////////////////
//
// RT_MANIFEST
@ -307,6 +363,25 @@ END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_GAMELISTPATH "Path"
IDS_UNIMPLEMENTED "Unimplemented"
END
STRINGTABLE
BEGIN
IDS_GAMELISTGENRE "Genre"
IDS_APPNAME "Potemkin"
IDS_GAMELISTTYPE "Type"
END
#endif // Swedish (Sweden) resources
/////////////////////////////////////////////////////////////////////////////

View file

@ -1,104 +0,0 @@
cmake_minimum_required(VERSION 2.6)
project (PPSSPP)
find_package(PkgConfig)
find_package(PNG REQUIRED)
pkg_check_modules(SDL sdl)
if (APPLE)
find_library(OGL_LIBRARY OpenGL)
include_directories(/usr/X11/include)
endif()
include(FindOpenGL)
include(FindSDL)
add_definitions(-g)
add_definitions(-O0)
add_definitions(-Wall)
add_definitions(-DSDL)
add_definitions(-Wno-multichar)
add_definitions(-fno-strict-aliasing)
add_definitions(-DUSE_PROFILER)
include_directories(jni)
include_directories(../native)
include_directories(../native/base)
include_directories(../native/math/lin)
include_directories(../native/audio)
include_directories(../native/ext/libzip)
include_directories(../native/ext/etcpack)
include_directories(/usr/local/include)
include_directories(${SDL_INCLUDE_DIR})
include_directories(${PNG_INCLUDE_DIR})
link_directories(/usr/local/lib)
link_directories(/usr/X11/lib)
add_subdirectory(../native/base base)
add_subdirectory(../native/gfx gfx)
add_subdirectory(../native/profiler profiler)
add_subdirectory(../native/gfx_es2 gfx_es2)
add_subdirectory(../native/file file)
add_subdirectory(../native/image image)
add_subdirectory(../native/ui ui)
add_subdirectory(../native/net net)
add_subdirectory(../native/json jsonwriter)
add_subdirectory(../native/audio audio)
add_subdirectory(../native/math math)
add_subdirectory(../native/ext/libzip libzip)
add_subdirectory(../native/ext/etcpack etcpack)
add_subdirectory(../native/ext/vjson vjson)
add_subdirectory(../native/ext/stb_vorbis stb_vorbis)
add_subdirectory(../native/ext/sha1 sha1)
set(LIBS ${LIBS} ${SDL_LIBRARY} ${OPENGL_LIBRARIES} GLEW file lin ${PNG_LIBRARY} z gfx gfx_es2 ui etcdec image mixer net profiler timeutil file zip base lin vjson stb_vorbis sha1 jsonwriter)
set(FILES
jni/ui_atlas.cpp
jni/ray_intersections.cpp
jni/collision.cpp
jni/AudioManager.cpp
jni/Campaign.cpp
jni/CampaignEndScreen.cpp
jni/CalibrateScreen.cpp
jni/CreditsScreen.cpp
jni/Curves.cpp
jni/CollidableMesh.cpp
jni/DrawList.cpp
jni/Globals.cpp
jni/Level.cpp
jni/CampaignEndScreen.cpp
jni/Material.cpp
jni/MainMenuScreen.cpp
jni/MessageBus.cpp
jni/Mesh.cpp
jni/MeshGenerator.cpp
jni/NativeApp.cpp
jni/GfxUtil.cpp
jni/GfxWrapper.cpp
jni/BallSimulator.cpp
jni/Node.cpp
jni/NormalGame.cpp
jni/NormalGameScreen.cpp
jni/Scene.cpp
jni/Sky.cpp
jni/ShaderManager.cpp
jni/StickSim.cpp
jni/TextureManager.cpp
jni/Transformation.cpp)
if (APPLE)
SET(FILES ${FILES} jni/SDLMain.m)
endif (APPLE)
add_executable(rollerball ../native/base/PCMain.cpp ${FILES})
target_link_libraries(rollerball ${LIBS})
#add_executable(meshtool jni/Meshtool.cpp ${FILES})
#target_link_libraries(meshtool ${LIBS})

View file

@ -1,2 +1,2 @@
APP_STL := stlport_static
APP_ABI := armeabi-v7a
APP_ABI := armeabi armeabi-v7a

View file

@ -379,16 +379,23 @@ static const char *credits[] =
"ced2911",
"soywiz",
"kovensky",
"xsacha",
"",
"Written in C++ for speed and portability",
"",
"",
"Free tools used:",
#ifdef ANDROID
"Android SDK + NDK",
#elif BLACKBERRY
"Blackberry NDK",
#else
"SDL",
#endif
"CMake",
"freetype2",
"zlib",
"the free PSP SDK",
"PSP SDK",
"",
"",
"Check out the website:",

@ -1 +1 @@
Subproject commit 3c81649c4b4056ddabaca293c093ba0d6989502b
Subproject commit 494e3592da54708e6178a3f6efa1467a4403c2fc

View file

@ -47,6 +47,8 @@ tests_good = [
"cpu/lsu/lsu",
"cpu/fpu/fpu",
"ctrl/ctrl",
"ctrl/sampling/sampling",
"display/display",
"dmac/dmactest",
"loader/bss/bss",
@ -95,7 +97,6 @@ tests_next = [
"threads/vpl/vpl",
"threads/vtimers/vtimer",
"threads/wakeup/wakeup",
"ctrl/ctrl",
"gpu/simple/simple",
"gpu/triangle/triangle",
"hle/check_not_used_uids",