diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index de2e705aa0..380f0ba778 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -46,10 +46,9 @@ const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate); const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate); // High and low watermarks, basically. -const int chanQueueMaxSizeFactor = 4; -const int chanQueueMinSizeFactor = 2; +const int chanQueueMaxSizeFactor = 2; +const int chanQueueMinSizeFactor = 1; -// A whole second, should be enough for anything. FixedSizeQueue outAudioQueue; @@ -131,25 +130,9 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking) // just sleep the main emulator thread a little. void __AudioUpdate() { -#ifdef _WIN32 - // HACK - TODO: Remove - bool noThrottle = GetAsyncKeyState(VK_TAB) != 0; -#else - bool noThrottle = false; -#endif - // Sleep here until the host audio hardware is ready to receive samples. - // This will effectively throttle the frame rate. - - if (!noThrottle && g_Config.bEnableSound) { - while (true) - { - if (outAudioQueue.size() < hwBlockSize * 4) - break; // room can only increase without us pushing, so there's no race condition between here and section.lock() - Common::SleepCurrentThread(0); - } - } - - section.lock(); + // Audio throttle doesn't really work on the PSP since the mixing intervals are so closely tied + // to the CPU. Much better to throttle the frame rate on frame display and just throw away audio + // if the buffer somehow gets full. s32 mixBuffer[hwBlockSize * 2]; memset(mixBuffer, 0, sizeof(mixBuffer)); @@ -193,7 +176,9 @@ void __AudioUpdate() } } - if (!noThrottle && g_Config.bEnableSound) { + section.lock(); + + if (g_Config.bEnableSound && outAudioQueue.room() >= hwBlockSize * 2) { // Push the mixed samples onto the output audio queue. for (int i = 0; i < hwBlockSize; i++) { s32 sampleL = mixBuffer[i * 2] >> 2; // TODO - what factor? @@ -233,7 +218,7 @@ int __AudioMix(short *outstereo, int numFrames) outstereo[i * 2 + 1] = sampleR; anythingToPlay = true; } else { - underrun = i; + if (underrun == -1) underrun = i; outstereo[i * 2] = sampleL; // repeat last sample, can reduce clicking outstereo[i * 2 + 1] = sampleR; // repeat last sample, can reduce clicking } diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 5c1725aa41..97b11cb618 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -307,14 +307,17 @@ void sceAudioOutput2OutputBlocking() chans[0].leftVolume = vol; chans[0].rightVolume = vol; chans[0].sampleAddress = dataPtr; - RETURN(chans[0].sampleCount); - __AudioEnqueue(chans[0], 0, true); + RETURN(0); + u32 retval = __AudioEnqueue(chans[0], 0, true); + if (retval < 0) + RETURN(retval); } -void sceAudioOutput2ChangeLength() +u32 sceAudioOutput2ChangeLength(u32 sampleCount) { - ERROR_LOG(HLE,"UNIMPL sceAudioOutput2ChangeLength"); - RETURN(0); + WARN_LOG(HLE,"sceAudioOutput2ChangeLength(%i)"); + chans[0].sampleCount = sampleCount; + return 0; } u32 sceAudioOutput2GetRestSample() @@ -343,20 +346,22 @@ u32 sceAudioSetFrequency(u32 freq) { const HLEFunction sceAudio[] = { - {0x01562ba3, sceAudioOutput2Reserve, "sceAudioOutput2Reserve"}, // N+, Super Stardust Portable uses these + // Newer simplified single channel audio output. Presumably for games that use Atrac3 + // directly from Sas instead of playing it on a separate audio channel. + {0x01562ba3, sceAudioOutput2Reserve, "sceAudioOutput2Reserve"}, {0x2d53f36e, sceAudioOutput2OutputBlocking, "sceAudioOutput2OutputBlocking"}, - {0x63f2889c, sceAudioOutput2ChangeLength, "sceAudioOutput2ChangeLength"}, + {0x63f2889c, WrapU_U, "sceAudioOutput2ChangeLength"}, {0x647cef33, WrapU_V, "sceAudioOutput2GetRestSample"}, {0x43196845, sceAudioOutput2Release, "sceAudioOutput2Release"}, - {0x38553111, 0, "sceAudioSRCChReserve"}, - {0x5C37C0AE, 0, "sceAudioSRCChRelease"}, - {0x80F1F7E0, sceAudioInit, "sceAudioInit"}, + {0x80F1F7E0, sceAudioInit, "sceAudioInit"}, {0x210567F7, sceAudioEnd, "sceAudioEnd"}, - {0x927AC32B, 0, "sceAudioSetVolumeOffset"}, + {0xA2BEAA6C, WrapU_U, "sceAudioSetFrequency"}, - {0xE0727056, 0, "sceAudioSRCOutputBlocking"}, - {0x8c1009b2, WrapU_UUU, "sceAudioOutput"}, + {0x927AC32B, 0, "sceAudioSetVolumeOffset"}, + + // The oldest and standard audio interface. Supports 8 channels, most games use 1-2. + {0x8c1009b2, WrapU_UUU, "sceAudioOutput"}, {0x136CAF51, WrapV_UUU, "sceAudioOutputBlocking"}, {0xE2D56B2D, WrapU_UUUU, "sceAudioOutputPanned"}, {0x13F592BC, WrapV_UUUU, "sceAudioOutputPannedBlocking"}, //(u32, u32, u32, void *)Output sound, blocking @@ -367,8 +372,17 @@ const HLEFunction sceAudio[] = {0xCB2E439E, WrapU_UU, "sceAudioSetChannelDataLen"}, //(u32, u32) {0x95FD0C2D, WrapU_UU, "sceAudioChangeChannelConfig"}, {0xB7E1D8E7, WrapU_UUU, "sceAudioChangeChannelVolume"}, + + // I guess these are like the others but do sample rate conversion? + {0x38553111, 0, "sceAudioSRCChReserve"}, + {0x5C37C0AE, 0, "sceAudioSRCChRelease"}, + {0xE0727056, 0, "sceAudioSRCOutputBlocking"}, + + // Never seen these used {0x41efade7, 0, "sceAudioOneshotOutput"}, {0xB61595C0, 0, "sceAudioLoopbackTest"}, + + // Microphone interface {0x7de61688, 0, "sceAudioInputInit"}, {0xE926D3FB, 0, "sceAudioInputInitEx"}, {0x6d4bec68, 0, "sceAudioInput"}, diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 59a9c4bcbf..2f31ccd402 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -17,8 +17,12 @@ #include -//#include "base/timeutil.h" +// TODO: Move the relevant parts into common. Don't want the core +// to be dependent on "native", I think. Or maybe should get rid of common +// and move everything into native... +#include "base/timeutil.h" +#include "Thread.h" #include "../Core/CoreTiming.h" #include "../MIPS/MIPS.h" #include "../HLE/HLE.h" @@ -63,6 +67,7 @@ static int hCountTotal = 0; //unused static int vCount = 0; static int isVblank = 0; static bool hasSetMode = false; +double lastFrameTime = 0; // STATE END @@ -165,15 +170,29 @@ void hleEnterVblank(u64 userdata, int cyclesLate) // anything to draw here. gpu->CopyDisplayToOutput(); - { - host->EndFrame(); + host->EndFrame(); - host->BeginFrame(); - gpu->BeginFrame(); - - shaderManager.DirtyShader(); - shaderManager.DirtyUniform(DIRTY_ALL); +#ifdef _WIN32 + static double lastFrameTime = 0.0; + // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. + time_update(); + if (lastFrameTime == 0.0) + lastFrameTime = time_now_d(); + if (!GetAsyncKeyState(VK_TAB)) { + while (time_now_d() < lastFrameTime + 1.0 / 60.0f) { + Common::SleepCurrentThread(1); + time_update(); + } + lastFrameTime = time_now_d(); } +#endif + + + host->BeginFrame(); + gpu->BeginFrame(); + + shaderManager.DirtyShader(); + shaderManager.DirtyUniform(DIRTY_ALL); // Tell the emu core that it's time to stop emulating // Win32 doesn't need this. diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 5ddd25ea71..89c5c3758b 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -47,7 +47,12 @@ u32 sceWlanGetEtherAddr(u32 addrAddr) u32 sceWlanDevIsPowerOn() { - DEBUG_LOG(HLE, "0=sceWlanDevIsPowerOn()"); + DEBUG_LOG(HLE, "UNTESTED 0=sceWlanDevIsPowerOn()"); + return 0; +} + +u32 sceWlanGetSwitchState() { + DEBUG_LOG(HLE, "UNTESTED sceWlanGetSwitchState()"); return 0; } @@ -179,7 +184,7 @@ const HLEFunction sceNetApctl[] = const HLEFunction sceWlanDrv[] = { - {0xd7763699, 0, "sceWlanGetSwitchState"}, + {0xd7763699, WrapU_V, "sceWlanGetSwitchState"}, {0x0c622081, WrapU_U, "sceWlanGetEtherAddr"}, {0x93440B11, WrapU_V, "sceWlanDevIsPowerOn"}, };