diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a48b2b886..858bc710c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -721,6 +721,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/HLE/scesupPreAcc.h
Core/HLE/sceUmd.cpp
Core/HLE/sceUmd.h
+ Core/HLE/sceUsb.cpp
+ Core/HLE/sceUsb.h
Core/HLE/sceUtility.cpp
Core/HLE/sceUtility.h
Core/HLE/sceVaudio.cpp
diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt
index 5aea4f6758..771ba59694 100644
--- a/Core/CMakeLists.txt
+++ b/Core/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRCS
HLE/sceRtc.cpp
HLE/sceSas.cpp
HLE/sceUmd.cpp
+ HLE/sceUsb.cpp
HLE/sceUtility.cpp
HLE/sceParseUri.cpp
HLE/sceSsl.cpp
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index c56e477604..0e795fcf0b 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -170,6 +170,7 @@
+
@@ -317,6 +318,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index a15d95c867..27b57d8951 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -349,6 +349,9 @@
>>>>>>> master
HW
+
+ HLE\Libraries
+
@@ -640,6 +643,9 @@
HW
+
+ HLE\Libraries
+
diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp
index c9bc5a6db7..6cffd3d3eb 100644
--- a/Core/CoreTiming.cpp
+++ b/Core/CoreTiming.cpp
@@ -504,6 +504,8 @@ void Idle(int maxIdle)
idledCycles += cyclesDown;
downcount -= cyclesDown;
+ if (downcount == 0)
+ downcount = -1;
}
std::string GetScheduledEventsSummary()
diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp
index 64089cf6d3..6513fb7b9a 100644
--- a/Core/FileSystems/DirectoryFileSystem.cpp
+++ b/Core/FileSystems/DirectoryFileSystem.cpp
@@ -138,7 +138,7 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access)
if (!success)
{
#ifdef _WIN32
- ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, %i", GetLastError());
+ ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", GetLastError(), (int)access);
#endif
//wwwwaaaaahh!!
return 0;
diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp
index b77c1d8223..11c8e88954 100644
--- a/Core/FileSystems/ISOFileSystem.cpp
+++ b/Core/FileSystems/ISOFileSystem.cpp
@@ -21,6 +21,7 @@
#include
#include
+
const int sectorSize = 2048;
static bool parseLBN(std::string filename, u32 *sectorStart, u32 *readSize)
@@ -209,7 +210,7 @@ nextblock:
e->isBlockSectorMode = false;
// Let's not excessively spam the log - I commented this line out.
- // DEBUG_LOG(FILESYS, "%s: %s %08x %08x %i", e->isDirectory?"D":"F", name, dir.firstDataSectorLE, e->startingPosition, e->startingPosition);
+ //DEBUG_LOG(FILESYS, "%s: %s %08x %08x %i", e->isDirectory?"D":"F", name, dir.firstDataSectorLE, e->startingPosition, e->startingPosition);
if (e->isDirectory && !relative)
{
@@ -253,8 +254,15 @@ ISOFileSystem::TreeEntry *ISOFileSystem::GetFromPath(std::string path)
{
for (size_t i=0; ichildren.size(); i++)
{
- std::string n = e->children[i]->name;
+ std::string n = (e->children[i]->name);
+ for (size_t j = 0; j < n.size(); j++) {
+ n[j] = tolower(n[j]);
+ }
std::string curPath = path.substr(0, path.find_first_of('/'));
+ for (size_t j = 0; j < curPath.size(); j++) {
+ curPath[j] = tolower(curPath[j]);
+ }
+
if (curPath == n)
{
//yay we got it
diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp
index b1b48ba11d..9d69f1d138 100644
--- a/Core/FileSystems/MetaFileSystem.cpp
+++ b/Core/FileSystems/MetaFileSystem.cpp
@@ -116,6 +116,12 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st
std::vector cmpnts; // path components
size_t capacityGuess = inPath.length();
+ // Special hack for strange root paths.
+ // Don't understand why this is needed. I don't think the current
+ // directory should be the root.
+ if (inAfter.substr(0, 11) == "./PSP_GAME/")
+ inAfter = inAfter.substr(1);
+
if ((inAfter[0] != '/'))
{
if (curDirLen == 0)
diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp
index 682c93005e..69af4be0c0 100644
--- a/Core/HLE/HLE.cpp
+++ b/Core/HLE/HLE.cpp
@@ -175,7 +175,8 @@ void ResolveSyscall(const char *moduleName, u32 nib, u32 address)
{
INFO_LOG(HLE,"Resolving %s/%08x",moduleName,nib);
// Note: doing that, we can't trace external module calls, so maybe something else should be done to debug more efficiently
- Memory::Write_U32(MIPS_MAKE_JAL(address), sysc->symAddr);
+ // Note that this should be J not JAL, as otherwise control will return to the stub..
+ Memory::Write_U32(MIPS_MAKE_J(address), sysc->symAddr);
Memory::Write_U32(MIPS_MAKE_NOP(), sysc->symAddr + 4);
}
}
diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp
index 67d1ef8d9e..a2e2f5a634 100644
--- a/Core/HLE/HLETables.cpp
+++ b/Core/HLE/HLETables.cpp
@@ -53,6 +53,7 @@
#include "sceParseHttp.h"
#include "scesupPreAcc.h"
#include "sceVaudio.h"
+#include "sceUsb.h"
#define N(s) s
@@ -185,43 +186,12 @@ const HLEFunction pspeDebug[] =
};
-const HLEFunction sceUsb[] =
-{
- {0xae5de6af, 0, "sceUsbStart"},
- {0xc2464fa0, 0, "sceUsbStop"},
- {0xc21645a4, 0, "sceUsbGetState"},
- {0x4e537366, 0, "sceUsbGetDrvList"},
- {0x112cc951, 0, "sceUsbGetDrvState"},
- {0x586db82c, 0, "sceUsbActivate"},
- {0xc572a9c8, 0, "sceUsbDeactivate"},
- {0x5be0e002, 0, "sceUsbWaitState"},
- {0x1c360735, 0, "sceUsbWaitCancel"},
-};
-
-const HLEFunction sceUsbstor[] =
-{
- {0x60066CFE, 0, "sceUsbstorGetStatus"},
-};
-
-const HLEFunction sceUsbstorBoot[] =
-{
- {0xE58818A8, 0, "sceUsbstorBootSetCapacity"},
- {0x594BBF95, 0, "sceUsbstorBootSetLoadAddr"},
- {0x6D865ECD, 0, "sceUsbstorBootGetDataSize"},
- {0xA1119F0D, 0, "sceUsbstorBootSetStatus"},
- {0x1F080078, 0, "sceUsbstorBootRegisterNotify"},
- {0xA55C9E16, 0, "sceUsbstorBootUnregisterNotify"},
-};
-
const HLEModule moduleList[] =
{
{"FakeSysCalls", SZ(FakeSysCalls), FakeSysCalls},
{"UtilsForUser",SZ(UtilsForUser),UtilsForUser},
{"KDebugForKernel",SZ(KDebugForKernel),KDebugForKernel},
{"sceSAScore"},
- {"sceUsbstor",SZ(sceUsbstor),sceUsbstor},
- {"sceUsbstorBoot",SZ(sceUsbstorBoot),sceUsbstorBoot},
- {"sceUsb", SZ(sceUsb), sceUsb},
{"SceBase64_Library"},
{"sceCert_Loader"},
{"SceFont_Library"},
@@ -275,6 +245,7 @@ void RegisterAllModules() {
Register_sceParseHttp();
Register_scesupPreAcc();
Register_sceVaudio();
+ Register_sceUsb();
for (int i = 0; i < numModules; i++)
{
diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp
index e880d228b2..bf22116aeb 100644
--- a/Core/HLE/__sceAudio.cpp
+++ b/Core/HLE/__sceAudio.cpp
@@ -38,15 +38,15 @@ std::recursive_mutex section;
int eventAudioUpdate = -1;
int eventHostAudioUpdate = -1;
-int mixFrequency = 48000;
-const int hwSampleRate = 48000;
+int mixFrequency = 44100;
+const int hwSampleRate = 44100;
const int hwBlockSize = 480;
const int hostAttemptBlockSize = 64;
const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate);
const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate);
// High and low watermarks, basically.
-const int chanQueueMaxSizeFactor = 12;
+const int chanQueueMaxSizeFactor = 4;
const int chanQueueMinSizeFactor = 1;
FixedSizeQueue outAudioQueue;
@@ -67,7 +67,7 @@ void hleHostAudioUpdate(u64 userdata, int cyclesLate)
void __AudioInit()
{
- mixFrequency = 48000;
+ mixFrequency = 44100;
eventAudioUpdate = CoreTiming::RegisterEvent("AudioUpdate", &hleAudioUpdate);
eventHostAudioUpdate = CoreTiming::RegisterEvent("AudioUpdateHost", &hleHostAudioUpdate);
@@ -95,8 +95,8 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking)
chan.waitingThread = __KernelGetCurThread();
// WARNING: This changes currentThread so must grab waitingThread before (line above).
__KernelWaitCurThread(WAITTYPE_AUDIOCHANNEL, (SceUID)chanNum, 0, 0, false);
- section.unlock();
- return 0;
+ // Fall through to the sample queueing, don't want to lose the samples even though
+ // we're getting full.
}
else
{
@@ -151,8 +151,8 @@ void __AudioUpdate()
if (chans[i].sampleQueue.size() >= 2)
{
s16 sampleL = chans[i].sampleQueue.front();
- s16 sampleR = chans[i].sampleQueue.front();
chans[i].sampleQueue.pop();
+ s16 sampleR = chans[i].sampleQueue.front();
chans[i].sampleQueue.pop();
mixBuffer[s * 2] += sampleL;
mixBuffer[s * 2 + 1] += sampleR;
@@ -225,7 +225,7 @@ int __AudioMix(short *outstereo, int numFrames)
}
}
if (anythingToPlay && underrun >= 0) {
- DEBUG_LOG(HLE, "audio out buffer UNDERRUN at %i of %i", underrun, numFrames);
+ ERROR_LOG(HLE, "audio out buffer UNDERRUN at %i of %i", underrun, numFrames);
} else {
// DEBUG_LOG(HLE, "No underrun, mixed %i samples fine", numFrames);
}
diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp
index be2cc3652f..bcfcb6300c 100644
--- a/Core/HLE/sceAudio.cpp
+++ b/Core/HLE/sceAudio.cpp
@@ -227,7 +227,6 @@ u32 sceAudioSetChannelDataLen(u32 chan, u32 len)
else
{
DEBUG_LOG(HLE, "sceAudioSetChannelDataLen(%i, %i)", chan, len);
- //chans[chan].dataLen = len;
chans[chan].sampleCount = len;
return 0;
}
@@ -335,6 +334,11 @@ u32 sceAudioSetFrequency(u32 freq) {
}
}
+u32 sceAudioSetVolumeOffset(u32 unknown) {
+ ERROR_LOG(HLE, "UNIMPL sceAudioSetVolumeOffset(%i)", unknown);
+ return 0;
+}
+
const HLEFunction sceAudio[] =
{
// Newer simplified single channel audio output. Presumably for games that use Atrac3
@@ -349,7 +353,7 @@ const HLEFunction sceAudio[] =
{0x210567F7, WrapU_V, "sceAudioEnd"},
{0xA2BEAA6C, WrapU_U, "sceAudioSetFrequency"},
- {0x927AC32B, 0, "sceAudioSetVolumeOffset"},
+ {0x927AC32B, WrapU_U, "sceAudioSetVolumeOffset"},
// The oldest and standard audio interface. Supports 8 channels, most games use 1-2.
{0x8c1009b2, WrapU_UUU, "sceAudioOutput"},
diff --git a/Core/HLE/sceAudio.h b/Core/HLE/sceAudio.h
index 356a7efff1..6f1305b0d6 100644
--- a/Core/HLE/sceAudio.h
+++ b/Core/HLE/sceAudio.h
@@ -51,7 +51,6 @@ struct AudioChannel
// last sample address
u32 sampleAddress;
u32 sampleCount; // Number of samples written in each OutputBlocking
- int dataLen; // Probably internal queue size. Not currently used.
int leftVolume;
int rightVolume;
diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp
index c1938e3f86..df34fda23c 100644
--- a/Core/HLE/sceDisplay.cpp
+++ b/Core/HLE/sceDisplay.cpp
@@ -85,8 +85,9 @@ enum {
struct WaitVBlankInfo
{
+ WaitVBlankInfo(u32 tid) : threadID(tid), vcountUnblock(0) {}
u32 threadID;
- int vcountUnblock;
+ int vcountUnblock; // what was this for again?
};
std::vector vblankWaitingThreads;
@@ -144,7 +145,10 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
__DisplayFireVblank();
// Wake up threads waiting for VBlank
- __KernelTriggerWait(WAITTYPE_VBLANK, 0, true);
+ for (int i = 0; i < vblankWaitingThreads.size(); i++) {
+ __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0);
+ }
+ vblankWaitingThreads.clear();
// Trigger VBlank interrupt handlers.
__TriggerInterrupt(PSP_VBLANK_INTR);
@@ -201,7 +205,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
gpuStats.resetFrame();
}
-
host->EndFrame();
#ifdef _WIN32
@@ -262,7 +265,7 @@ u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres)
return 0;
}
-void sceDisplaySetFramebuf()
+u32 sceDisplaySetFramebuf()
{
//host->EndFrame();
u32 topaddr = PARAM(0);
@@ -295,8 +298,7 @@ void sceDisplaySetFramebuf()
latchedFramebuf = fbstate;
framebufIsLatched = true;
}
-
- RETURN(0);
+ return 0;
}
u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode)
@@ -318,46 +320,57 @@ u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, i
void sceDisplayWaitVblankStart()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblankStart()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false);
}
void sceDisplayWaitVblank()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblank()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false);
}
void sceDisplayWaitVblankStartMulti()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMulti()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false);
}
void sceDisplayWaitVblankCB()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true);
}
void sceDisplayWaitVblankStartCB()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true);
}
void sceDisplayWaitVblankStartMultiCB()
{
DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()");
+ vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread()));
__KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true);
}
-void sceDisplayGetVcount()
+u32 sceDisplayGetVcount()
{
// Too spammy
// DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount);
- // Games like Puyo Puyo call this in a tight loop at end-of-frame. We could have it consume some time from CoreTiming?
+
+ // Puyo Puyo Fever polls this as a substitute for waiting vblank.
+ // As a result, the game never gets to reschedule so it doesn't mix audio and things break.
+ // I added this as a workaround until we figure out what call actually does reschedule - it doesn't call much though...
+
CoreTiming::Idle(1000000);
- RETURN(vCount);
+ __KernelReSchedule(); // Puyo puyo hack?
+ return vCount;
}
void sceDisplayGetCurrentHcount()
@@ -383,19 +396,19 @@ float sceDisplayGetFramePerSec()
const HLEFunction sceDisplay[] =
{
- {0x0E20F177,&WrapU_UUU, "sceDisplaySetMode"},
- {0x289D82FE,sceDisplaySetFramebuf, "sceDisplaySetFramebuf"},
- {0xEEDA2E54,&WrapU_UUUI,"sceDisplayGetFrameBuf"},
+ {0x0E20F177,WrapU_UUU, "sceDisplaySetMode"},
+ {0x289D82FE,WrapU_V, "sceDisplaySetFramebuf"},
+ {0xEEDA2E54,WrapU_UUUI,"sceDisplayGetFrameBuf"},
{0x36CDFADE,sceDisplayWaitVblank, "sceDisplayWaitVblank"},
{0x984C27E7,sceDisplayWaitVblankStart, "sceDisplayWaitVblankStart"},
{0x40f1469c,sceDisplayWaitVblankStartMulti, "sceDisplayWaitVblankStartMulti"},
{0x8EB9EC49,sceDisplayWaitVblankCB, "sceDisplayWaitVblankCB"},
{0x46F186C3,sceDisplayWaitVblankStartCB, "sceDisplayWaitVblankStartCB"},
{0x77ed8b3a,sceDisplayWaitVblankStartMultiCB,"sceDisplayWaitVblankStartMultiCB"},
- {0xdba6c4c4,&WrapF_V,"sceDisplayGetFramePerSec"},
+ {0xdba6c4c4,WrapF_V,"sceDisplayGetFramePerSec"},
{0x773dd3a3,sceDisplayGetCurrentHcount,"sceDisplayGetCurrentHcount"},
{0x210eab3a,sceDisplayGetAccumulatedHcount,"sceDisplayGetAccumulatedHcount"},
- {0x9C6EAAD7,sceDisplayGetVcount,"sceDisplayGetVcount"},
+ {0x9C6EAAD7,WrapU_V,"sceDisplayGetVcount"},
{0xDEA197D4,0,"sceDisplayGetMode"},
{0x7ED59BC4,0,"sceDisplaySetHoldMode"},
{0xA544C486,0,"sceDisplaySetResumeMode"},
diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp
index f2a775ba66..c26347cb7f 100644
--- a/Core/HLE/sceKernel.cpp
+++ b/Core/HLE/sceKernel.cpp
@@ -51,6 +51,7 @@
#include "sceUtility.h"
#include "sceUmd.h"
#include "sceSsl.h"
+#include "sceSas.h"
#include "../Util/PPGeDraw.h"
@@ -77,6 +78,7 @@ void __KernelInit()
__KernelThreadingInit();
__IoInit();
__AudioInit();
+ __SasInit();
__DisplayInit();
__InterruptsInit();
__GeInit();
@@ -109,6 +111,7 @@ void __KernelShutdown()
__PPGeShutdown();
__GeShutdown();
+ __SasShutdown();
__AudioShutdown();
__IoShutdown();
__InterruptsShutdown();
@@ -385,8 +388,8 @@ const HLEFunction ThreadManForUser[] =
{0x840E8133,sceKernelWaitThreadEndCB,"sceKernelWaitThreadEndCB"},
{0xd13bde95,sceKernelCheckThreadStack,"sceKernelCheckThreadStack"},
- {0x94416130,0,"sceKernelGetThreadmanIdList"},
- {0x57CF62DD,sceKernelGetThreadmanIdType,"sceKernelGetThreadmanIdType"},
+ {0x94416130,WrapU_UUUU,"sceKernelGetThreadmanIdList"},
+ {0x57CF62DD,WrapU_U,"sceKernelGetThreadmanIdType"},
{0x20fff560,sceKernelCreateVTimer,"sceKernelCreateVTimer"},
{0x328F9E52,0,"sceKernelDeleteVTimer"},
diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp
index 76f9c5faf9..a1e0976b82 100644
--- a/Core/HLE/sceKernelThread.cpp
+++ b/Core/HLE/sceKernelThread.cpp
@@ -522,20 +522,35 @@ void sceKernelGetThreadExitStatus()
}
}
-void sceKernelGetThreadmanIdType()
+u32 sceKernelGetThreadmanIdType(u32 uid) {
+ int type;
+ if (kernelObjects.GetIDType(uid, &type)) {
+ DEBUG_LOG(HLE, "%i=sceKernelGetThreadmanIdType(%i)", type, uid);
+ return type;
+ } else {
+ ERROR_LOG(HLE, "sceKernelGetThreadmanIdType(%i) - FAILED", uid);
+ return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
+ }
+}
+
+u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr)
{
- SceUID uid = PARAM(0);
- int type;
- if (kernelObjects.GetIDType(uid, &type))
- {
- RETURN(type);
- DEBUG_LOG(HLE, "%i=sceKernelGetThreadmanIdType(%i)", type, uid);
- }
- else
- {
- ERROR_LOG(HLE, "sceKernelGetThreadmanIdType(%i) - FAILED", uid);
- RETURN(SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT);
- }
+ DEBUG_LOG(HLE, "sceKernelGetThreadmanIdList(%i, %08x, %i, %08x)",
+ type, readBufPtr, readBufSize, idCountPtr);
+ if (!Memory::IsValidAddress(readBufPtr))
+ return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
+
+ if (type != SCE_KERNEL_TMID_Thread) {
+ ERROR_LOG(HLE, "sceKernelGetThreadmanIdList only implemented for threads");
+ return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < std::min(readBufSize, threadqueue.size()); i++)
+ {
+ Memory::Write_U32(threadqueue[i]->GetUID(), readBufPtr + i * 4);
+ }
+ Memory::Write_U32(threadqueue.size(), idCountPtr);
+ return 0;
}
// Saves the current CPU context
diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h
index 8735d3c0ce..8ecbb1eede 100644
--- a/Core/HLE/sceKernelThread.h
+++ b/Core/HLE/sceKernelThread.h
@@ -51,7 +51,8 @@ int sceKernelTerminateDeleteThread(int threadno);
int sceKernelTerminateThread(u32 threadID);
void sceKernelWaitThreadEndCB();
void sceKernelGetThreadExitStatus();
-void sceKernelGetThreadmanIdType();
+u32 sceKernelGetThreadmanIdType(u32);
+u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 idCountPtr);
enum WaitType //probably not the real values
@@ -104,7 +105,9 @@ SceUID __KernelGetCurThread();
void __KernelSaveContext(ThreadContext *ctx);
void __KernelLoadContext(ThreadContext *ctx);
-// TODO: Replace this with __KernelResumeThread over time as it's misguided.
+// TODO: Replace this with __KernelResumeThreadFromWait over time as it's misguided.
+// It's better that each subsystem keeps track of the list of waiting threads
+// and resumes them manually one by one using __KernelResumeThreadFromWait.
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
diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp
index b8902626bc..c19ae2c5bd 100644
--- a/Core/HLE/sceSas.cpp
+++ b/Core/HLE/sceSas.cpp
@@ -44,19 +44,27 @@ enum {
// TODO - allow more than one, associating each with one Core pointer (passed in to all the functions)
// No known games use more than one instance of Sas though.
-SasInstance sas;
+SasInstance *sas;
+
+void __SasInit() {
+ sas = new SasInstance();
+}
+
+void __SasShutdown() {
+ delete sas;
+ sas = 0;
+}
u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate)
{
- DEBUG_LOG(HLE,"0=sceSasInit(%08x, %i, maxVoices=%i, %i, %i)", core, grainSize, maxVoices, outputMode, sampleRate);
- memset(&sas, 0, sizeof(sas));
- sas.SetGrainSize(grainSize);
- sas.maxVoices = maxVoices;
- sas.sampleRate = sampleRate;
- sas.outputMode = outputMode;
+ INFO_LOG(HLE,"0=sceSasInit(%08x, grainSize=%i, maxVoices=%i, %i, %i)", core, grainSize, maxVoices, outputMode, sampleRate);
+ sas->SetGrainSize(grainSize);
+ sas->maxVoices = maxVoices;
+ sas->sampleRate = sampleRate;
+ sas->outputMode = outputMode;
for (int i = 0; i < 32; i++) {
- sas.voices[i].playing = false;
+ sas->voices[i].playing = false;
}
return 0;
}
@@ -64,8 +72,8 @@ u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampl
u32 sceSasGetEndFlag(u32 core)
{
u32 endFlag = 0;
- for (int i = 0; i < sas.maxVoices; i++) {
- if (!sas.voices[i].playing)
+ for (int i = 0; i < sas->maxVoices; i++) {
+ if (!sas->voices[i].playing)
endFlag |= 1 << i;
}
DEBUG_LOG(HLE,"%08x=sceSasGetEndFlag()", endFlag);
@@ -75,23 +83,23 @@ u32 sceSasGetEndFlag(u32 core)
// Runs the mixer
u32 _sceSasCore(u32 core, u32 outAddr)
{
- DEBUG_LOG(HLE,"0=sceSasCore(, %08x) (grain: %i samples)", outAddr, sas.GetGrainSize());
+ DEBUG_LOG(HLE,"0=sceSasCore(, %08x) (grain: %i samples)", outAddr, sas->GetGrainSize());
if (!Memory::IsValidAddress(outAddr)) {
return ERROR_SAS_INVALID_PARAMETER;
}
- Memory::Memset(outAddr, 0, sas.GetGrainSize() * 2 * 2);
- sas.Mix(outAddr);
+ Memory::Memset(outAddr, 0, sas->GetGrainSize() * 2 * 2);
+ sas->Mix(outAddr);
return 0;
}
// Another way of running the mixer, what was the difference again?
u32 _sceSasCoreWithMix(u32 core, u32 outAddr)
{
- DEBUG_LOG(HLE,"0=sceSasCoreWithMix(, %08x) (grain: %i samples)", outAddr, sas.GetGrainSize());
+ DEBUG_LOG(HLE,"0=sceSasCoreWithMix(, %08x) (grain: %i samples)", outAddr, sas->GetGrainSize());
if (!Memory::IsValidAddress(outAddr)) {
return ERROR_SAS_INVALID_PARAMETER;
}
- sas.Mix(outAddr);
+ sas->Mix(outAddr);
return 0;
}
@@ -107,20 +115,32 @@ u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop)
}
//Real VAG header is 0x30 bytes behind the vagAddr
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.type = VOICETYPE_VAG;
v.vagAddr = vagAddr;
v.vagSize = size;
v.loop = loop ? true : false;
- v.ChangedParams();
+ v.ChangedParams(true);
+ return 0;
+}
+
+u32 sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop)
+{
+ DEBUG_LOG(HLE,"0=sceSasSetVoicePCM(core=%08x, voicenum=%i, pcmAddr=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop);
+ SasVoice &v = sas->voices[voiceNum];
+ v.type = VOICETYPE_PCM;
+ v.pcmAddr = pcmAddr;
+ v.pcmSize = size;
+ v.loop = loop ? true : false;
+ v.playing = true;
return 0;
}
u32 sceSasGetPauseFlag(u32 core)
{
u32 pauseFlag = 0;
- for (int i = 0; i < sas.maxVoices; i++) {
- if (sas.voices[i].paused)
+ for (int i = 0; i < sas->maxVoices; i++) {
+ if (sas->voices[i].paused)
pauseFlag |= 1 << i;
}
DEBUG_LOG(HLE,"%08x=sceSasGetPauseFlag()", pauseFlag);
@@ -135,7 +155,7 @@ u32 sceSasSetPause(u32 core, int voicebit, int pause)
if (i < PSP_SAS_VOICES_MAX && i >= 0)
{
if ((voicebit & 1) != 0)
- sas.voices[i].paused = pause ? true : false;
+ sas->voices[i].paused = pause ? true : false;
}
// TODO: Correct error code? Mimana crashes otherwise.
else
@@ -155,7 +175,7 @@ u32 sceSasSetVolume(u32 core, int voiceNum, int l, int r, int el, int er)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.volumeLeft = l;
v.volumeRight = r;
return 0;
@@ -171,7 +191,7 @@ u32 sceSasSetPitch(u32 core, int voiceNum, int pitch)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.pitch = pitch;
return 0;
}
@@ -186,7 +206,7 @@ u32 sceSasSetKeyOn(u32 core, int voiceNum)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.KeyOn();
return 0;
}
@@ -202,7 +222,7 @@ u32 sceSasSetKeyOff(u32 core, int voiceNum)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.KeyOff();
return 0;
}
@@ -217,7 +237,7 @@ u32 sceSasSetNoise(u32 core, int voiceNum, int freq)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.type = VOICETYPE_NOISE;
v.noiseFreq = freq;
return 0;
@@ -233,7 +253,7 @@ u32 sceSasSetSL(u32 core, int voiceNum, int level)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.envelope.sustainLevel = level;
return 0;
}
@@ -248,7 +268,7 @@ u32 sceSasSetADSR(u32 core, int voiceNum,int flag ,int a, int d, int s, int r)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
if ((flag & 0x1) != 0) v.envelope.attackRate = a;
if ((flag & 0x2) != 0) v.envelope.decayRate = d;
if ((flag & 0x4) != 0) v.envelope.sustainRate = s;
@@ -266,7 +286,7 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
if ((flag & 0x1) != 0) v.envelope.attackType = a;
if ((flag & 0x2) != 0) v.envelope.decayType = d;
if ((flag & 0x4) != 0) v.envelope.sustainType = s;
@@ -278,7 +298,7 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int
u32 sceSasSetSimpleADSR(u32 core, u32 voiceNum, u32 ADSREnv1, u32 ADSREnv2)
{
DEBUG_LOG(HLE,"0=sasSetSimpleADSR(%08x, %i, %08x, %08x)", core, voiceNum, ADSREnv1, ADSREnv2);
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
v.envelope.SetSimpleEnvelope(ADSREnv1 & 0xFFFF, ADSREnv2 & 0xFFFF);
return 0;
}
@@ -296,85 +316,74 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum)
return ERROR_SAS_INVALID_VOICE;
}
- SasVoice &v = sas.voices[voiceNum];
+ SasVoice &v = sas->voices[voiceNum];
return v.envelope.GetHeight();
}
u32 sceSasRevType(u32 core, int type)
{
DEBUG_LOG(HLE,"0=sceSasRevType(core=%08x, type=%i)", core, type);
- sas.waveformEffect.type = type;
+ sas->waveformEffect.type = type;
return 0;
}
u32 sceSasRevParam(u32 core, int delay, int feedback)
{
DEBUG_LOG(HLE,"0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback);
- sas.waveformEffect.delay = delay;
- sas.waveformEffect.feedback = feedback;
+ sas->waveformEffect.delay = delay;
+ sas->waveformEffect.feedback = feedback;
return 0;
}
u32 sceSasRevEVOL(u32 core, int lv, int rv)
{
DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i)", core, lv, rv);
- sas.waveformEffect.leftVol = lv;
- sas.waveformEffect.rightVol = rv;
+ sas->waveformEffect.leftVol = lv;
+ sas->waveformEffect.rightVol = rv;
return 0;
}
u32 sceSasRevVON(u32 core, int dry, int wet)
{
DEBUG_LOG(HLE,"0=sceSasRevVON(core=%08x, dry=%i, wet=%i)", core, dry, wet);
- sas.waveformEffect.isDryOn = (dry > 0);
- sas.waveformEffect.isWetOn = (wet > 0);
+ sas->waveformEffect.isDryOn = (dry > 0);
+ sas->waveformEffect.isWetOn = (wet > 0);
return 0;
}
u32 sceSasGetGrain(u32 core)
{
DEBUG_LOG(HLE,"0=sceSasGetGrain(core=%08x)", core);
- return sas.GetGrainSize();
+ return sas->GetGrainSize();
}
u32 sceSasSetGrain(u32 core, int grain)
{
- DEBUG_LOG(HLE,"0=sceSasSetGrain(core=%08x, grain=%i)", core, grain);
- sas.SetGrainSize(grain);
+ INFO_LOG(HLE,"0=sceSasSetGrain(core=%08x, grain=%i)", core, grain);
+ sas->SetGrainSize(grain);
return 0;
}
u32 sceSasGetOutputMode(u32 core)
{
DEBUG_LOG(HLE,"0=sceSasGetOutputMode(core=%08x)", core);
- return sas.outputMode;
+ return sas->outputMode;
}
u32 sceSasSetOutputMode(u32 core, u32 outputMode)
{
DEBUG_LOG(HLE,"0=sceSasSetOutputMode(core=%08x, outputMode=%i)", core, outputMode);
- sas.outputMode = outputMode;
+ sas->outputMode = outputMode;
return 0;
}
-u32 sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop)
-{
- DEBUG_LOG(HLE,"0=sceSasSetVoicePCM(core=%08x, voicenum=%i, pcmAddr=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop);
- SasVoice &v = sas.voices[voiceNum];
- v.type = VOICETYPE_PCM;
- v.pcmAddr = pcmAddr;
- v.pcmSize = size;
- v.loop = loop ? true : false;
- v.playing = true;
- return 0;
-}
u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr)
{
DEBUG_LOG(HLE,"0=sceSasGetAllEnvelopeHeights(core=%08x, heightsAddr=%i)", core, heightsAddr);
if (Memory::IsValidAddress(heightsAddr)) {
- for (int i = 0; i < sas.length; i++) {
- int voiceHeight = sas.voices[i].envelope.GetHeight();
+ for (int i = 0; i < PSP_SAS_VOICES_MAX; i++) {
+ int voiceHeight = sas->voices[i].envelope.GetHeight();
Memory::Write_U32(voiceHeight, heightsAddr + i * 4);
}
}
diff --git a/Core/HLE/sceSas.h b/Core/HLE/sceSas.h
index bc3e331bbf..58efddd75b 100644
--- a/Core/HLE/sceSas.h
+++ b/Core/HLE/sceSas.h
@@ -17,4 +17,7 @@
#pragma once
+void __SasInit();
+void __SasShutdown();
+
void Register_sceSasCore();
diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp
index 4fa68cf5e5..fbe74b1ce8 100644
--- a/Core/HLE/sceUmd.cpp
+++ b/Core/HLE/sceUmd.cpp
@@ -284,14 +284,14 @@ int sceUmdWaitDriveStatCB(u32 stat, u32 timeout)
return 0;
}
-void sceUmdCancelWaitDriveStat()
+u32 sceUmdCancelWaitDriveStat()
{
DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()");
- RETURN(0);
__KernelTriggerWait(WAITTYPE_UMD, 1, SCE_KERNEL_ERROR_WAIT_CANCEL, true);
// 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.
+ return 0;
}
u32 sceUmdGetErrorStat()
@@ -300,6 +300,19 @@ u32 sceUmdGetErrorStat()
return umdErrorStat;
}
+u32 sceUmdReplaceProhibit()
+{
+ DEBUG_LOG(HLE,"sceUmdReplaceProhibit()");
+ return 0;
+}
+
+u32 sceUmdReplacePermit()
+{
+ DEBUG_LOG(HLE,"sceUmdReplacePermit()");
+ return 0;
+}
+
+
const HLEFunction sceUmdUser[] =
{
@@ -310,13 +323,14 @@ const HLEFunction sceUmdUser[] =
{0x8EF08FCE,WrapI_U,"sceUmdWaitDriveStat"},
{0x56202973,WrapI_UU,"sceUmdWaitDriveStatWithTimer"},
{0x4A9E5E29,WrapI_UU,"sceUmdWaitDriveStatCB"},
- {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"},
+ {0x6af9b50a,WrapU_V,"sceUmdCancelWaitDriveStat"},
{0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"},
{0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"},
{0x340B7686,WrapU_U,"sceUmdGetDiscInfo"},
{0xAEE7404D,&WrapU_U,"sceUmdRegisterUMDCallBack"},
{0xBD2BDE07,&WrapU_U,"sceUmdUnRegisterUMDCallBack"},
- {0x87533940,0,"sceUmdReplaceProhibit"}, // ??? sounds bogus
+ {0x87533940,WrapU_V,"sceUmdReplaceProhibit"},
+ {0x87533940,WrapU_V,"sceUmdReplacePermit"},
};
void Register_sceUmdUser()
diff --git a/Core/HLE/sceUsb.cpp b/Core/HLE/sceUsb.cpp
new file mode 100644
index 0000000000..faec5397a9
--- /dev/null
+++ b/Core/HLE/sceUsb.cpp
@@ -0,0 +1,64 @@
+// 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
+// the Free Software Foundation, version 2.0 or later versions.
+
+// 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/.
+
+#include "HLE.h"
+#include "../MIPS/MIPS.h"
+#include "../../Core/CoreTiming.h"
+#include "sceUsb.h"
+
+bool usbActivated = false;
+
+u32 sceUsbActivate() {
+ ERROR_LOG(HLE, "UNIMPL sceUsbActivate");
+ usbActivated = true;
+ return 0;
+}
+
+const HLEFunction sceUsb[] =
+{
+ {0xae5de6af, 0, "sceUsbStart"},
+ {0xc2464fa0, 0, "sceUsbStop"},
+ {0xc21645a4, 0, "sceUsbGetState"},
+ {0x4e537366, 0, "sceUsbGetDrvList"},
+ {0x112cc951, 0, "sceUsbGetDrvState"},
+ {0x586db82c, WrapU_V, "sceUsbActivate"},
+ {0xc572a9c8, 0, "sceUsbDeactivate"},
+ {0x5be0e002, 0, "sceUsbWaitState"},
+ {0x1c360735, 0, "sceUsbWaitCancel"},
+};
+
+const HLEFunction sceUsbstor[] =
+{
+ {0x60066CFE, 0, "sceUsbstorGetStatus"},
+};
+
+const HLEFunction sceUsbstorBoot[] =
+{
+ {0xE58818A8, 0, "sceUsbstorBootSetCapacity"},
+ {0x594BBF95, 0, "sceUsbstorBootSetLoadAddr"},
+ {0x6D865ECD, 0, "sceUsbstorBootGetDataSize"},
+ {0xA1119F0D, 0, "sceUsbstorBootSetStatus"},
+ {0x1F080078, 0, "sceUsbstorBootRegisterNotify"},
+ {0xA55C9E16, 0, "sceUsbstorBootUnregisterNotify"},
+};
+
+void Register_sceUsb()
+{
+ RegisterModule("sceUsbstor", ARRAY_SIZE(sceUsbstor), sceUsbstor);
+ RegisterModule("sceUsbstorBoot", ARRAY_SIZE(sceUsbstorBoot), sceUsbstorBoot);
+ RegisterModule("sceUsb", ARRAY_SIZE(sceUsb), sceUsb);
+}
diff --git a/Core/HLE/sceUsb.h b/Core/HLE/sceUsb.h
new file mode 100644
index 0000000000..009f44ec96
--- /dev/null
+++ b/Core/HLE/sceUsb.h
@@ -0,0 +1,20 @@
+// 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
+// the Free Software Foundation, version 2.0 or later versions.
+
+// 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/.
+
+#pragma once
+
+void Register_sceUsb();
diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp
index 6ee4dc95cc..c9413b3308 100644
--- a/Core/HW/SasAudio.cpp
+++ b/Core/HW/SasAudio.cpp
@@ -61,13 +61,9 @@ bool VagDecoder::DecodeBlock()
for (int i = 0; i < 28; i += 2)
{
int d = GetByte();
- int s = (d & 0xf) << 12;
- if (s & 0x8000)
- s |= 0xffff0000;
+ int s = (short)((d & 0xf) << 12);
samples[i] = (double)(s >> shift_factor);
- s = (d & 0xf0) << 8;
- if (s & 0x8000)
- s |= 0xffff0000;
+ s = (short)((d & 0xf0) << 8);
samples[i + 1] = (double)(s >> shift_factor);
}
for (int i = 0; i < 28; i++)
@@ -83,7 +79,7 @@ bool VagDecoder::DecodeBlock()
void VagDecoder::GetSamples(s16 *outSamples, int numSamples) {
if (end_) {
- memset(outSamples, 0, numSamples * sizeof(int));
+ memset(outSamples, 0, numSamples * sizeof(s16));
return;
}
for (int i = 0; i < numSamples; i++) {
@@ -172,7 +168,8 @@ void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) {
sustainLevel = getSustainLevel(ADSREnv1);
}
-SasInstance::SasInstance() : mixBuffer(0), sendBuffer(0), resampleBuffer(0), grainSize(0) {
+SasInstance::SasInstance()
+ : mixBuffer(0), sendBuffer(0), resampleBuffer(0), grainSize(0) {
}
SasInstance::~SasInstance() {
@@ -182,15 +179,16 @@ SasInstance::~SasInstance() {
}
void SasInstance::SetGrainSize(int newGrainSize) {
+ grainSize = newGrainSize;
+
if (mixBuffer)
delete [] mixBuffer;
if (sendBuffer)
delete [] sendBuffer;
- mixBuffer = new s32[newGrainSize * 2];
- sendBuffer = new s32[newGrainSize * 2];
- memset(mixBuffer, 0, sizeof(int) * newGrainSize * 2);
- memset(sendBuffer, 0, sizeof(int) * newGrainSize * 2);
- grainSize = newGrainSize;
+ mixBuffer = new s32[grainSize * 2];
+ sendBuffer = new s32[grainSize * 2];
+ memset(mixBuffer, 0, sizeof(int) * grainSize * 2);
+ memset(sendBuffer, 0, sizeof(int) * grainSize * 2);
if (resampleBuffer)
delete [] resampleBuffer;
@@ -209,7 +207,7 @@ void SasInstance::Mix(u32 outAddr) {
// TODO: Special case no-resample case for speed
- if (voice.vagAddr != 0) {
+ if (voice.type == VOICETYPE_VAG && voice.vagAddr != 0) {
// Load resample history (so we can use a wide filter)
resampleBuffer[0] = voice.resampleHist[0];
resampleBuffer[1] = voice.resampleHist[1];
@@ -217,7 +215,11 @@ void SasInstance::Mix(u32 outAddr) {
// Figure out number of samples to read.
int curSample = voice.samplePos / PSP_SAS_PITCH_BASE;
int lastSample = (voice.samplePos + grainSize * voice.pitch) / PSP_SAS_PITCH_BASE;
- int numSamples = lastSample - curSample;
+ u32 numSamples = lastSample - curSample;
+ if (numSamples > grainSize * 4) {
+ ERROR_LOG(SAS, "numSamples too large, clamping: %i vs %i", numSamples, grainSize * 4);
+ numSamples = grainSize * 4;
+ }
// Read N samples into the resample buffer. Could do either PCM or VAG here.
voice.vag.GetSamples(resampleBuffer + 2, numSamples);
@@ -254,16 +256,17 @@ void SasInstance::Mix(u32 outAddr) {
sendBuffer[i * 2 + 1] += sample * voice.volumeRightSend >> 15;
voice.envelope.Step();
}
+ voice.samplePos += voice.pitch * grainSize;
if (voice.envelope.HasEnded())
{
// NOTICE_LOG(SAS, "Hit end of envelope");
voice.playing = false;
}
}
- else if (voice.pcmAddr != 0) {
+ else if (voice.type == VOICETYPE_PCM && voice.pcmAddr != 0) {
// PCM mixing should be easy, can share code with VAG
}
- else if (voice.noiseFreq != 0) {
+ else if (voice.type == VOICETYPE_NOISE && voice.noiseFreq != 0) {
// Generate noise?
}
}
@@ -298,17 +301,22 @@ void SasVoice::Reset() {
}
void SasVoice::KeyOn() {
- on = true;
- playing = true;
- paused = false;
envelope.KeyOn();
switch (type) {
case VOICETYPE_VAG:
- vag.Start(Memory::GetPointer(vagAddr), loop);
+ if (Memory::IsValidAddress(vagAddr)) {
+ vag.Start(Memory::GetPointer(vagAddr), loop);
+ } else {
+ ERROR_LOG(SAS, "Invalid VAG address %08x", vagAddr);
+ return;
+ }
break;
default:
break;
}
+ playing = true;
+ on = true;
+ paused = false;
}
void SasVoice::KeyOff() {
@@ -316,9 +324,11 @@ void SasVoice::KeyOff() {
envelope.KeyOff();
}
-void SasVoice::ChangedParams() {
+void SasVoice::ChangedParams(bool changedVag) {
if (!playing && on) {
playing = true;
+ if (changedVag)
+ vag.Start(Memory::GetPointer(vagAddr), loop);
}
// TODO: restart VAG somehow
}
diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h
index 4478652cf8..3b776f5c6d 100644
--- a/Core/HW/SasAudio.h
+++ b/Core/HW/SasAudio.h
@@ -61,12 +61,13 @@ struct WaveformEffect
};
enum VoiceType {
- VOICETYPE_VAG = 0, // default
- VOICETYPE_PCM = 1,
- VOICETYPE_NOISE = 2,
- VOICETYPE_ATRAC3 = 3,
- VOICETYPE_TRIWAVE = 4, // are these used? there are functions for them (sceSetTriangularWave)
- VOICETYPE_PULSEWAVE = 5,
+ VOICETYPE_OFF,
+ VOICETYPE_VAG, // default
+ VOICETYPE_PCM,
+ VOICETYPE_NOISE,
+ VOICETYPE_ATRAC3,
+ VOICETYPE_TRIWAVE, // are these used? there are functions for them (sceSetTriangularWave)
+ VOICETYPE_PULSEWAVE,
};
// VAG is a Sony ADPCM audio compression format, which goes all the way back to the PSX.
@@ -76,6 +77,7 @@ enum VoiceType {
class VagDecoder
{
public:
+ VagDecoder() : data_(0), read_(0) {}
void Start(u8 *data, bool loopEnabled);
void GetSamples(s16 *outSamples, int numSamples);
@@ -154,6 +156,23 @@ private:
// It's not very likely that games encode VAG dynamically.
struct SasVoice
{
+ SasVoice()
+ : playing(false), paused(false), on(false),
+ type(VOICETYPE_OFF),
+ vagAddr(0),
+ vagSize(0),
+ pcmAddr(0),
+ pcmSize(0),
+ sampleRate(44100),
+ samplePos(0),
+ pitch(PSP_SAS_PITCH_BASE),
+ loop(false),
+ noiseFreq(0),
+ volumeLeft(0),
+ volumeRight(0),
+ volumeLeftSend(0),
+ volumeRightSend(0) {}
+
bool playing;
bool paused; // a voice can be playing AND paused. In that case, it won't play.
bool on; // key-on, key-off.
@@ -182,7 +201,7 @@ struct SasVoice
void KeyOn();
void KeyOff();
- void ChangedParams();
+ void ChangedParams(bool changedVag);
s16 resampleHist[2];
@@ -203,7 +222,6 @@ public:
int maxVoices;
int sampleRate;
int outputMode;
- int length;
int *mixBuffer;
int *sendBuffer;
diff --git a/Core/System.cpp b/Core/System.cpp
index da48ca9969..18c2b94687 100644
--- a/Core/System.cpp
+++ b/Core/System.cpp
@@ -112,7 +112,7 @@ void PSP_Shutdown()
currentCPU = 0;
}
-const CoreParameter &PSP_CoreParameter()
+CoreParameter &PSP_CoreParameter()
{
return coreParameter;
}
diff --git a/Core/System.h b/Core/System.h
index 352897e640..a3340b2a21 100644
--- a/Core/System.h
+++ b/Core/System.h
@@ -29,4 +29,4 @@ bool PSP_IsInited();
void PSP_Shutdown();
void PSP_HWAdvance(int cycles);
void PSP_SWI();
-const CoreParameter &PSP_CoreParameter();
\ No newline at end of file
+CoreParameter &PSP_CoreParameter();
\ No newline at end of file
diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp
index 630e966797..90931d75bc 100644
--- a/GPU/GLES/DisplayListInterpreter.cpp
+++ b/GPU/GLES/DisplayListInterpreter.cpp
@@ -47,7 +47,8 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight)
: interruptsEnabled_(true),
renderWidth_(renderWidth),
renderHeight_(renderHeight),
- dlIdGenerator(1)
+ dlIdGenerator(1),
+ displayFramebufPtr_(0)
{
renderWidthFactor_ = (float)renderWidth / 480.0f;
renderHeightFactor_ = (float)renderHeight / 272.0f;
@@ -106,7 +107,7 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format)
displayStride_ = stride;
displayFormat_ = format;
} else {
- DEBUG_LOG(HLE, "Bogus framebuffer address: %08x", framebuf);
+ ERROR_LOG(HLE, "Bogus framebuffer address: %08x", framebuf);
}
}
@@ -1182,8 +1183,8 @@ void GLES_GPU::DoBlockTransfer()
u32 srcBasePtr = (gstate.transfersrc & 0xFFFFFF) | ((gstate.transfersrcw & 0xFF0000) << 8);
u32 srcStride = gstate.transfersrcw & 0x3FF;
- u32 dstBasePtr = (gstate.transfersrc & 0xFFFFFF) | ((gstate.transfersrcw & 0xFF0000) << 8);
- u32 dstStride = gstate.transfersrcw & 0x3FF;
+ u32 dstBasePtr = (gstate.transferdst & 0xFFFFFF) | ((gstate.transferdstw & 0xFF0000) << 8);
+ u32 dstStride = gstate.transferdstw & 0x3FF;
int srcX = gstate.transfersrcpos & 0x3FF;
int srcY = (gstate.transfersrcpos >> 10) & 0x3FF;
diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp
index 31071a23b6..58ce633357 100644
--- a/GPU/GLES/TransformPipeline.cpp
+++ b/GPU/GLES/TransformPipeline.cpp
@@ -556,34 +556,34 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte
// All is valid, no blendcolor needed
glstate.blendFunc.set(aLookup[blendFuncA], bLookup[blendFuncB]);
} else {
- GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? 0 : aLookup[blendFuncA];
- GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? 0 : bLookup[blendFuncB];
+ GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? GL_INVALID_ENUM : aLookup[blendFuncA];
+ GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? GL_INVALID_ENUM : bLookup[blendFuncB];
u32 fixA = gstate.getFixA();
u32 fixB = gstate.getFixB();
// Shortcut by using GL_ONE where possible, no need to set blendcolor
- if (!glBlendFuncA && blendFuncA == GE_SRCBLEND_FIXA) {
+ if (glBlendFuncA == GL_INVALID_ENUM && blendFuncA == GE_SRCBLEND_FIXA) {
if (fixA == 0xFFFFFF)
glBlendFuncA = GL_ONE;
else if (fixA == 0)
glBlendFuncA = GL_ZERO;
}
- if (!glBlendFuncB && blendFuncB == GE_DSTBLEND_FIXB) {
+ if (glBlendFuncB == GL_INVALID_ENUM && blendFuncB == GE_DSTBLEND_FIXB) {
if (fixB == 0xFFFFFF)
glBlendFuncB = GL_ONE;
else if (fixB == 0)
glBlendFuncB = GL_ZERO;
}
- if (!glBlendFuncA && glBlendFuncB) {
+ if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB != GL_INVALID_ENUM) {
// Can use blendcolor trivially.
const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f};
glstate.blendColor.set(blendColor);
glBlendFuncA = GL_CONSTANT_COLOR;
- } else if (glBlendFuncA && !glBlendFuncB) {
+ } else if (glBlendFuncA != GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) {
// Can use blendcolor trivially.
const float blendColor[4] = {(fixB & 0xFF)/255.0f, ((fixB >> 8) & 0xFF)/255.0f, ((fixB >> 16) & 0xFF)/255.0f, 1.0f};
glstate.blendColor.set(blendColor);
glBlendFuncB = GL_CONSTANT_COLOR;
- } else if (!glBlendFuncA && !glBlendFuncB) { // Should also check for approximate equality
+ } else if (glBlendFuncA == GL_INVALID_ENUM && glBlendFuncB == GL_INVALID_ENUM) { // Should also check for approximate equality
if (fixA == (fixB ^ 0xFFFFFF)) {
glBlendFuncA = GL_CONSTANT_COLOR;
glBlendFuncB = GL_ONE_MINUS_CONSTANT_COLOR;
diff --git a/GPU/GPUState.h b/GPU/GPUState.h
index f11eb33bff..a111b09418 100644
--- a/GPU/GPUState.h
+++ b/GPU/GPUState.h
@@ -226,9 +226,10 @@ struct GPUgstate
transferstart,
transfersrcpos,
transferdstpos,
- transfersize;
+ pad99,
+ transfersize; // 0xEE
- u32 pad05[0x63-0x40];
+ u32 pad05[0xFF- 0xEE];
};
};
diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj
index 8016e5e377..4d14a6d2e3 100644
--- a/Windows/PPSSPP.vcxproj
+++ b/Windows/PPSSPP.vcxproj
@@ -323,6 +323,7 @@
+
@@ -360,4 +361,4 @@
-
+
\ No newline at end of file
diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters
index 5786358b73..c76c21f6ca 100644
--- a/Windows/PPSSPP.vcxproj.filters
+++ b/Windows/PPSSPP.vcxproj.filters
@@ -203,6 +203,7 @@
Android
+
diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp
index a80e17345c..dfcbb99462 100644
--- a/Windows/WndMainWindow.cpp
+++ b/Windows/WndMainWindow.cpp
@@ -18,6 +18,7 @@
#include "main.h"
#include "../Core/Core.h"
+#include "../Core/System.h"
#include "../Core/MemMap.h"
#include "EmuThread.h"
@@ -117,6 +118,8 @@ namespace MainWindow
GetWindowRectAtZoom(zoom, rc, rcOuter);
MoveWindow(hwndMain, rcOuter.left, rcOuter.top, rcOuter.right - rcOuter.left, rcOuter.bottom - rcOuter.top, TRUE);
MoveWindow(hwndDisplay, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
+ PSP_CoreParameter().pixelWidth = 480 * zoom;
+ PSP_CoreParameter().pixelHeight = 272 * zoom;
GL_Resized();
}
diff --git a/Windows/main.cpp b/Windows/main.cpp
index 7170d7ba2a..1a859b1a89 100644
--- a/Windows/main.cpp
+++ b/Windows/main.cpp
@@ -56,6 +56,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
token = strtok(szCmdLine," ");
g_Config.Load();
+ VFSRegister("", new DirectoryAssetReader("assets/"));
VFSRegister("", new DirectoryAssetReader(""));
while (token)
diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc
index d3c0c6b5d7..8ddb89699d 100644
--- a/Windows/ppsspp.rc
+++ b/Windows/ppsspp.rc
@@ -190,20 +190,20 @@ BEGIN
END
POPUP "&Emulation"
BEGIN
- MENUITEM "&Run", ID_EMULATION_RUN
- MENUITEM "&Pause", ID_EMULATION_PAUSE
+ MENUITEM "&Run\tF7", ID_EMULATION_RUN
+ MENUITEM "&Pause\tF8", ID_EMULATION_PAUSE
MENUITEM SEPARATOR
MENUITEM "R&eset", ID_EMULATION_RESET
MENUITEM SEPARATOR
MENUITEM "&Interpreter", ID_CPU_INTERPRETER
- MENUITEM "&Slightly faster interpreter", ID_CPU_FASTINTERPRETER
+ MENUITEM "&Slightly Faster Interpreter", ID_CPU_FASTINTERPRETER
MENUITEM "&Dynarec", ID_CPU_DYNAREC, CHECKED
END
POPUP "Debu&g"
BEGIN
MENUITEM "Load &Map File...", ID_DEBUG_LOADMAPFILE
MENUITEM "&Save Map File...", ID_DEBUG_SAVEMAPFILE
- MENUITEM "&Reset symbol table", ID_DEBUG_RESETSYMBOLTABLE
+ MENUITEM "&Reset Symbol Table", ID_DEBUG_RESETSYMBOLTABLE
MENUITEM SEPARATOR
MENUITEM "&Disassembly\tCtrl+D", ID_DEBUG_DISASSEMBLY
MENUITEM "&Log Console\tCtrl+L", ID_DEBUG_LOG
@@ -212,14 +212,14 @@ BEGIN
POPUP "&Options"
BEGIN
MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN
- MENUITEM "&Display raw framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER
- MENUITEM "&Buffered rendering", ID_OPTIONS_BUFFEREDRENDERING
- MENUITEM "&Show debug statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS
+ MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER
+ MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING
+ MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS
MENUITEM SEPARATOR
- MENUITEM "Screen &1x", ID_OPTIONS_SCREEN1X
- MENUITEM "Screen &2x", ID_OPTIONS_SCREEN2X
- MENUITEM "Screen &3x", ID_OPTIONS_SCREEN3X
- MENUITEM "Screen &4x", ID_OPTIONS_SCREEN4X
+ MENUITEM "Screen &1x\tCtrl+1", ID_OPTIONS_SCREEN1X
+ MENUITEM "Screen &2x\tCtrl+2", ID_OPTIONS_SCREEN2X
+ MENUITEM "Screen &3x\tCtrl+3", ID_OPTIONS_SCREEN3X
+ MENUITEM "Screen &4x\tCtrl+4", ID_OPTIONS_SCREEN4X
MENUITEM SEPARATOR
MENUITEM "&Ignore illegal reads/writes", ID_OPTIONS_IGNOREILLEGALREADS
END
@@ -313,9 +313,11 @@ BEGIN
"R", ID_DEBUG_REGISTERS, VIRTKEY, CONTROL, NOINVERT
VK_F8, ID_EMULATION_PAUSE, VIRTKEY, NOINVERT
VK_F7, ID_EMULATION_RUN, VIRTKEY, NOINVERT
- VK_F4, ID_FILE_LOADSTATE, VIRTKEY, NOINVERT
- VK_F5, ID_FILE_REFRESHGAMELIST, VIRTKEY, NOINVERT
- VK_F2, ID_FILE_SAVESTATE, VIRTKEY, NOINVERT
+ "1", ID_OPTIONS_SCREEN1X, VIRTKEY, CONTROL, NOINVERT
+ "2", ID_OPTIONS_SCREEN2X, VIRTKEY, CONTROL, NOINVERT
+ "3", ID_OPTIONS_SCREEN3X, VIRTKEY, CONTROL, NOINVERT
+ "4", ID_OPTIONS_SCREEN4X, VIRTKEY, CONTROL, NOINVERT
+ VK_F5, ID_OPTIONS_BUFFEREDRENDERING, VIRTKEY, NOINVERT
"W", ID_FILE_UNLOAD, VIRTKEY, CONTROL, NOINVERT
VK_F12, ID_OPTIONS_FULLSCREEN, VIRTKEY, NOINVERT
END
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 158ffa57e2..ca69ab1388 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -142,6 +142,7 @@ LOCAL_SRC_FILES := \
$(SRC)/Core/HLE/sceSas.cpp \
$(SRC)/Core/HLE/sceSsl.cpp \
$(SRC)/Core/HLE/sceUmd.cpp \
+ $(SRC)/Core/HLE/sceUsb.cpp \
$(SRC)/Core/HLE/sceUtility.cpp \
$(SRC)/Core/HLE/sceVaudio.cpp \
$(SRC)/Core/HLE/scesupPreAcc.cpp \