diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 11116c94c3..85b308eb11 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -338,9 +338,9 @@
-
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index 7ac7a64719..ebf5ad45bd 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -527,8 +527,8 @@
-
+
\ No newline at end of file
diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp
index 4be48dace0..5313b5a1f2 100644
--- a/Core/HLE/HLE.cpp
+++ b/Core/HLE/HLE.cpp
@@ -97,7 +97,7 @@ const char *GetFuncName(const char *moduleName, u32 nib)
else
{
static char temp[256];
- sprintf(temp,"[UNK:%08x]",nib);
+ sprintf(temp,"[UNK: 0x%08x ]",nib);
return temp;
}
}
diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp
index e564a3fbc2..9305852bcd 100644
--- a/Core/HLE/sceAudio.cpp
+++ b/Core/HLE/sceAudio.cpp
@@ -23,6 +23,11 @@
#include "__sceAudio.h"
#include "HLE.h"
+
+// There's a second Audio api called Audio2 that only has one channel, I guess the 8 channel api was overkill.
+// We simply map it to the first of the 8 channels.
+
+
AudioChannel chans[8];
// Enqueues the buffer pointer on the channel. If channel buffer queue is full (2 items?) will block until it isn't.
@@ -90,17 +95,17 @@ u32 sceAudioOutputPanned(u32 chan, u32 leftVol, u32 rightVol, u32 samplePtr)
}
}
-u32 sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr)
+void sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr)
{
if (chan < 0 || chan >= MAX_CHANNEL)
{
ERROR_LOG(HLE,"sceAudioOutputBlocking() - BAD CHANNEL");
- return SCE_ERROR_AUDIO_INVALID_CHANNEL;
+ RETURN(SCE_ERROR_AUDIO_INVALID_CHANNEL);
}
else if (!chans[chan].reserved)
{
ERROR_LOG(HLE,"sceAudioOutputBlocking() - channel not reserved");
- return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
+ RETURN(SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED);
}
else
{
@@ -109,7 +114,7 @@ u32 sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr)
chans[chan].leftVolume = vol;
chans[chan].rightVolume = vol;
chans[chan].sampleAddress = samplePtr;
- return __AudioEnqueue(chans[chan], chan, true);
+ __AudioEnqueue(chans[chan], chan, true);
}
}
@@ -236,13 +241,56 @@ void sceAudioInit()
RETURN(0);
}
+void sceAudioOutput2Reserve()
+{
+ int sampleCount = PARAM(0);
+ ERROR_LOG(HLE,"sceAudioOutput2Reserve(%i)", sampleCount);
+ chans[0].sampleCount = sampleCount;
+ chans[0].reserved = true;
+ RETURN(0);
+}
+
+void sceAudioOutput2OutputBlocking()
+{
+ int vol = PARAM(0);
+ u32 dataPtr = PARAM(1);
+
+ ERROR_LOG(HLE,"UNIMPL sceAudioOutput2OutputBlocking(%i, %08x)", vol, dataPtr);
+ chans[0].running = true;
+ chans[0].leftVolume = vol;
+ chans[0].rightVolume = vol;
+ chans[0].sampleAddress = dataPtr;
+ __AudioEnqueue(chans[0], 0, true);
+
+ RETURN(0);
+}
+
+void sceAudioOutput2ChangeLength()
+{
+ ERROR_LOG(HLE,"UNIMPL sceAudioOutput2ChangeLength");
+ RETURN(0);
+}
+
+void sceAudioOutput2GetRestSample()
+{
+ ERROR_LOG(HLE,"UNIMPL sceAudioOutput2GetRestSample");
+ RETURN(0);
+}
+
+void sceAudioOutput2Release()
+{
+ ERROR_LOG(HLE,"sceAudioOutput2Release()");
+ chans[0].reserved = false;
+ RETURN(0);
+}
+
const HLEFunction sceAudio[] =
{
- {0x01562ba3, 0, "sceAudioOutput2Reserve"}, // Super Stardust Portable uses these
- {0x2d53f36e, 0, "sceAudioOutput2OutputBlocking"},
- {0x63f2889c, 0, "sceAudioOutput2ChangeLength"},
- {0x647cef33, 0, "sceAudioOutput2GetRestSample"},
- {0x43196845, 0, "sceAudioOutput2Release"},
+ {0x01562ba3, sceAudioOutput2Reserve, "sceAudioOutput2Reserve"}, // N+, Super Stardust Portable uses these
+ {0x2d53f36e, sceAudioOutput2OutputBlocking, "sceAudioOutput2OutputBlocking"},
+ {0x63f2889c, sceAudioOutput2ChangeLength, "sceAudioOutput2ChangeLength"},
+ {0x647cef33, sceAudioOutput2GetRestSample, "sceAudioOutput2GetRestSample"},
+ {0x43196845, sceAudioOutput2Release, "sceAudioOutput2Release"},
{0x210567F7, 0, "sceAudioEnd"},
{0x38553111, 0, "sceAudioSRCChReserve"},
@@ -256,7 +304,7 @@ const HLEFunction sceAudio[] =
{0xE0727056, 0, "sceAudioSRCOutputBlocking"},
{0xE926D3FB, 0, "sceAudioInputInitEx"},
{0x8c1009b2, 0, "sceAudioOutput"},
- {0x136CAF51, WrapU_UUU, "sceAudioOutputBlocking"},
+ {0x136CAF51, WrapV_UUU, "sceAudioOutputBlocking"},
{0xE2D56B2D, WrapU_UUUU, "sceAudioOutputPanned"},
{0x13F592BC, WrapV_UUUU, "sceAudioOutputPannedBlocking"}, //(u32, u32, u32, void *)Output sound, blocking
{0x5EC81C55, WrapU_UUU, "sceAudioChReserve"}, //(u32, u32 samplecount, u32) Initialize channel and allocate buffer long, long samplecount, long);//init buffer? returns handle, minus if error
diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp
index a482759af6..0667bc3d1e 100644
--- a/Core/HLE/sceCtrl.cpp
+++ b/Core/HLE/sceCtrl.cpp
@@ -76,17 +76,22 @@ void sceCtrlInit()
{
ctrlInited = true;
memset(&ctrl, 0, sizeof(ctrl));
- DEBUG_LOG(HLE,"sceCtrlInit");
+ ctrl.analog[0] = 128;
+ ctrl.analog[1] = 128;
+ DEBUG_LOG(HLE,"sceCtrlInit");
}
void sceCtrlSetSamplingMode()
{
- DEBUG_LOG(HLE,"sceCtrlSetSamplingMode");
+ u32 mode = PARAM(0);
+ DEBUG_LOG(HLE,"sceCtrlSetSamplingMode(%i) ra=%08x", mode, currentMIPS->r[MIPS_REG_RA]);
if (ctrlInited)
{
+ RETURN((u32)analogEnabled);
// Looks odd
- analogEnabled = true;
+ analogEnabled = mode;
}
+ RETURN(0);
}
void sceCtrlSetIdleCancelThreshold()
@@ -146,8 +151,8 @@ void sceCtrlReadBufferPositive()
analogX += 100;
}
- data.analog[0]=analogX;
- data.analog[1]=analogY;
+ data.analog[0] = analogX;
+ data.analog[1] = analogY;
#endif
memcpy(Memory::GetPointer(ctrlData), &data, sizeof(_ctrl_data));
diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp
index 269e2b84a1..c49d94be2d 100644
--- a/Core/HLE/sceGe.cpp
+++ b/Core/HLE/sceGe.cpp
@@ -146,7 +146,9 @@ u32 sceGeSetCallback(u32 structAddr)
void sceGeUnsetCallback(u32 cbID)
{
- ERROR_LOG(HLE,"UNIMPL sceGeUnsetCallback(cbid=%08x)", cbID);
+ DEBUG_LOG(HLE,"sceGeUnsetCallback(cbid=%08x)", cbID);
+ sceKernelReleaseSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH);
+ sceKernelReleaseSubIntrHandler(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL);
}
void sceGeSaveContext()
diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h
index baca7e4eb2..b93089676b 100644
--- a/Core/HLE/sceKernelInterrupt.h
+++ b/Core/HLE/sceKernelInterrupt.h
@@ -63,6 +63,7 @@ bool __RunOnePendingInterrupt();
void __KernelReturnFromInterrupt();
u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg);
+u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber);
void Register_Kernel_Library();
void Register_InterruptManager();
diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp
index fd16ba283f..884a89911b 100644
--- a/Core/HLE/sceKernelMemory.cpp
+++ b/Core/HLE/sceKernelMemory.cpp
@@ -432,7 +432,10 @@ void sceKernelGetBlockHeadAddr()
void sceKernelPrintf()
{
+ const char *formatString = Memory::GetCharPointer(PARAM(0));
+
ERROR_LOG(HLE,"UNIMPL sceKernelPrintf(%08x, %08x, %08x, %08x)", PARAM(0),PARAM(1),PARAM(2),PARAM(3));
+ ERROR_LOG(HLE,"%s", formatString);
RETURN(0);
}
@@ -588,8 +591,24 @@ void sceKernelTryAllocateVpl()
void sceKernelFreeVpl()
{
- ERROR_LOG(HLE,"UNIMPL: sceKernelFreeVpl()");
- RETURN(0);
+ SceUID id = PARAM(0);
+ u32 blockPtr = PARAM(1);
+ DEBUG_LOG(HLE,"sceKernelFreeVpl(%i, %08x)", id, blockPtr);
+ u32 error;
+ VPL *vpl = kernelObjects.Get(id, error);
+ if (vpl)
+ {
+ if (vpl->alloc.Free(blockPtr)) {
+ RETURN(0);
+ // Should trigger waiting threads
+ } else {
+ ERROR_LOG(HLE, "sceKernelFreeVpl: Error freeing %08x", blockPtr);
+ RETURN(-1);
+ }
+ }
+ else {
+ RETURN(error);
+ }
}
void sceKernelCancelVpl()
diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp
index 2072ef423e..2f569e9e52 100644
--- a/Core/HLE/sceKernelModule.cpp
+++ b/Core/HLE/sceKernelModule.cpp
@@ -623,14 +623,22 @@ void sceKernelStopModule()
{
ERROR_LOG(HLE,"UNIMPL sceKernelStopModule");
RETURN(0);
-
}
void sceKernelUnloadModule()
{
- ERROR_LOG(HLE,"UNIMPL sceKernelUnloadModule");
- RETURN(0);
+ u32 moduleId = PARAM(0);
+ ERROR_LOG(HLE,"UNIMPL sceKernelUnloadModule(%i)", moduleId);
+ u32 error;
+ Module *module = kernelObjects.Get(moduleId, error);
+ if (!module)
+ {
+ RETURN(error);
+ return;
+ }
+ kernelObjects.Destroy(moduleId);
+ RETURN(0);
}
void sceKernelGetModuleIdByAddress()
diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp
index 4f8b26f116..8900ebee58 100644
--- a/Core/HLE/sceMpeg.cpp
+++ b/Core/HLE/sceMpeg.cpp
@@ -93,6 +93,11 @@ const HLEFunction sceMpeg[] =
{0xf2930c9c,0,"sceMpegAvcDecodeStopYCbCr"},
{0x31bd0272,0,"sceMpegAvcCsc"},
{0xa11c7026,0,"sceMpegAvcDecodeMode"},
+ {0x0558B075,0,"sceMpegAvcCopyYCbCr"},
+ {0x769BEBB6,0,"sceMpegRingbufferQueryPackNum"},
+ {0x8C1E027D,0,"sceMpegGetPcmAu"},
+ {0x9DCFB7EA,0,"sceMpegChangeGetAuMode"},
+ {0xC02CF6B5,0,"sceMpegQueryPcmEsSize"},
};
const HLEFunction sceMp3[] =
diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp
index 84d594b9da..bbf41d23d7 100644
--- a/Core/HLE/scePsmf.cpp
+++ b/Core/HLE/scePsmf.cpp
@@ -81,11 +81,22 @@ const HLEFunction scePsmf[] =
{0xA5EBFE81,0,"scePsmfGetStreamSizeFunction"},
};
+void scePsmfPlayerCreate() {
+ DEBUG_LOG(HLE, "scePsmfPlayerCreate");
+ RETURN(0);
+}
+
+void scePsmfPlayerReleasePsmf() {
+ DEBUG_LOG(HLE, "scePsmfPlayerReleasePsmf");
+ RETURN(0);
+}
+
+
const HLEFunction scePsmfPlayer[] =
{
+ {0x235d8787,scePsmfPlayerCreate,"scePsmfPlayerCreateFunction"},
{0x1078c008,0,"scePsmfPlayerStopFunction"},
{0x1e57a8e7,0,"scePsmfPlayerConfigPlayer"},
- {0x235d8787,0,"scePsmfPlayerCreateFunction"},
{0x2beb1569,0,"scePsmfPlayerBreak"},
{0x3d6d25a9,0,"scePsmfPlayerSetPsmfFunction"},
{0x3ea82a4b,0,"scePsmfPlayerGetAudioOutSize"},
@@ -103,11 +114,14 @@ const HLEFunction scePsmfPlayer[] =
{0xb8d10c56,0,"scePsmfPlayerSelectAudio"},
{0xb9848a74,0,"scePsmfPlayerGetAudioData"},
{0xdf089680,0,"scePsmfPlayerGetPsmfInfo"},
- {0xe792cd94,0,"scePsmfPlayerReleasePsmfFunction"},
+ {0xe792cd94,scePsmfPlayerReleasePsmf,"scePsmfPlayerReleasePsmfFunction"},
{0xf3efaa91,0,"scePsmfPlayerGetCurrentPlayMode"},
{0xf8ef08a6,0,"scePsmfPlayerGetCurrentStatus"},
{0x2D0E4E0A,0,"scePsmfPlayerSetTempBufFunction"},
{0x58B83577,0,"scePsmfPlayerSetPsmfCBFunction"},
+ {0x2673646B,0,"scePsmfVerifyPsmf"},
+ {0x4E624A34,0,"scePsmfGetEPWithId"},
+ {0x5F457515,0,"scePsmfGetEPidWithTimestampFunction"},
};
void Register_scePsmf() {
diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp
index 7ea14a4930..d2423d6c18 100644
--- a/Core/MIPS/MIPSIntVFPU.cpp
+++ b/Core/MIPS/MIPSIntVFPU.cpp
@@ -646,9 +646,33 @@ namespace MIPSInt
break;
case 2: //vi2us
- //break;
+ {
+ for (int i = 0; i < GetNumVectorElements(sz) / 2; i++) {
+ int low = s[i * 2];
+ int high = s[i * 2 + 1];
+ if (low < 0) low = 0;
+ if (high < 0) high = 0;
+ low >>= 15;
+ high >>= 15;
+ d[i] = low | (high << 16);
+ }
+ if (sz == V_Quad) oz = V_Pair;
+ if (sz == V_Pair) oz = V_Single;
+ }
+ break;
case 3: //vi2s
- //break;
+ {
+ for (int i = 0; i < GetNumVectorElements(sz) / 2; i++) {
+ u32 low = s[i * 2];
+ u32 high = s[i * 2 + 1];
+ low >>= 16;
+ high >>= 16;
+ d[i] = low | (high << 16);
+ }
+ if (sz == V_Quad) oz = V_Pair;
+ if (sz == V_Pair) oz = V_Single;
+ }
+ break;
default:
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
break;