From fdd2879443ac91a534833ad4b14076417126ffe7 Mon Sep 17 00:00:00 2001 From: TMaul Date: Mon, 17 Dec 2012 21:21:09 +0000 Subject: [PATCH 001/276] Another font function Used by assassins creed. --- Core/HLE/sceFont.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index dc1e6ffa82..adbf1145a9 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -318,6 +318,22 @@ int sceFontGetCharGlyphImage_Clip(u32 libHandler, u32 charCode, u32 glyphImagePt return 0; } + int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, u32 numFonts) + { + ERROR_LOG(HLE, "sceFontGetFontList %x, %x, %x", fontLibHandle, fontStylePtr, numFonts); + + FontStyle style; + memset(&style, 0, sizeof (style)); + + style.fontH = 20 / 64.f; + style.fontV = 20 / 64.f; + style.fontHRes = 20 / 64.f; + style.fontVRes = 20 / 64.f; + style.fontStyle = 1; + + Memory::WriteStruct(fontStylePtr, &style); + return 0; + } const HLEFunction sceLibFont[] = { @@ -325,7 +341,7 @@ const HLEFunction sceLibFont[] = {0x574b6fbc, WrapI_U, "sceFontDoneLib"}, {0x48293280, 0, "sceFontSetResolution"}, {0x27f6e642, WrapI_UU, "sceFontGetNumFontList"}, - {0xbc75d85b, 0, "sceFontGetFontList"}, + {0xbc75d85b, WrapI_UUU, "sceFontGetFontList"}, {0x099ef33c, WrapI_UUU, "sceFontFindOptimumFont"}, {0x681e61a7, WrapI_UUU, "sceFontFindFont"}, {0x2f67356a, 0, "sceFontCalcMemorySize"}, From 9a83dee9b5e7eef29310f4e6e707a34438c103d4 Mon Sep 17 00:00:00 2001 From: TMaul Date: Mon, 17 Dec 2012 23:57:40 +0000 Subject: [PATCH 002/276] With not insane tabs this time.. --- Core/HLE/sceFont.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index adbf1145a9..664a6699d5 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -318,12 +318,12 @@ int sceFontGetCharGlyphImage_Clip(u32 libHandler, u32 charCode, u32 glyphImagePt return 0; } - int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, u32 numFonts) - { - ERROR_LOG(HLE, "sceFontGetFontList %x, %x, %x", fontLibHandle, fontStylePtr, numFonts); - - FontStyle style; - memset(&style, 0, sizeof (style)); +int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, u32 numFonts) +{ + ERROR_LOG(HLE, "sceFontGetFontList %x, %x, %x", fontLibHandle, fontStylePtr, numFonts); + + FontStyle style; + memset(&style, 0, sizeof (style)); style.fontH = 20 / 64.f; style.fontV = 20 / 64.f; @@ -331,9 +331,9 @@ int sceFontGetCharGlyphImage_Clip(u32 libHandler, u32 charCode, u32 glyphImagePt style.fontVRes = 20 / 64.f; style.fontStyle = 1; - Memory::WriteStruct(fontStylePtr, &style); - return 0; - } + Memory::WriteStruct(fontStylePtr, &style); + return 0; +} const HLEFunction sceLibFont[] = { From b6ebe427ac36e4b2ca08b2f98e2781e02ea1eaa9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 09:26:08 +0100 Subject: [PATCH 003/276] Use the right reschedule function.. --- Core/HLE/sceDisplay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index df34fda23c..e10622fbba 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -364,12 +364,12 @@ u32 sceDisplayGetVcount() // Too spammy // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); - // Puyo Puyo Fever polls this as a substitute for waiting vblank. + // Puyo Puyo Fever polls this as a substitute for waiting for 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); - __KernelReSchedule(); // Puyo puyo hack? + hleReSchedule("sceDisplayGetVcount hack"); // Puyo puyo hack? return vCount; } From 2b8419e0fff838cd61da86b6ab5777ef8a5a565e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 10:25:57 +0100 Subject: [PATCH 004/276] Attempt more accurate frame timing (windows). Increase audio volume. --- Core/HLE/sceDisplay.cpp | 10 ++++++++-- Core/HW/SasAudio.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index e10622fbba..29b3dac45c 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -214,12 +214,18 @@ void hleEnterVblank(u64 userdata, int cyclesLate) if (lastFrameTime == 0.0) lastFrameTime = time_now_d(); if (!GetAsyncKeyState(VK_TAB)) { - while (time_now_d() < lastFrameTime + 1.0 / 60.0f) { + while (time_now_d() < lastFrameTime + 1.0 / 60.0) { Common::SleepCurrentThread(1); time_update(); } - lastFrameTime = time_now_d(); + // Advance lastFrameTime by a constant amount each frame, + // but don't let it get too far behind. + lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); } + + // We are going to have to do something about audio timing for platforms that + // are vsynced to something that's not exactly 60fps.. + #endif host->BeginFrame(); diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index c9413b3308..b4ad23d2ef 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -250,10 +250,10 @@ void SasInstance::Mix(u32 outAddr) { // We mix into this 32-bit temp buffer and clip in a second loop // Ideally, the shift right should be there too but for now I'm concerned about // not overflowing. - mixBuffer[i * 2] += sample * voice.volumeLeft >> 15; - mixBuffer[i * 2 + 1] += sample * voice.volumeRight >> 15; - sendBuffer[i * 2] += sample * voice.volumeLeftSend >> 15; - sendBuffer[i * 2 + 1] += sample * voice.volumeRightSend >> 15; + mixBuffer[i * 2] += sample * voice.volumeLeft >> 12; + mixBuffer[i * 2 + 1] += sample * voice.volumeRight >> 12; + sendBuffer[i * 2] += sample * voice.volumeLeftSend >> 12; + sendBuffer[i * 2 + 1] += sample * voice.volumeRightSend >> 12; voice.envelope.Step(); } voice.samplePos += voice.pitch * grainSize; From 4ef062738708dcad150f3c6691e005fb730e864d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 10:38:25 +0100 Subject: [PATCH 005/276] Revert puyo puyo hack, breaks things (not very surprisingly)... There has to be some function that should reschedule that doesn't, though... --- Core/HLE/sceDisplay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 29b3dac45c..69700b67da 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -372,10 +372,10 @@ u32 sceDisplayGetVcount() // Puyo Puyo Fever polls this as a substitute for waiting for 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... + // Need to find a better hack as this breaks games like Project Diva. + // hleReSchedule("sceDisplayGetVcount hack"); // Puyo puyo hack? CoreTiming::Idle(1000000); - hleReSchedule("sceDisplayGetVcount hack"); // Puyo puyo hack? return vCount; } From 35a38ac6b9643d3f2416704ce878ee60088ffc42 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 18 Dec 2012 00:58:46 -0800 Subject: [PATCH 006/276] Ensure interrupts don't run on real threads. If a thread waits on a sema, and an interrupt (such as an alarm) happens, and the interrupt signals or deletes the sema, it needs to return the value correctly. For callbacks, it's injected, since they run on thread. But interrupts aren't supposed to run on thread anyway, so this switches to idle. --- Core/HLE/sceKernelInterrupt.cpp | 4 ++++ Core/HLE/sceKernelThread.cpp | 24 ++++++++++++++++++++++++ Core/HLE/sceKernelThread.h | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index bf298e4d40..7d38ff6802 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -278,6 +278,10 @@ bool __RunOnePendingInterrupt() // Can easily prioritize between different kinds of interrupts if necessary. if (pendingInterrupts.size()) { + // If we came from CoreTiming::Advance(), we might've come from a waiting thread's callback. + // To avoid "injecting" return values into our saved state, we context switch here. + __KernelSwitchOffThread("interrupt"); + PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intState.save(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index b6ad2c7a00..a35a984362 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -395,6 +395,30 @@ void __KernelStartIdleThreads() } } +bool __KernelSwitchOffThread(const char *reason) +{ + if (!reason) + reason = "switch off thread"; + + SceUID threadID = currentThread->GetUID(); + + if (threadID != threadIdleID[0] && threadID != threadIdleID[1]) + { + u32 error; + // Idle 0 chosen entirely arbitrarily. + Thread *t = kernelObjects.Get(threadIdleID[0], error); + if (t) + { + __KernelSwitchContext(t, reason); + return true; + } + else + ERROR_LOG(HLE, "Unable to switch to idle thread."); + } + + return false; +} + void __KernelIdle() { CoreTiming::Idle(); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index eb99e239e4..913511fe65 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -175,6 +175,10 @@ void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(bool reschedAfter); void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg); +// Switch to an idle / non-user thread, if not already on one. +// Returns whether a switch occurred. +bool __KernelSwitchOffThread(const char *reason); + // A call into game code. These can be pending on a thread. // Similar to Callback-s (NOT CallbackInfos) in JPCSP. class Action; From dba622338aa1d33de9a714d9288fde7a57d35244 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 11:40:14 +0100 Subject: [PATCH 007/276] Audio smoothness improvements --- Common/FixedSizeQueue.h | 4 ++++ Core/HLE/__sceAudio.cpp | 41 +++++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Common/FixedSizeQueue.h b/Common/FixedSizeQueue.h index fbfd94c415..55bf3015ae 100644 --- a/Common/FixedSizeQueue.h +++ b/Common/FixedSizeQueue.h @@ -87,6 +87,10 @@ public: return count_; } + size_t capacity() const { + return N; + } + int room() const { return N - count_; } diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index bf22116aeb..db1cc7332a 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -28,20 +28,15 @@ #include "FixedSizeQueue.h" #include "Common/Thread.h" -// While buffers == MAX_BUFFERS, block on blocking write -// non-blocking writes will return busy, I guess - -#define MAX_BUFFERS 2 -#define MIN_BUFFERS 1 - std::recursive_mutex section; int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; int mixFrequency = 44100; + const int hwSampleRate = 44100; -const int hwBlockSize = 480; -const int hostAttemptBlockSize = 64; +const int hwBlockSize = 60; +const int hostAttemptBlockSize = 256; const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate); const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate); @@ -49,20 +44,20 @@ const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSamp const int chanQueueMaxSizeFactor = 4; const int chanQueueMinSizeFactor = 1; -FixedSizeQueue outAudioQueue; +FixedSizeQueue outAudioQueue; void hleAudioUpdate(u64 userdata, int cyclesLate) { __AudioUpdate(); - CoreTiming::ScheduleEvent(usToCycles(audioIntervalUs), eventAudioUpdate, 0); + CoreTiming::ScheduleEvent(usToCycles(audioIntervalUs) - cyclesLate, eventAudioUpdate, 0); } void hleHostAudioUpdate(u64 userdata, int cyclesLate) { host->UpdateSound(); - CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs), eventHostAudioUpdate, 0); + CoreTiming::ScheduleEvent(usToCycles(audioHostIntervalUs) - cyclesLate, eventHostAudioUpdate, 0); } void __AudioInit() @@ -142,7 +137,7 @@ void __AudioUpdate() if (!chans[i].reserved) continue; if (!chans[i].sampleQueue.size()) { - // DEBUG_LOG(HLE, "No queued samples, skipping channel %i", i); + // ERROR_LOG(HLE, "No queued samples, skipping channel %i", i); continue; } @@ -178,14 +173,20 @@ void __AudioUpdate() 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? - s32 sampleR = mixBuffer[i * 2 + 1] >> 2; + if (g_Config.bEnableSound) { + if (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? + s32 sampleR = mixBuffer[i * 2 + 1] >> 2; - outAudioQueue.push((s16)sampleL); - outAudioQueue.push((s16)sampleR); + outAudioQueue.push((s16)sampleL); + outAudioQueue.push((s16)sampleR); + } + } else { + // This happens quite a lot. There's still something slightly off + // about the amount of audio we produce. + DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), outAudioQueue.capacity()); } } @@ -225,7 +226,7 @@ int __AudioMix(short *outstereo, int numFrames) } } if (anythingToPlay && underrun >= 0) { - ERROR_LOG(HLE, "audio out buffer UNDERRUN at %i of %i", underrun, numFrames); + DEBUG_LOG(HLE, "audio out buffer UNDERRUN at %i of %i", underrun, numFrames); } else { // DEBUG_LOG(HLE, "No underrun, mixed %i samples fine", numFrames); } From 478c5074e4a9d7ead19b22d2b0ca7f85e352b8e0 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 18 Dec 2012 19:56:35 +0800 Subject: [PATCH 008/276] Quick viewport fix for fullscreen mode --- Windows/WndMainWindow.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index a80e17345c..5155aa162e 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -469,10 +469,16 @@ namespace MainWindow UpdateMenus(); break; case ID_OPTIONS_FULLSCREEN: - if(g_bFullScreen) + if(g_bFullScreen) { _ViewNormal(hWnd); - else + SetZoom(1); //restore window to original size + } + else { + int cx = ::GetSystemMetrics(SM_CXSCREEN); + float screenfactor = cx / 480.0f; + SetZoom(screenfactor); _ViewFullScreen(hWnd); + } break; case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: From 0448c62146701dcea0fcabcc3adbc94bccffe2ab Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 11:56:58 +0100 Subject: [PATCH 009/276] Properly size debug text when zoomed --- Core/HLE/sceDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 69700b67da..39c673b5c8 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -196,7 +196,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) gpuStats.numShaders ); - float zoom = 0.7f * sqrtf(g_Config.iWindowZoom); + float zoom = 0.7f / g_Config.iWindowZoom; PPGeBegin(); PPGeDrawText(stats, 2, 2, 0, zoom, 0x90000000); PPGeDrawText(stats, 0, 0, 0, zoom); From 90e87ead848281c99f5703f450d3d1bb93b1fc71 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 14:12:57 +0100 Subject: [PATCH 010/276] Fix a relative path issue - apparently paths starting with '/' are still relative. --- Core/FileSystems/MetaFileSystem.cpp | 8 +++++++- Core/HLE/sceKernelThread.cpp | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 9d69f1d138..772b056bbf 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -122,7 +122,13 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st if (inAfter.substr(0, 11) == "./PSP_GAME/") inAfter = inAfter.substr(1); - if ((inAfter[0] != '/')) + // Apparently it's okay for relative paths to start with '/'. + // For example, kahoots does sceIoChdir(disc0:/PSP_GAME/USRDIR/) + // then opens paths like "/images/gui". Support this. + if (inColon == std::string::npos && inAfter[0] == '/') + inAfter = inAfter.substr(1); + + if (inAfter[0] != '/') { if (curDirLen == 0) { diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index a35a984362..99fae0257e 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2038,7 +2038,7 @@ void sceKernelCheckCallback() bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) { - ERROR_LOG(HLE,"sceKernelCheckCallback() - processed a callback."); + DEBUG_LOG(HLE,"sceKernelCheckCallback() - processed a callback."); } else { RETURN(0); } From 07048131d00ba350ce3c1b1c5870b550ddc35ae6 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Tue, 18 Dec 2012 22:27:59 +0100 Subject: [PATCH 011/276] Correct mistake --- Core/Dialog/SavedataParam.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 189b04f11b..1fa24aa874 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -435,7 +435,7 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) } else // Load info on only save { - saveNameListData == 0; + saveNameListData = 0; Clear(); saveDataList = new SaveFileInfo[1]; From 0b187bb8b6e5a6c35711f1df4b41588e9c2d4902 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Dec 2012 22:54:08 +0100 Subject: [PATCH 012/276] Implement vhdp --- Core/MIPS/MIPSIntVFPU.cpp | 25 +++++++++++++++++++++++++ Core/MIPS/MIPSIntVFPU.h | 1 + Core/MIPS/MIPSTables.cpp | 9 +++------ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index b3045b9a4b..18d6f12b0b 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -851,6 +851,31 @@ namespace MIPSInt EatPrefixes(); } + void Int_VHdp(u32 op) + { + float s[4], t[4]; + float d; + int vd = _VD; + int vs = _VS; + int vt = _VT; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + ReadVector(t, sz, vt); + ApplySwizzleT(t, sz); + float sum = 0.0f; + int n = GetNumVectorElements(sz); + for (int i = 0; i < n; i++) + { + sum += (i == n - 1) ? t[i] : s[i]*t[i]; + } + d = sum; + ApplyPrefixD(&d,V_Single); + V(vd) = d; + PC += 4; + EatPrefixes(); + } + void Int_Vbfy(u32 op) { float s[4]; diff --git a/Core/MIPS/MIPSIntVFPU.h b/Core/MIPS/MIPSIntVFPU.h index 50e7229366..57e7eb8c2d 100644 --- a/Core/MIPS/MIPSIntVFPU.h +++ b/Core/MIPS/MIPSIntVFPU.h @@ -39,6 +39,7 @@ namespace MIPSInt void Int_VV2Op(u32 op); void Int_Vrot(u32 op); void Int_VDot(u32 op); + void Int_VHdp(u32 op); void Int_Vavg(u32 op); void Int_Vfad(u32 op); void Int_Vocp(u32 op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 67d9b70e92..b433e3108b 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -492,8 +492,8 @@ MIPSInstruction tableVFPU1[8] = INSTR("vmul",&Jit::Comp_Generic, Dis_VectorSet3, Int_VecDo3, IS_VFPU), INSTR("vdot",&Jit::Comp_Generic, Dis_VectorDot, Int_VDot, IS_VFPU), INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU), - INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), - {-2}, + {-2}, + INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU), INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU), INSTR("vdet",&Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), {-2}, @@ -848,13 +848,10 @@ const MIPSInstruction *MIPSGetInstruction(u32 op) instr = &table[subop]; if (encoding == Rese) return 0; //invalid instruction -// if (encoding == Spe3) -// __asm int 3 if (!instr) return 0; if (instr->altEncoding == -2) { - //BAD!! //ERROR_LOG(CPU, "Invalid instruction %08x in table %i, entry %i", op, (int)encoding, subop); return 0; //invalid instruction } @@ -924,7 +921,7 @@ void MIPSInterpret(u32 op) //only for those rare ones instr->interpret(op); else { - ERROR_LOG(CPU,"Unknown instruction %08x", op); + ERROR_LOG(CPU,"Unknown instruction %08x at %08x", op, currentMIPS->pc); // Try to disassemble it char disasm[256]; MIPSDisAsm(op, currentMIPS->pc, disasm); From 0ccce3c1a89d0b7689e5c8b88508130ad1cc6b32 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Wed, 19 Dec 2012 01:05:45 +0100 Subject: [PATCH 013/276] * Don't restart dialog if already running. This correct bug with MotoGP, even if the game make weird stuff with the dialog call... * Add log for data install and install request. --- Core/Dialog/PSPMsgDialog.cpp | 6 ++++++ Core/Dialog/PSPOskDialog.cpp | 5 +++++ Core/Dialog/PSPSaveDialog.cpp | 5 +++++ Core/HLE/sceUtility.cpp | 14 ++++++++++++-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 899f874ec1..1ca3fe7d94 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -31,6 +31,12 @@ PSPMsgDialog::~PSPMsgDialog() { void PSPMsgDialog::Init(unsigned int paramAddr) { + // Ignore if already running + if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) + { + return; + } + messageDialogAddr = paramAddr; if (!Memory::IsValidAddress(messageDialogAddr)) { diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 6646e4e7a2..66981f7910 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -172,6 +172,11 @@ void PSPOskDialog::HackyGetStringWide(std::string& _string, const u32 em_address int PSPOskDialog::Init(u32 oskPtr) { + // Ignore if already running + if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) + { + return -1; + } status = SCE_UTILITY_STATUS_INITIALIZE; memset(&oskParams, 0, sizeof(oskParams)); diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 421ebd12b4..f94940c40d 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -33,6 +33,11 @@ PSPSaveDialog::~PSPSaveDialog() { void PSPSaveDialog::Init(int paramAddr) { + // Ignore if already running + if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) + { + return; + } param.SetPspParam((SceUtilitySavedataParam*)Memory::GetPointer(paramAddr)); DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index a2530c7f04..f87baa8dae 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -179,6 +179,11 @@ int sceUtilityScreenshotGetStatus() return retval; } +void sceUtilityGamedataInstallInitStart(u32 unkown) +{ + DEBUG_LOG(HLE,"FAKE sceUtilityGamedataInstallInitStart(%i)", unkown); +} + int sceUtilityGamedataInstallGetStatus() { u32 retval = 0;//__UtilityGetStatus(); @@ -332,6 +337,11 @@ u32 sceUtilityUnloadNetModule(u32 module) return 0; } +void sceUtilityInstallInitStart(u32 unknown) +{ + DEBUG_LOG(HLE,"FAKE sceUtilityInstallInitStart()"); +} + const HLEFunction sceUtility[] = { {0x1579a159, &WrapU_U, "sceUtilityLoadNetModule"}, @@ -398,7 +408,7 @@ const HLEFunction sceUtility[] = {0x0D5BC6D2, 0, "sceUtilityLoadUsbModule"}, {0xF64910F0, 0, "sceUtilityUnloadUsbModule"}, - {0x24AC31EB, 0, "sceUtilityGamedataInstallInitStart"}, + {0x24AC31EB, &WrapV_U, "sceUtilityGamedataInstallInitStart"}, {0x32E32DCB, 0, "sceUtilityGamedataInstallShutdownStart"}, {0x4AECD179, 0, "sceUtilityGamedataInstallUpdate"}, {0xB57E95D9, &WrapI_V, "sceUtilityGamedataInstallGetStatus"}, @@ -409,7 +419,7 @@ const HLEFunction sceUtility[] = {0xF3FBC572, 0, "sceUtilityNpSigninUpdate"}, {0x86ABDB1B, 0, "sceUtilityNpSigninGetStatus"}, - {0x1281DA8E, 0, "sceUtilityInstallInitStart"}, + {0x1281DA8E, &WrapV_U, "sceUtilityInstallInitStart"}, {0x5EF1C24A, 0, "sceUtilityInstallShutdownStart"}, {0xA03D29BA, 0, "sceUtilityInstallUpdate"}, {0xC4700FA3, 0, "sceUtilityInstallGetStatus"}, From 392f6604f36aceb62ac648bf7a1e53b089a7ff96 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 17 Dec 2012 05:06:20 +1000 Subject: [PATCH 014/276] Updated Qt .pro's for latest files --- Qt/Core.pro | 4 ++++ Qt/Native.pro | 4 ++-- Qt/PPSSPP.pro | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Qt/Core.pro b/Qt/Core.pro index 2b351629f3..d5c1c384e9 100755 --- a/Qt/Core.pro +++ b/Qt/Core.pro @@ -80,9 +80,11 @@ SOURCES += ../Core/MIPS/ARM/Asm.cpp \ #CoreARM ../Core/HLE/sceSsl.cpp \ ../Core/HLE/scesupPreAcc.cpp \ ../Core/HLE/sceUmd.cpp \ + ../Core/HLE/sceUsb.cpp \ ../Core/HLE/sceUtility.cpp \ ../Core/HLE/sceVaudio.cpp \ ../Core/HW/MemoryStick.cpp \ + ../Core/HW/SasAudio.cpp \ ../Core/Host.cpp \ ../Core/Loaders.cpp \ ../Core/MIPS/JitCommon/JitCommon.cpp \ @@ -186,9 +188,11 @@ HEADERS += ../Core/MIPS/ARM/Asm.h \ ../Core/HLE/sceSsl.h \ ../Core/HLE/scesupPreAcc.h \ ../Core/HLE/sceUmd.h \ + ../Core/HLE/sceUsb.h \ ../Core/HLE/sceUtility.h \ ../Core/HLE/sceVaudio.h \ ../Core/HW/MemoryStick.h \ + ../Core/HW/SasAudio.h \ ../Core/Host.h \ ../Core/Loaders.h \ ../Core/MIPS/JitCommon/JitCommon.h \ diff --git a/Qt/Native.pro b/Qt/Native.pro index e0d9242e29..1ad7bf8d4e 100755 --- a/Qt/Native.pro +++ b/Qt/Native.pro @@ -189,6 +189,6 @@ QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-mult DEFINES += ARM USING_GLES2 blackberry: DEFINES += BLACKBERRY BLACKBERRY10 symbian: { - QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment - DEFINES += SYMBIAN + QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment + DEFINES += SYMBIAN } diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index a795dabd99..b958d46f76 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -42,7 +42,7 @@ symbian: { assets.sources = ../android/assets/ui_atlas.zim ../android/assets/ppge_atlas.zim assets.path = E:/PPSSPP DEPLOYMENT += my_deployment assets - ICON = ../assets/icon.svg + ICON = ../assets/icon.svg # 268MB maximum TARGET.EPOCHEAPSIZE = 0x40000 0x10000000 TARGET.EPOCSTACKSIZE = 0x10000 From a0b809023c03c5989930fa6821bfbd1a0371a0fe Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 17 Dec 2012 05:26:18 +1000 Subject: [PATCH 015/276] Don't check if unsigned is less than 0. Fix tabbing. --- Core/HLE/sceRtc.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 8d1f3256c7..38447046fa 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -299,7 +299,7 @@ u32 sceRtcGetDayOfWeek(u32 year, u32 month, u32 day) return 0; } year -= month < 3; - return ( year + year/4 - year/100 + year/400 + t[month-1] + day) % 7; + return (year + year/4 - year/100 + year/400 + t[month-1] + day) % 7; } u32 sceRtcGetDaysInMonth(u32 year, u32 month) @@ -307,7 +307,7 @@ u32 sceRtcGetDaysInMonth(u32 year, u32 month) DEBUG_LOG(HLE, "sceRtcGetDaysInMonth(%d, %d)", year, month); u32 numberOfDays; - if (year <= 0 || month <= 0 || month > 12) + if (year == 0 || month == 0 || month > 12) return SCE_KERNEL_ERROR_INVALID_ARGUMENT; switch (month) @@ -381,36 +381,32 @@ int sceRtcCheckValid(u32 datePtr) ScePspDateTime pt; Memory::ReadStruct(datePtr, &pt); if (pt.year < 1 || pt.year > 9999) - { - ret = PSP_TIME_INVALID_YEAR; - } + { + ret = PSP_TIME_INVALID_YEAR; + } else if (pt.month < 1 || pt.month > 12) { - ret = PSP_TIME_INVALID_MONTH; + ret = PSP_TIME_INVALID_MONTH; } - else if (pt.day < 1 || pt.day > 31) + else if (pt.day < 1 || pt.day > 31) // TODO: Needs to check actual days in month, including leaps { - ret = PSP_TIME_INVALID_DAY; - } - else if (pt.day < 0 || pt.day > 31) // TODO: Needs to check actual days in month, including leaps - { - ret = PSP_TIME_INVALID_DAY; + ret = PSP_TIME_INVALID_DAY; } - else if (pt.hour < 0 || pt.hour > 23) + else if (pt.hour > 23) { - ret = PSP_TIME_INVALID_HOUR; + ret = PSP_TIME_INVALID_HOUR; } - else if (pt.minute < 0 || pt.minute > 59) + else if (pt.minute > 59) { - ret = PSP_TIME_INVALID_MINUTES; + ret = PSP_TIME_INVALID_MINUTES; } - else if (pt.second < 0 || pt.second > 59) + else if (pt.second > 59) { - ret = PSP_TIME_INVALID_SECONDS; + ret = PSP_TIME_INVALID_SECONDS; } - else if (pt.microsecond < 0 || pt.microsecond >= 1000000) + else if (pt.microsecond >= 1000000) { - ret = PSP_TIME_INVALID_MICROSECONDS; + ret = PSP_TIME_INVALID_MICROSECONDS; } } else From d640bdd032f75a9d22a226f81756f85d666b6811 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 11:11:27 +0100 Subject: [PATCH 016/276] Fix memory stick status check - now saving works in Lumines --- Core/HLE/sceIo.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 17817b760b..d25d07983d 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -494,9 +494,16 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, } break; - case 0x02025806: // Memory stick inserted? case 0x02025801: // Memstick Driver status? - if (Memory::IsValidAddress(outPtr)) { + if (Memory::IsValidAddress(outPtr) && outLen >= 4) { + Memory::Write_U32(4, outPtr); // JPSCP: The right return value is 4 for some reason + return 0; + } else { + return ERROR_MEMSTICK_DEVCTL_BAD_PARAMS; + } + + case 0x02025806: // Memory stick inserted? + if (Memory::IsValidAddress(outPtr) && outLen >= 4) { Memory::Write_U32(1, outPtr); return 0; } else { From 4541c3e18b56dcc4fb417c1f53d730e8394686d5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 11:11:56 +0100 Subject: [PATCH 017/276] Slightly better logging in path mapping --- Core/FileSystems/MetaFileSystem.cpp | 21 +++++++++++---------- Core/FileSystems/MetaFileSystem.h | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 772b056bbf..6dae780398 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -18,7 +18,7 @@ #include #include "MetaFileSystem.h" -bool applyPathStringToComponentsVector(std::vector &vector, const std::string &pathString) +static bool ApplyPathStringToComponentsVector(std::vector &vector, const std::string &pathString) { size_t len = pathString.length(); size_t start = 0; @@ -63,7 +63,7 @@ bool applyPathStringToComponentsVector(std::vector &vector, const s * Changes relative paths to absolute, removes ".", "..", and trailing "/" * babel (and possibly other games) use "/directoryThatDoesNotExist/../directoryThatExists/filename" */ -bool RealPath(const std::string ¤tDirectory, const std::string &inPath, std::string &outPath) +static bool RealPath(const std::string ¤tDirectory, const std::string &inPath, std::string &outPath) { size_t inLen = inPath.length(); if (inLen == 0) @@ -152,7 +152,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st else { const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); - if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) + if (! ApplyPathStringToComponentsVector(cmpnts, curDirAfter) ) { ERROR_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); return false; @@ -162,7 +162,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st capacityGuess += currentDirectory.length(); } - if (! applyPathStringToComponentsVector(cmpnts, inAfter) ) + if (! ApplyPathStringToComponentsVector(cmpnts, inAfter) ) { DEBUG_LOG(HLE, "RealPath: inPath is not a valid path: \"%s\"", inPath.c_str()); return false; @@ -194,30 +194,31 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) return 0; } -bool MetaFileSystem::MapFilePath(std::string inpath, std::string &outpath, IFileSystem **system) +bool MetaFileSystem::MapFilePath(const std::string &inpath, std::string &outpath, IFileSystem **system) { //TODO: implement current directory per thread (NOT per drive) //DEBUG_LOG(HLE, "MapFilePath: starting with \"%s\"", inpath.c_str()); - if ( RealPath(currentDirectory, inpath, inpath) ) + std::string realpath; + if ( RealPath(currentDirectory, inpath, realpath) ) { for (size_t i = 0; i < fileSystems.size(); i++) { size_t prefLen = fileSystems[i].prefix.size(); - if (fileSystems[i].prefix == inpath.substr(0, prefLen)) + if (fileSystems[i].prefix == realpath.substr(0, prefLen)) { - outpath = inpath.substr(prefLen); + outpath = realpath.substr(prefLen); *system = fileSystems[i].system; - DEBUG_LOG(HLE, "MapFilePath: mapped to prefix: \"%s\", path: \"%s\"", fileSystems[i].prefix.c_str(), outpath.c_str()); + DEBUG_LOG(HLE, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath.c_str()); return true; } } } - DEBUG_LOG(HLE, "MapFilePath: failed, returning false"); + DEBUG_LOG(HLE, "MapFilePath: failed mapping \"%s\", returning false", inpath.c_str()); return false; } diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index dee552e098..b0b63d9b97 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -37,7 +37,7 @@ public: void FreeHandle(u32 handle) {} IFileSystem *GetHandleOwner(u32 handle); - bool MapFilePath(std::string inpath, std::string &outpath, IFileSystem **system); + bool MapFilePath(const std::string &inpath, std::string &outpath, IFileSystem **system); std::vector GetDirListing(std::string path); u32 OpenFile(std::string filename, FileAccess access); From 404614616446b56e7acecca4aaabd833964cc7ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 15:14:41 +0100 Subject: [PATCH 018/276] Add experimental wireframe mode for debugging. Fix texenv color. Code cleanup. --- Core/Config.cpp | 4 ++ Core/Config.h | 1 + GPU/GLES/DisplayListInterpreter.cpp | 32 ++++++++++++++ GPU/GLES/DisplayListInterpreter.h | 6 +++ GPU/GLES/FragmentShaderGenerator.cpp | 2 +- GPU/GLES/ShaderManager.cpp | 16 +++++-- GPU/GLES/TransformPipeline.cpp | 64 +++++++++++++++++----------- Windows/WndMainWindow.cpp | 5 +++ Windows/ppsspp.rc | 1 + Windows/resource.h | 3 +- 10 files changed, 104 insertions(+), 30 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index eb09dece92..befe00334f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -64,6 +64,10 @@ void CConfig::Load(const char *iniFileName) IniFile::Section *control = iniFile.GetOrCreateSection("Control"); control->Get("ShowStick", &bShowAnalogStick, false); control->Get("ShowTouchControls", &bShowTouchControls, true); + + + // Ephemeral settings + bDrawWireframe = false; } void CConfig::Save() diff --git a/Core/Config.h b/Core/Config.h index d873fcb725..461859e4aa 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -43,6 +43,7 @@ public: bool bIgnoreBadMemAccess; bool bDisplayFramebuffer; bool bBufferedRendering; + bool bDrawWireframe; bool bShowTouchControls; bool bShowDebuggerOnLoad; diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 90931d75bc..1662d17c06 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -116,6 +116,8 @@ void GLES_GPU::CopyDisplayToOutput() if (!g_Config.bBufferedRendering) return; + EndDebugDraw(); + VirtualFramebuffer *vfb = GetDisplayFBO(); fbo_unbind(); @@ -145,6 +147,8 @@ void GLES_GPU::CopyDisplayToOutput() shaderManager.DirtyShader(); shaderManager.DirtyUniform(DIRTY_ALL); gstate_c.textureChanged = true; + + BeginDebugDraw(); } GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() @@ -221,6 +225,20 @@ void GLES_GPU::SetRenderFrameBuffer() } } +void GLES_GPU::BeginDebugDraw() +{ + if (g_Config.bDrawWireframe) { +#ifndef USING_GLES2 + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif + // glClear(GL_COLOR_BUFFER_BIT); + } +} +void GLES_GPU::EndDebugDraw() { +#ifndef USING_GLES2 + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif +} // Render queue @@ -698,6 +716,20 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } break; + case GE_CMD_TEXMAPMODE: + DEBUG_LOG(G3D,"Tex map mode: %06x", data); + break; + + case GE_CMD_TEXSHADELS: + DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); + break; + + case GE_CMD_CLUTFORMAT: + { + DEBUG_LOG(G3D,"DL Clut format: %06x", data); + } + break; + case GE_CMD_TRANSFERSRC: { // Nothing to do, the next one prints diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index a105ca7818..8fe6ae971a 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -51,11 +51,17 @@ public: private: // TransformPipeline.cpp void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); + void ApplyDrawState(); + void Flush(); void UpdateViewportAndProjection(); void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); bool ProcessDLQueue(); + // Applies states for debugging if enabled. + void BeginDebugDraw(); + void EndDebugDraw(); + FramebufferManager framebufferManager; ShaderManager *shaderManager_; diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index e42e96e2b6..0b4003c3a2 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -85,7 +85,7 @@ char *GenerateFragmentShader() WRITE(p, "uniform vec3 u_fogcolor;\n"); WRITE(p, "uniform vec2 u_fogcoef;\n"); } - WRITE(p, "uniform vec4 u_texenv;\n"); + WRITE(p, "uniform vec3 u_texenv;\n"); WRITE(p, "varying vec4 v_color0;\n"); if (lmode) WRITE(p, "varying vec4 v_color1;\n"); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 857968560b..78303948c8 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -97,9 +97,20 @@ LinkedShader::~LinkedShader() { glDeleteProgram(program); } +// Utility +static void SetColorUniform3(int uniform, u32 color) +{ + const float col[3] = { ((color & 0xFF0000) >> 16) / 255.0f, ((color & 0xFF00) >> 8) / 255.0f, ((color & 0xFF)) / 255.0f}; + glUniform3fv(uniform, 1, col); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); + + if (!dirtyUniforms) + return; + // Update any dirty uniforms before we draw if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) { glUniformMatrix4fv(u_proj, 1, GL_FALSE, gstate.projMatrix); @@ -122,14 +133,13 @@ void LinkedShader::use() { glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr()); } if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) { - glUniform4f(u_texenv, 1.0, 1.0, 1.0, 1.0); // TODO + SetColorUniform3(u_texenv, gstate.texenvcolor); } if (u_alpharef != -1 && (dirtyUniforms & DIRTY_ALPHAREF)) { glUniform4f(u_alpharef, ((float)((gstate.alphatest >> 8) & 0xFF)) / 255.0f, 0.0f, 0.0f, 0.0f); } if (u_fogcolor != -1 && (dirtyUniforms & DIRTY_FOGCOLOR)) { - const float fogc[3] = { ((gstate.fogcolor & 0xFF0000) >> 16) / 255.0f, ((gstate.fogcolor & 0xFF00) >> 8) / 255.0f, ((gstate.fogcolor & 0xFF)) / 255.0f}; - glUniform3fv(u_fogcolor, 1, fogc); + SetColorUniform3(u_fogcolor, gstate.fogcolor); } if (u_fogcoef != -1 && (dirtyUniforms & DIRTY_FOGCOEF)) { const float fogcoef[2] = { getFloat24(gstate.fog1), getFloat24(gstate.fog2) }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 58ce633357..b5569bfea4 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -226,6 +226,16 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte *bytesRead = vertexCount * dec.VertexSize(); bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; + + /* + DEBUG_LOG(G3D, "View matrix:"); + const float *m = &gstate.viewMatrix[0]; + DEBUG_LOG(G3D, "%f %f %f", m[0], m[1], m[2]); + DEBUG_LOG(G3D, "%f %f %f", m[3], m[4], m[5]); + DEBUG_LOG(G3D, "%f %f %f", m[6], m[7], m[8]); + DEBUG_LOG(G3D, "%f %f %f", m[9], m[10], m[11]); + */ + // Then, transform and draw in one big swoop (urgh!) // need to move this to the shader. @@ -423,7 +433,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte memcpy(&transformed[index].color1, c1, 4 * sizeof(float)); } - // Step 2: Expand using the index buffer, and expand rectangles. const TransformedVertex *drawBuffer = transformed; @@ -526,6 +535,35 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } + ApplyDrawState(); + UpdateViewportAndProjection(); + LinkedShader *program = shaderManager_->ApplyShader(prim); + + // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. + glEnableVertexAttribArray(program->a_position); + if (useTexCoord && program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); + if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); + if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1); + const int vertexSize = sizeof(transformed[0]); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); + if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); + if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); + if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); + // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); + if (drawIndexed) { + glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); + } else { + glDrawArrays(glprim[prim], 0, numTrans); + } + glDisableVertexAttribArray(program->a_position); + if (useTexCoord && program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); + if (program->a_color0 != -1) glDisableVertexAttribArray(program->a_color0); + if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); +} + +void GLES_GPU::ApplyDrawState() +{ + // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. // TODO: The top bit of the alpha channel should be written to the stencil bit somehow. This appears to require very expensive multipass rendering :( Alternatively, one could do a @@ -620,30 +658,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte float depthRangeMin = gstate_c.zOff - gstate_c.zScale; float depthRangeMax = gstate_c.zOff + gstate_c.zScale; glstate.depthRange.set(depthRangeMin, depthRangeMax); - - UpdateViewportAndProjection(); - LinkedShader *program = shaderManager_->ApplyShader(prim); - - // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. - glEnableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); - if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); - if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1); - const int vertexSize = sizeof(transformed[0]); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); - if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); - if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); - if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); - // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); - if (drawIndexed) { - glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); - } else { - glDrawArrays(glprim[prim], 0, numTrans); - } - glDisableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); - if (program->a_color0 != -1) glDisableVertexAttribArray(program->a_color0); - if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } void GLES_GPU::UpdateViewportAndProjection() diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 91f12d24c1..51664cc983 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -483,6 +483,10 @@ namespace MainWindow _ViewFullScreen(hWnd); } break; + case ID_OPTIONS_WIREFRAME: + g_Config.bDrawWireframe = !g_Config.bDrawWireframe; + UpdateMenus(); + break; case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; @@ -627,6 +631,7 @@ namespace MainWindow CHECKITEM(ID_CPU_DYNAREC,g_Config.iCpuCore == CPU_JIT); CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); + CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); BOOL enable = !Core_IsStepping(); EnableMenuItem(menu,ID_EMULATION_RUN,enable); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 8ddb89699d..4d12eb0163 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -214,6 +214,7 @@ BEGIN MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING + MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS MENUITEM SEPARATOR MENUITEM "Screen &1x\tCtrl+1", ID_OPTIONS_SCREEN1X diff --git a/Windows/resource.h b/Windows/resource.h index 594a397e12..631760dffe 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -243,13 +243,14 @@ #define ID_EMULATION_FASTINTERPRETER 40120 #define ID_CPU_FASTINTERPRETER 40121 #define ID_OPTIONS_SHOWDEBUGSTATISTICS 40122 +#define ID_OPTIONS_WIREFRAME 40123 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40123 +#define _APS_NEXT_COMMAND_VALUE 40124 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif From fc4159efefbce7ef2fe387ffaf276a87af91a486 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Wed, 19 Dec 2012 16:57:22 +0100 Subject: [PATCH 019/276] Work on mode 8 --- Core/Dialog/PSPSaveDialog.cpp | 10 +++- Core/Dialog/SavedataParam.cpp | 89 +++++++++++++++++++++++++++++------ Core/Dialog/SavedataParam.h | 2 + 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index f94940c40d..7fc01c7b98 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -646,8 +646,14 @@ void PSPSaveDialog::Update() return; break; case SCE_UTILITY_SAVEDATA_TYPE_SIZES: - param.GetSizes(param.GetPspParam()); - param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; + if(param.GetSizes(param.GetPspParam())) + { + param.GetPspParam()->result = 0; + } + else + { + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; + } status = SCE_UTILITY_STATUS_FINISHED; return; case SCE_UTILITY_SAVEDATA_TYPE_LIST: diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 1fa24aa874..45831541c6 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -20,6 +20,7 @@ #include "image/png_load.h" #include "../HLE/sceKernelMemory.h" #include "../ELF/ParamSFO.h" +#include "Core/HW/MemoryStick.h" std::string icon0Name = "ICON0.PNG"; std::string icon1Name = "ICON1.PMF"; @@ -29,6 +30,15 @@ std::string sfoName = "PARAM.SFO"; std::string savePath = "ms0:/PSP/SAVEDATA/"; +namespace +{ + int getSizeNormalized(int size) + { + int sizeCluster = MemoryStick_SectorSize(); + return ((size + sizeCluster - 1) / sizeCluster) * sizeCluster; + } +} + SavedataParam::SavedataParam() : pspParam(0) , selectedSave(0) @@ -254,6 +264,26 @@ bool SavedataParam::Load(SceUtilitySavedataParam* param, int saveId) return true; } +std::string SavedataParam::GetSpaceText(int size) +{ + if(size < 1024) + return size + " B"; + + size /= 1024; + + if(size < 1024) + return size + " KB"; + + size /= 1024; + + if(size < 1024) + return size + " MB"; + + return size + " GB"; +} + +// From my test, PSP only answer with data for save of size 1500 (sdk < 2) +// Perhaps remplaced with mode 22 id SDK >= 2 bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) { if (!param) { @@ -262,26 +292,55 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) if(Memory::IsValidAddress(param->msFree)) { - Memory::Write_U32(32768,param->msFree); - Memory::Write_U32(32768,param->msFree+4); - Memory::Write_U32(1048576,param->msFree+8); - Memory::Write_U8(0,param->msFree+12); + Memory::Write_U32((u32)MemoryStick_SectorSize(),param->msFree); // cluster Size + Memory::Write_U32((u32)(MemoryStick_FreeSpace() / MemoryStick_SectorSize()),param->msFree+4); // Free cluster + Memory::Write_U32((u32)(MemoryStick_FreeSpace() / 0x400),param->msFree+8); // Free space (in KB) + std::string spaceTxt = SavedataParam::GetSpaceText(MemoryStick_FreeSpace()); + Memory::Memset(param->msFree+12,0,spaceTxt.size()+1); + Memory::Memcpy(param->msFree+12,spaceTxt.c_str(),spaceTxt.size()); // Text representing free space } if(Memory::IsValidAddress(param->msData)) { - Memory::Write_U32(0,param->msData+36); - Memory::Write_U32(0,param->msData+40); - Memory::Write_U8(0,param->msData+44); - Memory::Write_U32(0,param->msData+52); - Memory::Write_U8(0,param->msData+56); + std::string path = GetSaveFilePath(param,0); + PSPFileInfo finfo = pspFileSystem.GetFileInfo(path); + if(finfo.exists) + { + // TODO : fill correctly + Memory::Write_U32(1,param->msData+36); //1 + Memory::Write_U32(0x20,param->msData+40); // 0x20 + Memory::Write_U8(0,param->msData+44); // "32 KB" // 8 u8 + Memory::Write_U32(0x20,param->msData+52); // 0x20 + Memory::Write_U8(0,param->msData+56); // "32 KB" // 8 u8 + } + else + { + Memory::Write_U32(1,param->msData+36); + Memory::Write_U32(0x20,param->msData+40); + Memory::Write_U8(0,param->msData+44); + Memory::Write_U32(0x20,param->msData+52); + Memory::Write_U8(0,param->msData+56); + //return false; + } } - if(Memory::IsValidAddress(param->utilityData)) + if(Memory::IsValidAddress(param->utilityData)) // Calc space required for save { - Memory::Write_U32(13,param->utilityData); - Memory::Write_U32(416,param->utilityData+4); - Memory::Write_U8(0,param->utilityData+8); - Memory::Write_U32(416,param->utilityData+16); - Memory::Write_U8(0,param->utilityData+20); + int total_size = 0; + total_size += getSizeNormalized(1); // SFO; + total_size += getSizeNormalized(param->dataSize); // Save Data + total_size += getSizeNormalized(param->icon0FileData.size); + total_size += getSizeNormalized(param->icon1FileData.size); + total_size += getSizeNormalized(param->pic1FileData.size); + total_size += getSizeNormalized(param->snd0FileData.size); + + Memory::Write_U32(total_size / MemoryStick_SectorSize(),param->utilityData); // num cluster + Memory::Write_U32(total_size / 0x400,param->utilityData+4); // save size in KB + std::string spaceTxt = SavedataParam::GetSpaceText(total_size); + Memory::Memset(param->utilityData+8,0,spaceTxt.size()+1); + Memory::Memcpy(param->utilityData+8,spaceTxt.c_str(),spaceTxt.size()); // save size in text + Memory::Write_U32(total_size / 0x400,param->utilityData+16); // save size in KB + spaceTxt = SavedataParam::GetSpaceText(total_size); + Memory::Memset(param->utilityData+20,0,spaceTxt.size()+1); + Memory::Memcpy(param->utilityData+20,spaceTxt.c_str(),spaceTxt.size()); // save size in text } return true; diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 23c77e28ad..e4fc5f4094 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -151,6 +151,8 @@ public: std::string GetSaveName(SceUtilitySavedataParam* param); std::string GetFileName(SceUtilitySavedataParam* param); + static std::string GetSpaceText(int size); + SavedataParam(); void SetPspParam(SceUtilitySavedataParam* param); From 4fb3066e39edc451af2626d3cb9d85fae8b6fd87 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Wed, 19 Dec 2012 18:15:02 +0100 Subject: [PATCH 020/276] Continue work on mode 8 --- Core/Dialog/SavedataParam.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 45831541c6..0a5887f901 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -35,7 +35,7 @@ namespace int getSizeNormalized(int size) { int sizeCluster = MemoryStick_SectorSize(); - return ((size + sizeCluster - 1) / sizeCluster) * sizeCluster; + return ((int)((size + sizeCluster - 1) / sizeCluster)) * sizeCluster; } } @@ -266,24 +266,38 @@ bool SavedataParam::Load(SceUtilitySavedataParam* param, int saveId) std::string SavedataParam::GetSpaceText(int size) { + char text[50]; + if(size < 1024) - return size + " B"; + { + sprintf(text,"%d B",size); + return std::string(text); + } size /= 1024; if(size < 1024) - return size + " KB"; + { + sprintf(text,"%d KB",size); + return std::string(text); + } size /= 1024; if(size < 1024) - return size + " MB"; + { + sprintf(text,"%d MB",size); + return std::string(text); + } - return size + " GB"; + size /= 1024; + sprintf(text,"%d GB",size); + return std::string(text); } // From my test, PSP only answer with data for save of size 1500 (sdk < 2) -// Perhaps remplaced with mode 22 id SDK >= 2 +// Perhaps changed to use mode 22 id SDK >= 2 +// For now we always return results bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) { if (!param) { @@ -305,7 +319,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) PSPFileInfo finfo = pspFileSystem.GetFileInfo(path); if(finfo.exists) { - // TODO : fill correctly + // TODO : fill correctly with the total save size Memory::Write_U32(1,param->msData+36); //1 Memory::Write_U32(0x20,param->msData+40); // 0x20 Memory::Write_U8(0,param->msData+44); // "32 KB" // 8 u8 From fbc825a73dd9568a4b949da8056fc0cb8f10b82c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 18:35:20 +0100 Subject: [PATCH 021/276] Buildfix --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 99fae0257e..2f119152a4 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -569,7 +569,7 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; } - for (size_t i = 0; i < std::min(readBufSize, threadqueue.size()); i++) + for (size_t i = 0; i < std::min((size_t)readBufSize, threadqueue.size()); i++) { Memory::Write_U32(threadqueue[i]->GetUID(), readBufPtr + i * 4); } From b8d596cbec18d8fdef060d132f0940ffa50d8f23 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 18:35:37 +0100 Subject: [PATCH 022/276] Add some infrastructure for flexible vertex formats --- GPU/GLES/DisplayListInterpreter.cpp | 2 +- GPU/GLES/DisplayListInterpreter.h | 2 +- GPU/GLES/FragmentShaderGenerator.cpp | 17 ++- GPU/GLES/ShaderManager.cpp | 11 +- GPU/GLES/ShaderManager.h | 9 +- GPU/GLES/TransformPipeline.cpp | 71 ++++++++++++- GPU/GLES/VertexDecoder.cpp | 134 +++++++++++++++++++----- GPU/GLES/VertexDecoder.h | 151 ++++++++++++++++++++++++++- 8 files changed, 353 insertions(+), 44 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 1662d17c06..47ebb62592 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -995,7 +995,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ALPHATEST: DEBUG_LOG(G3D,"DL Alpha test settings"); - shaderManager.DirtyUniform(DIRTY_ALPHAREF); + shaderManager.DirtyUniform(DIRTY_ALPHACOLORREF); break; case GE_CMD_TEXFUNC: diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 8fe6ae971a..e7faf8c45a 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -52,7 +52,7 @@ private: // TransformPipeline.cpp void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); void ApplyDrawState(); - void Flush(); + void Flush(int prim); void UpdateViewportAndProjection(); void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 0b4003c3a2..a7f11113bd 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -79,8 +79,8 @@ char *GenerateFragmentShader() if (doTexture) WRITE(p, "uniform sampler2D tex;\n"); - if (gstate.alphaTestEnable & 1) - WRITE(p, "uniform vec4 u_alpharef;\n"); + if ((gstate.alphaTestEnable & 1) || (gstate.colorTestEnable & 1)) + WRITE(p, "uniform vec4 u_alphacolorref;\n"); if (gstate.fogEnable & 1) { WRITE(p, "uniform vec3 u_fogcolor;\n"); WRITE(p, "uniform vec2 u_fogcoef;\n"); @@ -163,9 +163,20 @@ char *GenerateFragmentShader() int alphaTestFunc = gstate.alphatest & 7; const char *alphaTestFuncs[] = { "#", "#", " == ", " != ", " < ", " <= ", " > ", " >= " }; // never/always don't make sense if (alphaTestFuncs[alphaTestFunc][0] != '#') - WRITE(p, "if (!(v.a %s u_alpharef.x)) discard;", alphaTestFuncs[alphaTestFunc]); + WRITE(p, "if (!(v.a %s u_alphacolorref.a)) discard;", alphaTestFuncs[alphaTestFunc]); } + // Disabled for now until we actually find a need for it. + /* + if (gstate.colorTestEnable & 1) { + // TODO: There are some colortestmasks we could handle. + int colorTestFunc = gstate.colortest & 3; + const char *colorTestFuncs[] = { "#", "#", " == ", " != " }; // never/always don't make sense} + int colorTestMask = gstate.colormask; + if (colorTestFuncs[colorTestFunc][0] != '#') + WRITE(p, "if (!(v.rgb %s u_alphacolorref.rgb)) discard;", colorTestFuncs[colorTestFunc]); + }*/ + if (gstate.isFogEnabled()) { // Haven't figured out how to adjust the depth range yet. // WRITE(p, " v = mix(v, u_fogcolor, u_fogcoef.x + u_fogcoef.y * v_depth;\n"); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 78303948c8..34c24c0aeb 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -79,18 +79,21 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) u_texenv = glGetUniformLocation(program, "u_texenv"); u_fogcolor = glGetUniformLocation(program, "u_fogcolor"); u_fogcoef = glGetUniformLocation(program, "u_fogcoef"); - u_alpharef = glGetUniformLocation(program, "u_alpharef"); + u_alphacolorref = glGetUniformLocation(program, "u_alphacolorref"); a_position = glGetAttribLocation(program, "a_position"); a_color0 = glGetAttribLocation(program, "a_color0"); a_color1 = glGetAttribLocation(program, "a_color1"); a_texcoord = glGetAttribLocation(program, "a_texcoord"); + a_normal = glGetAttribLocation(program, "a_normal"); + a_weight0123 = glGetAttribLocation(program, "a_weight0123"); + a_weight4567 = glGetAttribLocation(program, "a_weight4567"); glUseProgram(program); // Default uniform values glUniform1i(u_tex, 0); // The rest, use the "dirty" mechanism. - dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_TEXENV | DIRTY_ALPHAREF; + dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_TEXENV | DIRTY_ALPHACOLORREF; } LinkedShader::~LinkedShader() { @@ -135,8 +138,8 @@ void LinkedShader::use() { if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) { SetColorUniform3(u_texenv, gstate.texenvcolor); } - if (u_alpharef != -1 && (dirtyUniforms & DIRTY_ALPHAREF)) { - glUniform4f(u_alpharef, ((float)((gstate.alphatest >> 8) & 0xFF)) / 255.0f, 0.0f, 0.0f, 0.0f); + if (u_alphacolorref != -1 && (dirtyUniforms & DIRTY_ALPHACOLORREF)) { + glUniform4f(u_alphacolorref, 0.0f, 0.0f, 0.0f, ((float)((gstate.alphatest >> 8) & 0xFF)) / 255.0f); } if (u_fogcolor != -1 && (dirtyUniforms & DIRTY_FOGCOLOR)) { SetColorUniform3(u_fogcolor, gstate.fogcolor); diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index 33c5b308dc..5b4a98ee8c 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -40,8 +40,9 @@ struct LinkedShader int a_color0; int a_color1; int a_texcoord; - // int a_blendWeight0123; - // int a_blendWeight4567; + int a_normal; + int a_weight0123; + int a_weight4567; int u_tex; int u_proj; @@ -49,7 +50,7 @@ struct LinkedShader int u_texenv; // Fragment processing inputs - int u_alpharef; + int u_alphacolorref; int u_fogcolor; int u_fogcoef; @@ -66,7 +67,7 @@ enum DIRTY_FOGCOLOR = (1 << 2), DIRTY_FOGCOEF = (1 << 3), DIRTY_TEXENV = (1 << 4), - DIRTY_ALPHAREF = (1 << 5), + DIRTY_ALPHACOLORREF = (1 << 5), DIRTY_COLORREF = (1 << 6), DIRTY_LIGHT0 = (1 << 12), diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index b5569bfea4..f0aeec1a7d 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -203,6 +203,15 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte VertexDecoder dec; dec.SetVertexType(gstate.vertType); dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + if (bytesRead) + *bytesRead = vertexCount * dec.VertexSize(); + + // And here we should return, having collected the morphed but untransformed vertices. + // Note that DecodeVerts should convert strips into indexed lists etc, adding to our + // current vertex buffer and index buffer. + + // The rest below here should only execute on Flush. + #if 0 for (int i = indexLowerBound; i <= indexUpperBound; i++) { PrintDecodedVertex(decoded[i], gstate.vertType); @@ -222,9 +231,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte gpuStats.numDrawCalls++; gpuStats.numVertsTransformed += vertexCount; - if (bytesRead) - *bytesRead = vertexCount * dec.VertexSize(); - bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; /* @@ -535,8 +541,12 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } + // TODO: This should not be done on every drawcall, we should collect vertex data + // until critical state changes. That's when we draw (flush). + ApplyDrawState(); UpdateViewportAndProjection(); + LinkedShader *program = shaderManager_->ApplyShader(prim); // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. @@ -561,6 +571,61 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } +struct GlTypeInfo { + GLuint type; + int count; + GLboolean normalized; +}; + +const GlTypeInfo GLComp[8] = { + {0}, // DEC_NONE, + {GL_FLOAT, 1, GL_FALSE}, // DEC_FLOAT_1, + {GL_FLOAT, 2, GL_FALSE}, // DEC_FLOAT_2, + {GL_FLOAT, 3, GL_FALSE}, // DEC_FLOAT_3, + {GL_FLOAT, 4, GL_FALSE}, // DEC_FLOAT_4, + {GL_BYTE, 3, GL_TRUE}, // DEC_S8_3, + {GL_SHORT, 3, GL_TRUE},// DEC_S16_3, + {GL_BYTE, 4, GL_TRUE},// DEC_U8_4, +}; + +static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) { + if (attrib != -1 && fmt) { + const GlTypeInfo &type = GLComp[fmt]; + glEnableVertexAttribArray(attrib); + glVertexAttribPointer(attrib, type.count, type.type, type.normalized, stride, ptr); + } +} +static inline void VertexAttribDisable(int attrib, int fmt) { + if (attrib != -1 && fmt) { + glDisableVertexAttribArray(attrib); + } +} + +// TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets +static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) { + VertexAttribSetup(program->a_weight0123, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off); + VertexAttribSetup(program->a_weight4567, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off); + VertexAttribSetup(program->a_texcoord, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff); + VertexAttribSetup(program->a_color0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off); + VertexAttribSetup(program->a_color1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off); + VertexAttribSetup(program->a_normal, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff); + VertexAttribSetup(program->a_position, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff); +} + +static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) { + VertexAttribDisable(program->a_weight0123, decFmt.w0fmt); + VertexAttribDisable(program->a_weight4567, decFmt.w1fmt); + VertexAttribDisable(program->a_texcoord, decFmt.uvfmt); + VertexAttribDisable(program->a_color0, decFmt.c0fmt); + VertexAttribDisable(program->a_color1, decFmt.c1fmt); + VertexAttribDisable(program->a_normal, decFmt.nrmfmt); + VertexAttribDisable(program->a_position, decFmt.posfmt); +} + +void GLES_GPU::Flush(int prim) { + // TODO +} + void GLES_GPU::ApplyDrawState() { diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 33f3281865..91f9aebf0f 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -22,8 +22,7 @@ #include "VertexDecoder.h" -void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype) -{ +void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype) { if (vtype & GE_VTYPE_NRM_MASK) printf("N: %f %f %f\n", vtx.normal[0], vtx.normal[1], vtx.normal[2]); if (vtype & GE_VTYPE_TC_MASK) printf("TC: %f %f\n", vtx.uv[0], vtx.uv[1]); if (vtype & GE_VTYPE_COL_MASK) printf("C: %02x %02x %02x %02x\n", vtx.color[0], vtx.color[1], vtx.color[2], vtx.color[3]); @@ -37,67 +36,137 @@ const int nrmsize[4] = {0,3,6,12}, nrmalign[4] = {0,1,2,4}; const int possize[4] = {0,3,6,12}, posalign[4] = {0,1,2,4}; const int wtsize[4] = {0,1,2,4}, wtalign[4] = {0,1,2,4}; -inline int align(int n, int align) -{ +inline int align(int n, int align) { return (n + (align - 1)) & ~(align - 1); } -void VertexDecoder::SetVertexType(u32 fmt) -{ +int DecFmtSize(u8 fmt) { + switch (fmt) { + case DEC_NONE: return 0; + case DEC_FLOAT_1: return 4; + case DEC_FLOAT_2: return 8; + case DEC_FLOAT_3: return 12; + case DEC_FLOAT_4: return 16; + case DEC_S8_3: return 4; + case DEC_S16_3: return 8; + case DEC_U8_4: return 4; + default: + return 0; + } +} + +// This is what the software transform spits out, and thus w +DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { + DecVtxFormat tfm = {0}; + int size = 0; + int offset = 0; + // Weights disappear during transform. + if (fmt.uvfmt) { + // UV always becomes float2. + tfm.uvfmt = DEC_FLOAT_2; + tfm.uvoff = offset; + offset += DecFmtSize(tfm.uvfmt); + } + // We always (?) get two colors out, they're floats (although we'd probably be fine with less precision). + tfm.c0fmt = DEC_FLOAT_4; + tfm.c0off = offset; + offset += DecFmtSize(tfm.c0fmt); + tfm.c1fmt = DEC_FLOAT_3; // color1 (specular) doesn't have alpha. + tfm.c1off = offset; + offset += DecFmtSize(tfm.c1fmt); + // We never get a normal, it's gone. + // But we do get a position, and it's always float3. + tfm.posfmt = DEC_FLOAT_3; + tfm.posoff = offset; + offset += DecFmtSize(tfm.posfmt); + // Update stride. + tfm.stride = offset; + return tfm; +} + +void VertexDecoder::SetVertexType(u32 fmt) { fmt = fmt; throughmode = (fmt & GE_VTYPE_THROUGH) != 0; int biggest = 0; size = 0; - tc = fmt & 0x3; - col = (fmt >> 2) & 0x7; - nrm = (fmt >> 5) & 0x3; - pos = (fmt >> 7) & 0x3; + tc = fmt & 0x3; + col = (fmt >> 2) & 0x7; + nrm = (fmt >> 5) & 0x3; + pos = (fmt >> 7) & 0x3; weighttype = (fmt >> 9) & 0x3; - idx = (fmt >> 11) & 0x3; + idx = (fmt >> 11) & 0x3; morphcount = ((fmt >> 18) & 0x7)+1; - nweights = ((fmt >> 14) & 0x7)+1; + nweights = ((fmt >> 14) & 0x7)+1; + + int decOff = 0; + memset(&decFmt, 0, sizeof(decFmt)); DEBUG_LOG(G3D,"VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount); - if (weighttype) - { + if (weighttype) { // && nweights? //size = align(size, wtalign[weighttype]); unnecessary size += wtsize[weighttype] * nweights; if (wtalign[weighttype] > biggest) biggest = wtalign[weighttype]; + + if (nweights < 5) { + decFmt.w0off = decOff; + decFmt.w0fmt = DEC_FLOAT_1 + nweights - 1; + } else { + decFmt.w0off = decOff; + decFmt.w0fmt = DEC_FLOAT_4; + decFmt.w1off = decOff + 4 * 4; + decFmt.w1fmt = DEC_FLOAT_1 + nweights - 5; + } + decOff += nweights * 4; } - if (tc) - { + if (tc) { size = align(size, tcalign[tc]); tcoff = size; size += tcsize[tc]; if (tcalign[tc] > biggest) biggest = tcalign[tc]; + + // All UV decode to DEC_FLOAT2 currently. + decFmt.uvfmt = DEC_FLOAT_2; + decFmt.uvoff = decOff; + decOff += DecFmtSize(decFmt.uvfmt); } - if (col) - { + if (col) { size = align(size, colalign[col]); coloff = size; size += colsize[col]; if (colalign[col] > biggest) biggest = colalign[col]; - } - else - { + + // All color formats decode to DEC_U8_4 currently. + // They can become floats later during transform though. + decFmt.c0fmt = DEC_U8_4; + decFmt.c0off = decOff; + decOff += DecFmtSize(decFmt.c0fmt); + } else { coloff = 0; } - if (nrm) - { + if (nrm) { size = align(size, nrmalign[nrm]); nrmoff = size; size += nrmsize[nrm]; if (nrmalign[nrm] > biggest) biggest = nrmalign[nrm]; + + // The normal formats match the gl formats perfectly, let's use 'em. + switch (nrm) { + case GE_VTYPE_NRM_8BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S8_3; break; + case GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S16_3; break; + case GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_FLOAT_3; break; + } + decFmt.nrmoff = decOff; + decOff += DecFmtSize(decFmt.nrmfmt); } //if (pos) - there's always a position @@ -107,6 +176,19 @@ void VertexDecoder::SetVertexType(u32 fmt) size += possize[pos]; if (posalign[pos] > biggest) biggest = posalign[pos]; + + if (throughmode) { + decFmt.posfmt = DEC_FLOAT_3; + } else { + // The non-through-mode position formats match the gl formats perfectly, let's use 'em. + switch (pos) { + case GE_VTYPE_POS_8BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S8_3; break; + case GE_VTYPE_POS_16BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S16_3; break; + case GE_VTYPE_POS_FLOAT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_FLOAT_3; break; + } + } + decFmt.posoff = decOff; + decOff += DecFmtSize(decFmt.posfmt); } size = align(size, biggest); @@ -343,14 +425,16 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const case GE_VTYPE_POS_8BIT >> 7: { + float multiplier = 1.0f / 127.0f; + if (throughmode) multiplier = 1.0f; const s8 *sv = (const s8*)(ptr + posoff); for (int j = 0; j < 3; j++) - v[j] = sv[j] / 127.f; + v[j] = sv[j] * multiplier; } break; default: - ERROR_LOG(G3D,"Unknown position format %i",pos); + ERROR_LOG(G3D, "Unknown position format %i",pos); break; } } else { diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 464ebf72a1..fb02f42218 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -21,6 +21,36 @@ #include "../Globals.h" #include "base/basictypes.h" +// DecVtxFormat - vertex formats for PC +// Kind of like a D3D VertexDeclaration. +// Can write code to easily bind these using OpenGL, or read these manually. +// No morph support, that is taken care of by the VertexDecoder. + +enum { + DEC_NONE, + DEC_FLOAT_1, + DEC_FLOAT_2, + DEC_FLOAT_3, + DEC_FLOAT_4, + DEC_S8_3, + DEC_S16_3, + DEC_U8_4, +}; + +int DecFmtSize(u8 fmt); + +struct DecVtxFormat { + u8 w0fmt; u8 w0off; // first 4 weights + u8 w1fmt; u8 w1off; // second 4 weights + u8 uvfmt; u8 uvoff; + u8 c0fmt; u8 c0off; // First color + u8 c1fmt; u8 c1off; + u8 nrmfmt; u8 nrmoff; + u8 posfmt; u8 posoff; + short stride; +}; + +// This is going away soon enough. struct DecodedVertex { float pos[3]; // in case of morph, preblend during decode @@ -30,6 +60,7 @@ struct DecodedVertex float weights[8]; // ugh, expensive }; +// This struct too. struct TransformedVertex { float x, y, z; // in case of morph, preblend during decode @@ -38,31 +69,37 @@ struct TransformedVertex float color1[4]; // prelit }; +DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt); // Right now // - only contains computed information // - does decoding in nasty branchfilled loops // Future TODO +// - should be cached, not recreated every time +// - will compile into list of called functions // - will compile into lighting fast specialized x86 and ARM // - will not bother translating components that can be read directly -// by OpenGL ES. Will still have to translate 565 colors, and things +// by OpenGL ES. Will still have to translate 565 colors and things // like that. DecodedVertex will not be a fixed struct. Will have to // do morphing here. -// -// We want 100% perf on 1Ghz even in vertex complex games! class VertexDecoder { public: VertexDecoder() : coloff(0), nrmoff(0), posoff(0) {} ~VertexDecoder() {} + void SetVertexType(u32 vtype); + + const DecVtxFormat &GetDecVtxFmt() { return decFmt; } void DecodeVerts(DecodedVertex *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const; bool hasColor() const { return col != 0; } int VertexSize() const { return size; } private: u32 fmt; + DecVtxFormat decFmt; + bool throughmode; int biggest; int size; @@ -84,6 +121,114 @@ private: int nweights; }; + +// Reads decoded vertex formats in a convenient way. For software transform and debugging. +class VertexReader +{ +public: + VertexReader(u8 *data, const DecVtxFormat &decFmt) : data_(data), decFmt_(decFmt) {} + + void ReadPos(float pos[3]) { + switch (decFmt_.posfmt) { + case DEC_FLOAT_3: memcpy(pos, data_ + decFmt_.posoff, 12); break; + case DEC_S16_3: + { + s16 *p = (s16 *)(data_ + decFmt_.posoff); + for (int i = 0; i < 3; i++) + pos[i] = p[i] / 32767.0f; + } + break; + case DEC_S8_3: + { + s8 *p = (s8 *)(data_ + decFmt_.posoff); + for (int i = 0; i < 3; i++) + pos[i] = p[i] / 127.0f; + } + break; + } + } + + void ReadNrm(float nrm[3]) { + switch (decFmt_.nrmoff) { + case DEC_FLOAT_3: memcpy(nrm, data_ + decFmt_.nrmoff, 12); break; + case DEC_S16_3: + { + s16 *p = (s16 *)(data_ + decFmt_.nrmoff); + for (int i = 0; i < 3; i++) + nrm[i] = p[i] / 32767.0f; + } + break; + case DEC_S8_3: + { + s8 *p = (s8 *)(data_ + decFmt_.nrmoff); + for (int i = 0; i < 3; i++) + nrm[i] = p[i] / 127.0f; + } + break; + } + } + + void ReadUV(float uv[2]) { + switch (decFmt_.uvfmt) { + case DEC_FLOAT_2: + memcpy(uv, data_ + decFmt_.nrmoff, 8); break; + } + } + + void ReadColor0(float color[4]) { + switch (decFmt_.c0fmt) { + case DEC_U8_4: + { + u8 *p = (u8 *)(data_ + decFmt_.c0off); + for (int i = 0; i < 4; i++) + color[i] = p[i] / 255.0f; + } + break; + case DEC_FLOAT_4: + memcpy(color, data_ + decFmt_.c0off, 16); break; + } + } + + void ReadColor1(float color[4]) { + switch (decFmt_.c1fmt) { + case DEC_U8_4: + { + u8 *p = (u8 *)(data_ + decFmt_.c1off); + for (int i = 0; i < 4; i++) + color[i] = p[i] / 255.0f; + } + break; + case DEC_FLOAT_4: + memcpy(color, data_ + decFmt_.c1off, 16); break; + } + } + + void ReadWeights(float weights[8]) { + switch (decFmt_.w0fmt) { + case DEC_FLOAT_1: memcpy(weights, data_ + decFmt_.w0off, 4); break; + case DEC_FLOAT_2: memcpy(weights, data_ + decFmt_.w0off, 8); break; + case DEC_FLOAT_3: memcpy(weights, data_ + decFmt_.w0off, 12); break; + case DEC_FLOAT_4: memcpy(weights, data_ + decFmt_.w0off, 16); break; + } + switch (decFmt_.w1fmt) { + case DEC_FLOAT_1: memcpy(weights + 4, data_ + decFmt_.w1off, 4); break; + case DEC_FLOAT_2: memcpy(weights + 4, data_ + decFmt_.w1off, 8); break; + case DEC_FLOAT_3: memcpy(weights + 4, data_ + decFmt_.w1off, 12); break; + case DEC_FLOAT_4: memcpy(weights + 4, data_ + decFmt_.w1off, 16); break; + } + } + + void Next() { + data_ += decFmt_.stride; + } + +private: + u8 *data_; + DecVtxFormat decFmt_; + int vtype_; +}; + // Debugging utilities void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype); + From 13460b7aa6e25efc63d2f519bd37a8678ea43f9f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 20:21:59 +0100 Subject: [PATCH 023/276] Use flexible vertex formats pre-transform. Saves memory b/w. --- GPU/GLES/TransformPipeline.cpp | 88 ++++++++++++++++++---------- GPU/GLES/VertexDecoder.cpp | 102 +++++++++++++++++++-------------- GPU/GLES/VertexDecoder.h | 28 +++++---- 3 files changed, 134 insertions(+), 84 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index f0aeec1a7d..de27b6533f 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -42,7 +42,7 @@ GLuint glprim[8] = GL_TRIANGLES, // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? }; -DecodedVertex decoded[65536]; +u8 decoded[65536 * 32]; TransformedVertex transformed[65536]; TransformedVertex transformedExpanded[65536]; uint16_t indexBuffer[65536]; // Unused @@ -270,8 +270,11 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte Lighter lighter; + VertexReader reader(decoded, dec.GetDecVtxFmt()); for (int index = indexLowerBound; index <= indexUpperBound; index++) { + reader.Goto(index); + float v[3] = {0, 0, 0}; float c0[4] = {1, 1, 1, 1}; float c1[4] = {0, 0, 0, 0}; @@ -280,11 +283,10 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (throughmode) { // Do not touch the coordinates or the colors. No lighting. - for (int j=0; j<3; j++) - v[j] = decoded[index].pos[j]; - if(dec.hasColor()) { - for (int j=0; j<4; j++) { - c0[j] = decoded[index].color[j] / 255.0f; + reader.ReadPos(v); + if (reader.hasColor0()) { + reader.ReadColor0(c0); + for (int j = 0; j < 4; j++) { c1[j] = 0.0f; } } @@ -296,48 +298,69 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte c0[3] = (gstate.materialalpha & 0xFF) / 255.f; } - // TODO : check if has uv - for (int j=0; j<2; j++) - uv[j] = decoded[index].uv[j]; - // Rescale UV? + if (reader.hasUV()) { + reader.ReadUV(uv); + } + // Scale UV? } else { // We do software T&L for now float out[3], norm[3]; + float pos[3], nrm[3]; + reader.ReadPos(pos); + if (reader.hasNormal()) + reader.ReadNrm(nrm); + if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { - Vec3ByMatrix43(out, decoded[index].pos, gstate.worldMatrix); - Norm3ByMatrix43(norm, decoded[index].normal, gstate.worldMatrix); + Vec3ByMatrix43(out, pos, gstate.worldMatrix); + if (reader.hasNormal()) { + Norm3ByMatrix43(norm, nrm, gstate.worldMatrix); + } else { + memset(norm, 0, 12); + } } else { + float weights[8]; + reader.ReadPos(pos); + if (reader.hasNormal()) { + reader.ReadNrm(nrm); + } else { + memset(nrm, 0, 12); + } + reader.ReadWeights(weights); // Skinning Vec3 psum(0,0,0); Vec3 nsum(0,0,0); int nweights = ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT) + 1; for (int i = 0; i < nweights; i++) { - if (decoded[index].weights[i] != 0.0f) { - Vec3ByMatrix43(out, decoded[index].pos, gstate.boneMatrix+i*12); - Norm3ByMatrix43(norm, decoded[index].normal, gstate.boneMatrix+i*12); - Vec3 tpos(out), tnorm(norm); - psum += tpos*decoded[index].weights[i]; - nsum += tnorm*decoded[index].weights[i]; + if (weights[i] != 0.0f) { + Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12); + Vec3 tpos(out); + psum += tpos * weights[i]; + if (reader.hasNormal()) { + Norm3ByMatrix43(norm, nrm, gstate.boneMatrix+i*12); + Vec3 tnorm(norm); + nsum += tnorm * weights[i]; + } } } - - nsum.Normalize(); - + Vec3ByMatrix43(out, psum.v, gstate.worldMatrix); - Norm3ByMatrix43(norm, nsum.v, gstate.worldMatrix); + if (reader.hasNormal()) { + nsum.Normalize(); + Norm3ByMatrix43(norm, nsum.v, gstate.worldMatrix); + } } // Perform lighting here if enabled. don't need to check through, it's checked above. float dots[4] = {0,0,0,0}; - float unlitColor[4]; - for (int j = 0; j < 4; j++) { - unlitColor[j] = decoded[index].color[j] / 255.0f; + float unlitColor[4] = {1, 1, 1, 1}; + if (reader.hasColor0()) { + reader.ReadColor0(unlitColor); } float litColor0[4]; float litColor1[4]; @@ -378,14 +401,16 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (customUV) { uv[0] = customUV[index * 2 + 0]*gstate_c.uScale + gstate_c.uOff; uv[1] = customUV[index * 2 + 1]*gstate_c.vScale + gstate_c.vOff; - } else { + } else if (reader.hasUV()) { + float ruv[2]; + reader.ReadUV(ruv); // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. switch (gstate.texmapmode & 0x3) { case 0: // UV mapping // Texture scale/offset is only performed in this mode. - uv[0] = decoded[index].uv[0]*gstate_c.uScale + gstate_c.uOff; - uv[1] = decoded[index].uv[1]*gstate_c.vScale + gstate_c.vOff; + uv[0] = ruv[0]*gstate_c.uScale + gstate_c.uOff; + uv[1] = ruv[1]*gstate_c.vScale + gstate_c.vOff; break; case 1: { @@ -394,10 +419,10 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte switch ((gstate.texmapmode >> 8) & 0x3) { case 0: // Use model space XYZ as source - source = decoded[index].pos; + source = pos; break; case 1: // Use unscaled UV as source - source = Vec3(decoded[index].uv[0], decoded[index].uv[1], 0.0f); + source = Vec3(ruv[0], ruv[1], 0.0f); break; case 2: // Use normalized normal as source source = Vec3(norm).Normalized(); @@ -406,6 +431,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte source = Vec3(norm); break; } + float uvw[3]; Vec3ByMatrix43(uvw, &source.x, gstate.tgenMatrix); uv[0] = uvw[0]; @@ -433,6 +459,8 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte // will be moved to hardware transform anyway. Vec3ByMatrix43(v, out, gstate.viewMatrix); } + + // TODO: Write to a flexible buffer. memcpy(&transformed[index].x, v, 3 * sizeof(float)); memcpy(&transformed[index].uv, uv, 2 * sizeof(float)); memcpy(&transformed[index].color0, c0, 4 * sizeof(float)); diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 91f9aebf0f..fd94ecae31 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -85,7 +85,7 @@ DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { } void VertexDecoder::SetVertexType(u32 fmt) { - fmt = fmt; + fmt_ = fmt; throughmode = (fmt & GE_VTYPE_THROUGH) != 0; int biggest = 0; @@ -165,6 +165,8 @@ void VertexDecoder::SetVertexType(u32 fmt) { case GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S16_3; break; case GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_FLOAT_3; break; } + // Actually, temporarily let's not. + decFmt.nrmfmt = DEC_FLOAT_3; decFmt.nrmoff = decOff; decOff += DecFmtSize(decFmt.nrmfmt); } @@ -186,10 +188,13 @@ void VertexDecoder::SetVertexType(u32 fmt) { case GE_VTYPE_POS_16BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S16_3; break; case GE_VTYPE_POS_FLOAT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_FLOAT_3; break; } + // Actually, temporarily let's not. + decFmt.posfmt = DEC_FLOAT_3; } decFmt.posoff = decOff; decOff += DecFmtSize(decFmt.posfmt); } + decFmt.stride = decOff; size = align(size, biggest); onesize_ = size; @@ -197,14 +202,12 @@ void VertexDecoder::SetVertexType(u32 fmt) { DEBUG_LOG(G3D,"SVT : size = %i, aligned to biggest %i", size, biggest); } -void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const +void VertexDecoder::DecodeVerts(u8 *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const { // TODO: Remove if (morphcount == 1) gstate_c.morphWeights[0] = 1.0f; - char *ptr = (char *)verts; - // Find index bounds. Could cache this in display lists. int lowerBound = 0x7FFFFFFF; int upperBound = 0; @@ -234,10 +237,10 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const // Decode the vertices within the found bounds, once each (unlike the previous way..) for (int index = lowerBound; index <= upperBound; index++) { - ptr = (char*)verts + (index * size); + u8 *ptr = (u8*)verts + (index * size); // TODO: Should weights be morphed? - float *wt = decoded[index].weights; + float *wt = (float *)decoded; switch (weighttype) { case GE_VTYPE_WEIGHT_NONE >> 9: @@ -267,26 +270,28 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const } break; } + if (weighttype) + decoded += nweights * sizeof(float); // TODO: Not morphing UV yet - float *uv = decoded[index].uv; switch (tc) { case GE_VTYPE_TC_NONE: - uv[0] = 0.0f; - uv[1] = 0.0f; break; case GE_VTYPE_TC_8BIT: { + float *uv = (float *)decoded; const u8 *uvdata = (const u8*)(ptr + tcoff); for (int j = 0; j < 2; j++) uv[j] = (float)uvdata[j] / 128.0f; + decoded += 2 * sizeof(float); break; } case GE_VTYPE_TC_16BIT: { + float *uv = (float *)decoded; const u16 *uvdata = (const u16*)(ptr + tcoff); if (throughmode) { @@ -298,11 +303,13 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const uv[0] = (float)uvdata[0] / 32768.0f; uv[1] = (float)uvdata[1] / 32768.0f; } + decoded += 2 * sizeof(float); } break; case GE_VTYPE_TC_FLOAT: { + float *uv = (float *)decoded; const float *uvdata = (const float*)(ptr + tcoff); if (throughmode) { uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth); @@ -311,97 +318,103 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const uv[0] = uvdata[0]; uv[1] = uvdata[1]; } + decoded += 2 * sizeof(float); } break; } // TODO: Not morphing color yet - u8 *c = decoded[index].color; switch (col) { case GE_VTYPE_COL_4444 >> 2: { + u8 *c = decoded; u16 cdata = *(u16*)(ptr + coloff); for (int j = 0; j < 4; j++) c[j] = Convert4To8((cdata >> (j * 4)) & 0xF); + decoded += 4; } break; case GE_VTYPE_COL_565 >> 2: { + u8 *c = decoded; u16 cdata = *(u16*)(ptr + coloff); c[0] = Convert5To8(cdata & 0x1f); c[1] = Convert6To8((cdata>>5) & 0x3f); c[2] = Convert5To8((cdata>>11) & 0x1f); c[3] = 1.0f; + decoded += 4; } break; case GE_VTYPE_COL_5551 >> 2: { + u8 *c = decoded; u16 cdata = *(u16*)(ptr + coloff); c[0] = Convert5To8(cdata & 0x1f); c[1] = Convert5To8((cdata>>5) & 0x1f); c[2] = Convert5To8((cdata>>10) & 0x1f); c[3] = (cdata>>15) ? 255 : 0; + decoded += 4; } break; case GE_VTYPE_COL_8888 >> 2: { + u8 *c = decoded; // TODO: speedup u8 *cdata = (u8*)(ptr + coloff); for (int j = 0; j < 4; j++) c[j] = cdata[j]; + decoded += 4; } break; default: - c[0] = 255; - c[1] = 255; - c[2] = 255; - c[3] = 255; break; } - float *normal = decoded[index].normal; - memset(normal, 0, sizeof(float)*3); - for (int n = 0; n < morphcount; n++) - { - float multiplier = gstate_c.morphWeights[n]; - if (gstate.reversenormals & 0xFFFFFF) { - multiplier = -multiplier; - } - switch (nrm) + float *normal = (float *)decoded; + if (nrm) { + memset(normal, 0, sizeof(float)*3); + for (int n = 0; n < morphcount; n++) { - case GE_VTYPE_NRM_8BIT: - { - const s8 *sv = (const s8*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += (sv[j]/127.0f) * multiplier; + float multiplier = gstate_c.morphWeights[n]; + if (gstate.reversenormals & 0xFFFFFF) { + multiplier = -multiplier; } - break; + switch (nrm) + { + case GE_VTYPE_NRM_8BIT: + { + const s8 *sv = (const s8*)(ptr + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += (sv[j]/127.0f) * multiplier; + } + break; - case GE_VTYPE_NRM_FLOAT >> 5: - { - const float *fv = (const float*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += fv[j] * multiplier; - } - break; + case GE_VTYPE_NRM_FLOAT >> 5: + { + const float *fv = (const float*)(ptr + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += fv[j] * multiplier; + } + break; - case GE_VTYPE_NRM_16BIT >> 5: - { - const short *sv = (const short*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += (sv[j]/32767.0f) * multiplier; + case GE_VTYPE_NRM_16BIT >> 5: + { + const short *sv = (const short*)(ptr + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += (sv[j]/32767.0f) * multiplier; + } + break; } - break; } + decoded += 12; } - float *v = decoded[index].pos; - + float *v = (float *)decoded; if (morphcount == 1) { switch (pos) { @@ -475,6 +488,7 @@ void VertexDecoder::DecodeVerts(DecodedVertex *decoded, const void *verts, const } } } + decoded += 12; } } diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index fb02f42218..b2b3b2eee8 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -92,12 +92,12 @@ public: void SetVertexType(u32 vtype); const DecVtxFormat &GetDecVtxFmt() { return decFmt; } - void DecodeVerts(DecodedVertex *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const; + void DecodeVerts(u8 *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const; bool hasColor() const { return col != 0; } int VertexSize() const { return size; } private: - u32 fmt; + u32 fmt_; DecVtxFormat decFmt; bool throughmode; @@ -121,16 +121,17 @@ private: int nweights; }; - // Reads decoded vertex formats in a convenient way. For software transform and debugging. class VertexReader { public: - VertexReader(u8 *data, const DecVtxFormat &decFmt) : data_(data), decFmt_(decFmt) {} + VertexReader(u8 *base, const DecVtxFormat &decFmt) : base_(base), data_(base), decFmt_(decFmt) {} void ReadPos(float pos[3]) { switch (decFmt_.posfmt) { - case DEC_FLOAT_3: memcpy(pos, data_ + decFmt_.posoff, 12); break; + case DEC_FLOAT_3: + memcpy(pos, data_ + decFmt_.posoff, 12); + break; case DEC_S16_3: { s16 *p = (s16 *)(data_ + decFmt_.posoff); @@ -149,8 +150,10 @@ public: } void ReadNrm(float nrm[3]) { - switch (decFmt_.nrmoff) { - case DEC_FLOAT_3: memcpy(nrm, data_ + decFmt_.nrmoff, 12); break; + switch (decFmt_.nrmfmt) { + case DEC_FLOAT_3: + memcpy(nrm, data_ + decFmt_.nrmoff, 12); + break; case DEC_S16_3: { s16 *p = (s16 *)(data_ + decFmt_.nrmoff); @@ -171,7 +174,7 @@ public: void ReadUV(float uv[2]) { switch (decFmt_.uvfmt) { case DEC_FLOAT_2: - memcpy(uv, data_ + decFmt_.nrmoff, 8); break; + memcpy(uv, data_ + decFmt_.uvoff, 8); break; } } @@ -218,11 +221,16 @@ public: } } - void Next() { - data_ += decFmt_.stride; + bool hasColor0() const { return decFmt_.c0fmt != 0; } + bool hasNormal() const { return decFmt_.nrmfmt != 0; } + bool hasUV() const { return decFmt_.uvfmt != 0; } + + void Goto(int index) { + data_ = base_ + index * decFmt_.stride; } private: + u8 *base_; u8 *data_; DecVtxFormat decFmt_; int vtype_; From fede297f304311ff9617c323d0d085a7010bebe5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 21:21:46 +0100 Subject: [PATCH 024/276] Fix sceIoGetStat, memstick capacity check --- Core/HLE/sceIo.cpp | 61 ++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index d25d07983d..aa6e540c74 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -245,13 +245,16 @@ void __IoGetStat(SceIoStat *stat, PSPFileInfo &info) { u32 sceIoGetstat(const char *filename, u32 addr) { SceIoStat stat; PSPFileInfo info = pspFileSystem.GetFileInfo(filename); - __IoGetStat(&stat, info); - Memory::WriteStruct(addr, &stat); - - DEBUG_LOG(HLE, "sceIoGetstat(%s, %08x) : sector = %08x", filename, addr, + if (info.exists) { + __IoGetStat(&stat, info); + Memory::WriteStruct(addr, &stat); + DEBUG_LOG(HLE, "sceIoGetstat(%s, %08x) : sector = %08x", filename, addr, info.startSector); - - return 0; + return 0; + } else { + DEBUG_LOG(HLE, "sceIoGetstat(%s, %08x) : FILE NOT FOUND", filename, addr); + return SCE_KERNEL_ERROR_NOFILE; + } } //Not sure about wrapping it or not, since the log seems to take the address of the data var @@ -428,11 +431,11 @@ void sceIoSync() { } struct DeviceSize { + u32 maxClusters; + u32 freeClusters; u32 maxSectors; u32 sectorSize; - u32 sectorsPerCluster; - u32 totalClusters; - u32 freeClusters; + u32 sectorCount; }; u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, int outLen) { @@ -512,20 +515,23 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, case 0x02425818: // Get memstick size etc // Pretend we have a 2GB memory stick. - if (Memory::IsValidAddress(argAddr)) { // "Should" be outPtr but isn't + if (Memory::IsValidAddress(argAddr) && argLen >= 4) { // "Should" be outPtr but isn't u32 pointer = Memory::Read_U32(argAddr); - - u64 totalSize = (u32)2 * 1024 * 1024 * 1024; - u64 freeSize = 1 * 1024 * 1024 * 1024; + u32 sectorSize = 0x200; + u32 memStickSectorSize = 32 * 1024; + u32 sectorCount = memStickSectorSize / sectorSize; + u64 freeSize = 1 * 1024 * 1024 * 1024; DeviceSize deviceSize; - deviceSize.maxSectors = 512; - deviceSize.sectorSize = 0x200; - deviceSize.sectorsPerCluster = 0x08; - deviceSize.totalClusters = (u32)((totalSize * 95 / 100) / (deviceSize.sectorSize * deviceSize.sectorsPerCluster)); - deviceSize.freeClusters = (u32)((freeSize * 95 / 100) / (deviceSize.sectorSize * deviceSize.sectorsPerCluster)); + deviceSize.maxClusters = (freeSize * 95 / 100) / (sectorSize * sectorCount); + deviceSize.freeClusters = deviceSize.maxClusters; + deviceSize.maxSectors = deviceSize.maxClusters; + deviceSize.sectorSize = sectorSize; + deviceSize.sectorCount = sectorCount; Memory::WriteStruct(pointer, &deviceSize); + DEBUG_LOG(HLE, "Returned memstick size: maxSectors=%i", deviceSize.maxSectors); return 0; } else { + ERROR_LOG(HLE, "memstick size query: bad params"); return ERROR_MEMSTICK_DEVCTL_BAD_PARAMS; } } @@ -580,17 +586,18 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, case 0x02425818: // Get memstick size etc // Pretend we have a 2GB memory stick. { - if (Memory::IsValidAddress(argAddr)) { // "Should" be outPtr but isn't + if (Memory::IsValidAddress(argAddr) && argLen >= 4) { // NOTE: not outPtr u32 pointer = Memory::Read_U32(argAddr); - - u64 totalSize = (u32)2 * 1024 * 1024 * 1024; - u64 freeSize = 1 * 1024 * 1024 * 1024; + u32 sectorSize = 0x200; + u32 memStickSectorSize = 32 * 1024; + u32 sectorCount = memStickSectorSize / sectorSize; + u64 freeSize = 1 * 1024 * 1024 * 1024; DeviceSize deviceSize; - deviceSize.maxSectors = 512; - deviceSize.sectorSize = 0x200; - deviceSize.sectorsPerCluster = 0x08; - deviceSize.totalClusters = (u32)((totalSize * 95 / 100) / (deviceSize.sectorSize * deviceSize.sectorsPerCluster)); - deviceSize.freeClusters = (u32)((freeSize * 95 / 100) / (deviceSize.sectorSize * deviceSize.sectorsPerCluster)); + deviceSize.maxClusters = (freeSize * 95 / 100) / (sectorSize * sectorCount); + deviceSize.freeClusters = deviceSize.maxClusters; + deviceSize.maxSectors = deviceSize.maxClusters; + deviceSize.sectorSize = sectorSize; + deviceSize.sectorCount = sectorCount; Memory::WriteStruct(pointer, &deviceSize); return 0; } else { From fa7de38ccf4c2bafeb7f23e58d483fb2fafa2004 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 21:23:52 +0100 Subject: [PATCH 025/276] PSPSaveDialog: Style/warning fixes. Add a way to return errors (unused). --- Core/Dialog/PSPSaveDialog.cpp | 32 +++++----- Core/Dialog/PSPSaveDialog.h | 2 +- Core/Dialog/SavedataParam.cpp | 117 +++++++++++++++++----------------- Core/Dialog/SavedataParam.h | 5 +- Core/HLE/sceUtility.cpp | 4 +- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index f94940c40d..3185a43a0b 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -31,19 +31,17 @@ PSPSaveDialog::PSPSaveDialog() PSPSaveDialog::~PSPSaveDialog() { } -void PSPSaveDialog::Init(int paramAddr) +u32 PSPSaveDialog::Init(int paramAddr) { // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { - return; + return 0; } - param.SetPspParam((SceUtilitySavedataParam*)Memory::GetPointer(paramAddr)); - - DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); + u32 retval = param.SetPspParam((SceUtilitySavedataParam*)Memory::GetPointer(paramAddr)); DEBUG_LOG(HLE,"Mode: %i", param.GetPspParam()->mode); - switch(param.GetPspParam()->mode) + switch (param.GetPspParam()->mode) { case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD: case SCE_UTILITY_SAVEDATA_TYPE_LOAD: @@ -85,12 +83,12 @@ void PSPSaveDialog::Init(int paramAddr) ERROR_LOG(HLE, "Load/Save function %d not coded. Title: %s Save: %s File: %s", param.GetPspParam()->mode, param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str()); param.GetPspParam()->result = 0; display = DS_NONE; - return; // Return 0 should allow the game to continue, but missing function must be implemented and returning the right value or the game can block. + return 0; // Return 0 should allow the game to continue, but missing function must be implemented and returning the right value or the game can block. } break; } - status = SCE_UTILITY_STATUS_INITIALIZE; + status = (int)retval < 0 ? SCE_UTILITY_STATUS_SHUTDOWN : SCE_UTILITY_STATUS_INITIALIZE; currentSelectedSave = 0; lastButtons = __CtrlPeekButtons(); @@ -126,7 +124,7 @@ void PSPSaveDialog::Init(int paramAddr) INFO_LOG(HLE,"snd0 data : %08x",*((unsigned int*)¶m.GetPspParam()->snd0FileData.buf)); INFO_LOG(HLE,"snd0 size : %u",param.GetPspParam()->snd0FileData.bufSize);*/ - + return retval; } void PSPSaveDialog::DisplaySaveList(bool canMove) @@ -142,16 +140,16 @@ void PSPSaveDialog::DisplaySaveList(bool canMove) } // Calc save image position on screen - int w = 150; - int h = 80; - int x = 20; + float w = 150; + float h = 80; + float x = 20; if(displayCount != currentSelectedSave) { w = 80; h = 40; x = 50; } - int y = 80; + float y = 80; if(displayCount < currentSelectedSave) y -= 50 * (currentSelectedSave - displayCount); else if(displayCount > currentSelectedSave) @@ -199,10 +197,10 @@ void PSPSaveDialog::DisplaySaveIcon() } // Calc save image position on screen - int w = 150; - int h = 80; - int x = 20; - int y = 80; + float w = 150; + float h = 80; + float x = 20; + float y = 80; int tw = 256; int th = 256; diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index b5b5c55d86..3c00817280 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -62,7 +62,7 @@ public: PSPSaveDialog(); virtual ~PSPSaveDialog(); - virtual void Init(int paramAddr); + virtual u32 Init(int paramAddr); virtual void Update(); void Shutdown(); diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 1fa24aa874..e510f28026 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -20,6 +20,7 @@ #include "image/png_load.h" #include "../HLE/sceKernelMemory.h" #include "../ELF/ParamSFO.h" +#include "PSPSaveDialog.h" std::string icon0Name = "ICON0.PNG"; std::string icon1Name = "ICON1.PMF"; @@ -41,7 +42,7 @@ SavedataParam::SavedataParam() void SavedataParam::Init() { - if(!pspFileSystem.GetFileInfo(savePath).exists) + if (!pspFileSystem.GetFileInfo(savePath).exists) { pspFileSystem.MkDir(savePath); } @@ -54,7 +55,7 @@ std::string SavedataParam::GetSaveDir(SceUtilitySavedataParam* param, int saveId } std::string dirPath = GetGameName(param)+GetSaveName(param); - if(saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it + if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it dirPath = std::string(GetGameName(param))+GetFilename(saveId); return dirPath; @@ -101,9 +102,9 @@ bool SavedataParam::Delete(SceUtilitySavedataParam* param, int saveId) } std::string dirPath = GetSaveFilePath(param,saveId); - if(saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it + if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it { - if(saveDataList[saveId].size == 0) // don't delete no existing file + if (saveDataList[saveId].size == 0) // don't delete no existing file { return false; } @@ -119,22 +120,22 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) return false; } - u8* data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); + u8 *data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); std::string dirPath = GetSaveFilePath(param, saveId); - if(!pspFileSystem.GetFileInfo(dirPath).exists) + if (!pspFileSystem.GetFileInfo(dirPath).exists) pspFileSystem.MkDir(dirPath); std::string filePath = dirPath+"/"+GetFileName(param); INFO_LOG(HLE,"Saving file with size %u in %s",param->dataBufSize,filePath.c_str()); unsigned int handle = pspFileSystem.OpenFile(filePath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle == 0) + if (handle == 0) { ERROR_LOG(HLE,"Error opening file %s",filePath.c_str()); return false; } - if(!pspFileSystem.WriteFile(handle, data_, param->dataBufSize)) + if (!pspFileSystem.WriteFile(handle, data_, param->dataBufSize)) { pspFileSystem.CloseFile(handle); ERROR_LOG(HLE,"Error writing file %s",filePath.c_str()); @@ -154,12 +155,12 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); sfoFile.SetValue("SAVEDATA_FILE_LIST","",3168); // This need to be filed with the save filename and a hash sfoFile.SetValue("SAVEDATA_PARAMS","",128); // This need to be filled with a hash of the save file encrypted. - u8* sfoData; + u8 *sfoData; size_t sfoSize; sfoFile.WriteSFO(&sfoData,&sfoSize); std::string sfopath = dirPath+"/"+sfoName; handle = pspFileSystem.OpenFile(sfopath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle) + if (handle) { pspFileSystem.WriteFile(handle, sfoData, sfoSize); pspFileSystem.CloseFile(handle); @@ -167,36 +168,36 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) delete[] sfoData; // SAVE ICON0 - if(param->icon0FileData.buf) + if (param->icon0FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon0FileData.buf)); std::string icon0path = dirPath+"/"+icon0Name; handle = pspFileSystem.OpenFile(icon0path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle) + if (handle) { pspFileSystem.WriteFile(handle, data_, param->icon0FileData.bufSize); pspFileSystem.CloseFile(handle); } } // SAVE ICON1 - if(param->icon1FileData.buf) + if (param->icon1FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon1FileData.buf)); std::string icon1path = dirPath+"/"+icon1Name; handle = pspFileSystem.OpenFile(icon1path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle) + if (handle) { pspFileSystem.WriteFile(handle, data_, param->icon1FileData.bufSize); pspFileSystem.CloseFile(handle); } } // SAVE PIC1 - if(param->pic1FileData.buf) + if (param->pic1FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->pic1FileData.buf)); std::string pic1path = dirPath+"/"+pic1Name; handle = pspFileSystem.OpenFile(pic1path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle) + if (handle) { pspFileSystem.WriteFile(handle, data_, param->pic1FileData.bufSize); pspFileSystem.CloseFile(handle); @@ -204,12 +205,12 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) } // Save SND - if(param->snd0FileData.buf) + if (param->snd0FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->snd0FileData.buf)); std::string snd0path = dirPath+"/"+snd0Name; handle = pspFileSystem.OpenFile(snd0path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if(handle) + if (handle) { pspFileSystem.WriteFile(handle, data_, param->snd0FileData.bufSize); pspFileSystem.CloseFile(handle); @@ -219,18 +220,18 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) return true; } -bool SavedataParam::Load(SceUtilitySavedataParam* param, int saveId) +bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) { if (!param) { return false; } - u8* data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); + u8 *data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); std::string dirPath = GetSaveFilePath(param, saveId); - if(saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it + if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it { - if(saveDataList[saveId].size == 0) // don't read no existing file + if (saveDataList[saveId].size == 0) // don't read no existing file { return false; } @@ -239,12 +240,12 @@ bool SavedataParam::Load(SceUtilitySavedataParam* param, int saveId) std::string filePath = dirPath+"/"+GetFileName(param); INFO_LOG(HLE,"Loading file with size %u in %s",param->dataBufSize,filePath.c_str()); u32 handle = pspFileSystem.OpenFile(filePath,FILEACCESS_READ); - if(!handle) + if (!handle) { ERROR_LOG(HLE,"Error opening file %s",filePath.c_str()); return false; } - if(!pspFileSystem.ReadFile(handle, data_, param->dataBufSize)) + if (!pspFileSystem.ReadFile(handle, data_, param->dataBufSize)) { pspFileSystem.CloseFile(handle); ERROR_LOG(HLE,"Error reading file %s",filePath.c_str()); @@ -254,20 +255,20 @@ bool SavedataParam::Load(SceUtilitySavedataParam* param, int saveId) return true; } -bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) +bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) { if (!param) { return false; } - if(Memory::IsValidAddress(param->msFree)) + if (Memory::IsValidAddress(param->msFree)) { Memory::Write_U32(32768,param->msFree); Memory::Write_U32(32768,param->msFree+4); Memory::Write_U32(1048576,param->msFree+8); Memory::Write_U8(0,param->msFree+12); } - if(Memory::IsValidAddress(param->msData)) + if (Memory::IsValidAddress(param->msData)) { Memory::Write_U32(0,param->msData+36); Memory::Write_U32(0,param->msData+40); @@ -275,7 +276,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) Memory::Write_U32(0,param->msData+52); Memory::Write_U8(0,param->msData+56); } - if(Memory::IsValidAddress(param->utilityData)) + if (Memory::IsValidAddress(param->utilityData)) { Memory::Write_U32(13,param->utilityData); Memory::Write_U32(416,param->utilityData+4); @@ -287,13 +288,13 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) } -bool SavedataParam::GetList(SceUtilitySavedataParam* param) +bool SavedataParam::GetList(SceUtilitySavedataParam *param) { if (!param) { return false; } - if(Memory::IsValidAddress(param->idListAddr)) + if (Memory::IsValidAddress(param->idListAddr)) { Memory::Write_U32(0,param->idListAddr+4); } @@ -302,11 +303,11 @@ bool SavedataParam::GetList(SceUtilitySavedataParam* param) void SavedataParam::Clear() { - if(saveDataList) + if (saveDataList) { - for(int i = 0; i < saveNameListDataCount; i++) + for (int i = 0; i < saveNameListDataCount; i++) { - if(saveDataList[i].textureData != 0) + if (saveDataList[i].textureData != 0) kernelMemory.Free(saveDataList[i].textureData); saveDataList[i].textureData = 0; } @@ -316,23 +317,23 @@ void SavedataParam::Clear() } } -void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) +u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) { pspParam = param; - if(!pspParam) + if (!pspParam) { Clear(); - return; + return 0; } bool listEmptyFile = true; - if(param->mode == SCE_UTILITY_SAVEDATA_TYPE_LISTLOAD || + if (param->mode == SCE_UTILITY_SAVEDATA_TYPE_LISTLOAD || param->mode == SCE_UTILITY_SAVEDATA_TYPE_LISTDELETE) { listEmptyFile = false; } - if(param->saveNameList != 0) + if (param->saveNameList != 0) { saveNameListData = (char(*)[20])Memory::GetPointer(param->saveNameList); @@ -348,13 +349,13 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) // get and stock file info for each file int realCount = 0; - for(int i = 0; i fileName; PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); - if(info.exists) + if (info.exists) { saveDataList[realCount].size = info.size; saveDataList[realCount].saveName = saveNameListData[i]; @@ -365,15 +366,15 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound std::string fileDataPath2 = savePath+GetGameName(param)+saveNameListData[i]+"/"+icon0Name; PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if(info2.exists) + if (info2.exists) { - u8* textureDataPNG = new u8[info2.size]; + u8 *textureDataPNG = new u8[(size_t)info2.size]; int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); pspFileSystem.CloseFile(handle); unsigned char* textureData; int w,h; - pngLoadPtr(textureDataPNG, info2.size, &w, &h, &textureData, false); + pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); delete[] textureDataPNG; u32 texSize = w*h*4; u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); @@ -391,14 +392,14 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) // Load info in PARAM.SFO fileDataPath2 = savePath+GetGameName(param)+saveNameListData[i]+"/"+sfoName; info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if(info2.exists) + if (info2.exists) { - u8* sfoParam = new u8[info2.size]; + u8 *sfoParam = new u8[(size_t)info2.size]; int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); pspFileSystem.ReadFile(handle,sfoParam,info2.size); pspFileSystem.CloseFile(handle); ParamSFOData sfoFile; - if(sfoFile.ReadSFO(sfoParam,info2.size)) + if (sfoFile.ReadSFO(sfoParam, (size_t)info2.size)) { std::string title = sfoFile.GetValueString("TITLE"); memcpy(saveDataList[realCount].title,title.c_str(),title.size()); @@ -420,7 +421,7 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) } else { - if(listEmptyFile) + if (listEmptyFile) { saveDataList[realCount].size = 0; saveDataList[realCount].saveName = saveNameListData[i]; @@ -445,7 +446,7 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) std::string fileDataPath = savePath+GetGameName(param)+GetSaveName(param)+"/"+param->fileName; PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); - if(info.exists) + if (info.exists) { saveDataList[0].size = info.size; saveDataList[0].saveName = GetSaveName(param); @@ -456,15 +457,15 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound std::string fileDataPath2 = savePath+GetGameName(param)+GetSaveName(param)+"/"+icon0Name; PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if(info2.exists) + if (info2.exists) { - u8* textureDataPNG = new u8[info2.size]; + u8 *textureDataPNG = new u8[(size_t)info2.size]; int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); pspFileSystem.CloseFile(handle); - unsigned char* textureData; + unsigned char *textureData; int w,h; - pngLoadPtr(textureDataPNG, info2.size, &w, &h, &textureData, false); + pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); delete[] textureDataPNG; u32 texSize = w*h*4; u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); @@ -482,14 +483,14 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) // Load info in PARAM.SFO fileDataPath2 = savePath+GetGameName(param)+GetSaveName(param)+"/"+sfoName; info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if(info2.exists) + if (info2.exists) { - u8* sfoParam = new u8[info2.size]; + u8 *sfoParam = new u8[(size_t)info2.size]; int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); pspFileSystem.ReadFile(handle,sfoParam,info2.size); pspFileSystem.CloseFile(handle); ParamSFOData sfoFile; - if(sfoFile.ReadSFO(sfoParam,info2.size)) + if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) { std::string title = sfoFile.GetValueString("TITLE"); memcpy(saveDataList[0].title,title.c_str(),title.size()); @@ -511,7 +512,7 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) } else { - if(listEmptyFile) + if (listEmptyFile) { saveDataList[0].size = 0; saveDataList[0].saveName = GetSaveName(param); @@ -520,8 +521,10 @@ void SavedataParam::SetPspParam(SceUtilitySavedataParam* param) DEBUG_LOG(HLE,"Don't Exist"); } saveNameListDataCount = 0; + return 0; } } + return 0; } SceUtilitySavedataParam* SavedataParam::GetPspParam() @@ -547,8 +550,8 @@ int SavedataParam::GetSelectedSave() { return selectedSave; } + void SavedataParam::SetSelectedSave(int idx) { selectedSave = idx; } - diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 23c77e28ad..8295c44df1 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -118,9 +118,10 @@ struct SceUtilitySavedataParam }; +// Non native, this one we can reorganize as we like struct SaveFileInfo { - int size; + s64 size; std::string saveName; int idx; @@ -153,7 +154,7 @@ public: SavedataParam(); - void SetPspParam(SceUtilitySavedataParam* param); + u32 SetPspParam(SceUtilitySavedataParam* param); SceUtilitySavedataParam* GetPspParam(); int GetFilenameCount(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index f87baa8dae..3155748cf3 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -41,8 +41,8 @@ void __UtilityInit() int sceUtilitySavedataInitStart(u32 paramAddr) { - saveDialog.Init(paramAddr); - return 0; + DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); + return (u32)saveDialog.Init(paramAddr); } int sceUtilitySavedataShutdownStart() From 56fa601d244affb3275aa240816eb64a6e06d4d9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 22:27:26 -0800 Subject: [PATCH 026/276] Add include for tolower(), made Android unhappy. --- Core/FileSystems/ISOFileSystem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 11c8e88954..2964d8e684 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -20,6 +20,7 @@ #include "ISOFileSystem.h" #include #include +#include const int sectorSize = 2048; From 1f83fc4e9cc166264949b7d5d39f0bc83943579e Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 20 Dec 2012 21:11:21 +0800 Subject: [PATCH 027/276] Implement Vdet --- Core/MIPS/MIPSIntVFPU.cpp | 21 ++++++++++++++++++++- Core/MIPS/MIPSIntVFPU.h | 1 + Core/MIPS/MIPSTables.cpp | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index b3045b9a4b..27d0fe5e50 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -906,7 +906,26 @@ namespace MIPSInt PC += 4; EatPrefixes(); } - + + void Int_Vdet(u32 op) + { + float s[4], t[4]; + float d[4]; + int vd = _VD; + int vs = _VS; + int vt = _VT; + VectorSize sz = GetVecSize(op); + if (sz != V_Pair) + _dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted"); + ReadVector(s, sz, vs); + ReadVector(t, sz, vt); + d[0] = s[0] * t[1] - s[1] * t[0]; + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + void Int_Vfad(u32 op) { float s[4]; diff --git a/Core/MIPS/MIPSIntVFPU.h b/Core/MIPS/MIPSIntVFPU.h index 50e7229366..c75b1ac183 100644 --- a/Core/MIPS/MIPSIntVFPU.h +++ b/Core/MIPS/MIPSIntVFPU.h @@ -50,6 +50,7 @@ namespace MIPSInt void Int_Vcmp(u32 op); void Int_Vminmax(u32 op); void Int_Vcrs(u32 op); + void Int_Vdet(u32 op); void Int_Vcmov(u32 op); void Int_CrossQuat(u32 op); void Int_VPFX(u32 op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 67d9b70e92..c8fffe8205 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -495,7 +495,7 @@ MIPSInstruction tableVFPU1[8] = INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), {-2}, INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU), - INSTR("vdet",&Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), + INSTR("vdet",&Jit::Comp_Generic, Dis_Generic, Int_Vdet, IS_VFPU), {-2}, }; From aeafc92d3b0a69d4bc7f8f33c4d73b151bff40d2 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 20 Dec 2012 05:33:05 -0800 Subject: [PATCH 028/276] paths with a colon are never relative --- Core/FileSystems/MetaFileSystem.cpp | 78 ++++++++--------------------- 1 file changed, 22 insertions(+), 56 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 6dae780398..c3c1eef198 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -61,6 +61,7 @@ static bool ApplyPathStringToComponentsVector(std::vector &vector, /* * Changes relative paths to absolute, removes ".", "..", and trailing "/" + * "drive:./blah" is absolute (ignore the dot) and "/blah" is relative (because it's missing "drive:") * babel (and possibly other games) use "/directoryThatDoesNotExist/../directoryThatExists/filename" */ static bool RealPath(const std::string ¤tDirectory, const std::string &inPath, std::string &outPath) @@ -81,70 +82,27 @@ static bool RealPath(const std::string ¤tDirectory, const std::string &inP return true; } - std::string curDirPrefix; - size_t curDirColon = std::string::npos, curDirLen = currentDirectory.length(); - if (curDirLen != 0) - { - curDirColon = currentDirectory.find(':'); - - if (curDirColon == std::string::npos) - { - DEBUG_LOG(HLE, "RealPath: currentDirectory has no prefix: \"%s\"", currentDirectory.c_str()); - } - else - { - if (curDirColon + 1 == curDirLen) - DEBUG_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); - - curDirPrefix = currentDirectory.substr(0, curDirColon + 1); - } - } - - std::string inPrefix, inAfter; - - if (inColon == std::string::npos) - { - inPrefix = curDirPrefix; - inAfter = inPath; - } - else - { - inPrefix = inPath.substr(0, inColon + 1); - inAfter = inPath.substr(inColon + 1); - } - + bool relative = (inColon == std::string::npos); + + std::string prefix, inAfterColon; std::vector cmpnts; // path components - size_t capacityGuess = inPath.length(); + size_t outPathCapacityGuess = 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); - - // Apparently it's okay for relative paths to start with '/'. - // For example, kahoots does sceIoChdir(disc0:/PSP_GAME/USRDIR/) - // then opens paths like "/images/gui". Support this. - if (inColon == std::string::npos && inAfter[0] == '/') - inAfter = inAfter.substr(1); - - if (inAfter[0] != '/') + if (relative) { + size_t curDirLen = currentDirectory.length(); if (curDirLen == 0) { ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory is empty", inPath.c_str()); return false; } - if (curDirColon == std::string::npos || curDirPrefix.length() == 0) + size_t curDirColon = currentDirectory.find(':'); + if (curDirColon == std::string::npos) { ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" has no prefix", inPath.c_str(), currentDirectory.c_str()); return false; } - - if (inPrefix != curDirPrefix) - WARN_LOG(HLE, "RealPath: inPath \"%s\" is relative, but specifies a different prefix than current directory \"%s\"", inPath.c_str(), currentDirectory.c_str()); - if (curDirColon + 1 == curDirLen) { ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" is all prefix and no path. Using \"/\" as path for current directory.", inPath.c_str(), currentDirectory.c_str()); @@ -157,21 +115,29 @@ static bool RealPath(const std::string ¤tDirectory, const std::string &inP ERROR_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); return false; } + + outPathCapacityGuess += curDirLen; } - capacityGuess += currentDirectory.length(); + prefix = currentDirectory.substr(0, curDirColon + 1); + inAfterColon = inPath; + } + else + { + prefix = inPath.substr(0, inColon + 1); + inAfterColon = inPath.substr(inColon + 1); } - if (! ApplyPathStringToComponentsVector(cmpnts, inAfter) ) + if (! ApplyPathStringToComponentsVector(cmpnts, inAfterColon) ) { - DEBUG_LOG(HLE, "RealPath: inPath is not a valid path: \"%s\"", inPath.c_str()); + WARN_LOG(HLE, "RealPath: inPath is not a valid path: \"%s\"", inPath.c_str()); return false; } outPath.clear(); - outPath.reserve(capacityGuess); + outPath.reserve(outPathCapacityGuess); - outPath.append(inPrefix); + outPath.append(prefix); size_t numCmpnts = cmpnts.size(); for (size_t i = 0; i < numCmpnts; i++) From 936d80b21464c37bc932b4f2db011aaa1ea8d4d7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 20 Dec 2012 21:39:10 +0800 Subject: [PATCH 029/276] Implement Vscmp --- Core/MIPS/MIPSIntVFPU.cpp | 27 ++++++++++++++++++++++++++- Core/MIPS/MIPSIntVFPU.h | 1 + Core/MIPS/MIPSTables.cpp | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index b3045b9a4b..1cb7fc4167 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1321,7 +1321,32 @@ namespace MIPSInt PC += 4; EatPrefixes(); } - + + void Int_Vscmp(u32 op) { + int vt = _VT; + int vs = _VS; + int vd = _VD; + VectorSize sz = GetVecSize(op); + float s[4]; + float t[4]; + float d[4]; + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + ReadVector(t, sz, vt); + ApplySwizzleT(t, sz); + int n = GetNumVectorElements(sz); + for (int i = 0; i < n ; i++) { + int a=s[i] - t[i]; + if (a > 0) d[i]=1; + else if (a < 0) d[i]=-1; + else d[i]=0; + } + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + void Int_Vsge(u32 op) { int vt = _VT; int vs = _VS; diff --git a/Core/MIPS/MIPSIntVFPU.h b/Core/MIPS/MIPSIntVFPU.h index 50e7229366..73165eb2fe 100644 --- a/Core/MIPS/MIPSIntVFPU.h +++ b/Core/MIPS/MIPSIntVFPU.h @@ -49,6 +49,7 @@ namespace MIPSInt void Int_Vidt(u32 op); void Int_Vcmp(u32 op); void Int_Vminmax(u32 op); + void Int_Vscmp(u32 op); void Int_Vcrs(u32 op); void Int_Vcmov(u32 op); void Int_CrossQuat(u32 op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 67d9b70e92..c73bceaf07 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -506,7 +506,7 @@ MIPSInstruction tableVFPU3[8] = //011011 xxx INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU), INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU), {-2}, - INSTR("vscmp",&Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), + INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU), INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU), INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU), }; From c4ca9b595636aab10b113d3b7bd3d7b9fe6d4d57 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Dec 2012 21:29:02 +0100 Subject: [PATCH 030/276] Get rid of the DecodedVertex struct. --- GPU/GLES/VertexDecoder.cpp | 32 ++++++++++++++++++++++++++------ GPU/GLES/VertexDecoder.h | 16 +++------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index fd94ecae31..4cfc4a321a 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -22,12 +22,32 @@ #include "VertexDecoder.h" -void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype) { - if (vtype & GE_VTYPE_NRM_MASK) printf("N: %f %f %f\n", vtx.normal[0], vtx.normal[1], vtx.normal[2]); - if (vtype & GE_VTYPE_TC_MASK) printf("TC: %f %f\n", vtx.uv[0], vtx.uv[1]); - if (vtype & GE_VTYPE_COL_MASK) printf("C: %02x %02x %02x %02x\n", vtx.color[0], vtx.color[1], vtx.color[2], vtx.color[3]); - if (vtype & GE_VTYPE_WEIGHT_MASK) printf("W: TODO\n"); - printf("P: %f %f %f\n", vtx.pos[0], vtx.pos[1], vtx.pos[2]); +void PrintDecodedVertex(VertexReader &vtx) { + if (vtx.hasNormal()) + { + float nrm[3]; + vtx.ReadNrm(nrm); + printf("N: %f %f %f\n", nrm[0], nrm[1], nrm[2]); + } + if (vtx.hasUV()) { + float uv[2]; + vtx.ReadUV(uv); + printf("TC: %f %f\n", uv[0], uv[1]); + } + if (vtx.hasColor0()) { + float col0[4]; + vtx.ReadColor0(col0); + printf("C0: %f %f %f %f\n", col0[0], col0[1], col0[2], col0[3]); + } + if (vtx.hasColor0()) { + float col1[3]; + vtx.ReadColor1(col1); + printf("C1: %f %f %f\n", col1[0], col1[1], col1[2]); + } + // Etc.. + float pos[3]; + vtx.ReadPos(pos); + printf("P: %f %f %f\n", pos[0], pos[1], pos[2]); } const int tcsize[4] = {0,2,4,8}, tcalign[4] = {0,1,2,4}; diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index b2b3b2eee8..72048d9bcf 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -50,16 +50,6 @@ struct DecVtxFormat { short stride; }; -// This is going away soon enough. -struct DecodedVertex -{ - float pos[3]; // in case of morph, preblend during decode - float normal[3]; // in case of morph, preblend during decode - float uv[2]; // scaled by uscale, vscale, if there - u8 color[4]; // unlit - float weights[8]; // ugh, expensive -}; - // This struct too. struct TransformedVertex { @@ -192,12 +182,12 @@ public: } } - void ReadColor1(float color[4]) { + void ReadColor1(float color[3]) { switch (decFmt_.c1fmt) { case DEC_U8_4: { u8 *p = (u8 *)(data_ + decFmt_.c1off); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 3; i++) color[i] = p[i] / 255.0f; } break; @@ -237,6 +227,6 @@ private: }; // Debugging utilities -void PrintDecodedVertex(const DecodedVertex &vtx, u32 vtype); +void PrintDecodedVertex(VertexReader &vtx); From 1b5407f505d27b0e3f6f3fb835f91ac874b0e97e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 00:48:57 +0100 Subject: [PATCH 031/276] Rewrite the vertex decoder a bit. Turn on SSE2 compiler flag etc. --- Core/Core.vcxproj | 3 + GPU/GLES/VertexDecoder.cpp | 713 +++++++++++++++++++++++------------- GPU/GLES/VertexDecoder.h | 58 ++- GPU/GPU.vcxproj | 7 +- ext/libkirk/libkirk.vcxproj | 3 + ext/zlib/zlib.vcxproj | 2 + headless/Headless.vcxproj | 3 + 7 files changed, 530 insertions(+), 259 deletions(-) diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index e7c9e19328..f10562449e 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -91,6 +91,9 @@ true true ../common;..;../native;../native/ext/glew;../ext/zlib + false + StreamingSIMDExtensions2 + Fast true diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 4cfc4a321a..fee736172c 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -104,9 +104,446 @@ DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { return tfm; } +void VertexDecoder::Step_WeightsU8() const +{ + float *wt = (float *)decoded_; + const u8 *wdata = (const u8*)(ptr_); + for (int j = 0; j < nweights; j++) + wt[j] = (float)wdata[j] / 128.0f; + decoded_ += nweights * sizeof(float); +} + +void VertexDecoder::Step_WeightsU16() const +{ + float *wt = (float *)decoded_; + const u16 *wdata = (const u16*)(ptr_); + for (int j = 0; j < nweights; j++) + wt[j] = (float)wdata[j] / 32768.0f; + decoded_ += nweights * sizeof(float); +} + +void VertexDecoder::Step_WeightsFloat() const +{ + float *wt = (float *)decoded_; + const float *wdata = (const float*)(ptr_); + for (int j = 0; j < nweights; j++) + wt[j] = wdata[j]; + decoded_ += nweights * sizeof(float); +} + +void VertexDecoder::Step_TcU8() const +{ + float *uv = (float *)decoded_; + const u8 *uvdata = (const u8*)(ptr_ + tcoff); + for (int j = 0; j < 2; j++) + uv[j] = (float)uvdata[j] / 128.0f; + decoded_ += 2 * sizeof(float); +} + +void VertexDecoder::Step_TcU16() const +{ + float *uv = (float *)decoded_; + const u16 *uvdata = (const u16*)(ptr_ + tcoff); + uv[0] = (float)uvdata[0] / 32768.0f; + uv[1] = (float)uvdata[1] / 32768.0f; + decoded_ += 2 * sizeof(float); +} + +void VertexDecoder::Step_TcU16Through() const +{ + float *uv = (float *)decoded_; + const u16 *uvdata = (const u16*)(ptr_ + tcoff); + uv[0] = (float)uvdata[0] / (float)(gstate_c.curTextureWidth); + uv[1] = (float)uvdata[1] / (float)(gstate_c.curTextureHeight); + decoded_ += 2 * sizeof(float); +} + +void VertexDecoder::Step_TcFloat() const +{ + float *uv = (float *)decoded_; + const float *uvdata = (const float*)(ptr_ + tcoff); + uv[0] = uvdata[0]; + uv[1] = uvdata[1]; + decoded_ += 2 * sizeof(float); +} + +void VertexDecoder::Step_TcFloatThrough() const +{ + float *uv = (float *)decoded_; + const float *uvdata = (const float*)(ptr_ + tcoff); + uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth); + uv[1] = uvdata[1] / (float)(gstate_c.curTextureHeight); + decoded_ += 2 * sizeof(float); +} + +void VertexDecoder::Step_Color565() const +{ + u8 *c = decoded_; + u16 cdata = *(u16*)(ptr_ + coloff); + c[0] = Convert5To8(cdata & 0x1f); + c[1] = Convert6To8((cdata>>5) & 0x3f); + c[2] = Convert5To8((cdata>>11) & 0x1f); + c[3] = 1.0f; + decoded_ += 4; +} + +void VertexDecoder::Step_Color5551() const +{ + u8 *c = decoded_; + u16 cdata = *(u16*)(ptr_ + coloff); + c[0] = Convert5To8(cdata & 0x1f); + c[1] = Convert5To8((cdata>>5) & 0x1f); + c[2] = Convert5To8((cdata>>10) & 0x1f); + c[3] = (cdata>>15) ? 255 : 0; + decoded_ += 4; +} + +void VertexDecoder::Step_Color4444() const +{ + u8 *c = decoded_; + u16 cdata = *(u16*)(ptr_ + coloff); + for (int j = 0; j < 4; j++) + c[j] = Convert4To8((cdata >> (j * 4)) & 0xF); + decoded_ += 4; +} + +void VertexDecoder::Step_Color8888() const +{ + u8 *c = decoded_; + // TODO: speedup + u8 *cdata = (u8*)(ptr_ + coloff); + for (int j = 0; j < 4; j++) + c[j] = cdata[j]; + decoded_ += 4; +} + +void VertexDecoder::Step_Color565Morph() const +{ + float col[3] = {0}; + for (int n = 0; n < morphcount; n++) + { + float w = gstate_c.morphWeights[n]; + u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); + col[0] += w * (cdata & 0x1f) / 31.f; + col[1] += w * ((cdata>>5) & 0x3f) / 63.f; + col[2] += w * ((cdata>>11) & 0x1f) / 31.f; + } + for (int i = 0; i < 3; i++) { + decoded_[i] = (u8)(col[i] * 255.0f); + } + decoded_[3] = 255; + decoded_ += 4; +} + +void VertexDecoder::Step_Color5551Morph() const +{ + float col[4] = {0}; + for (int n = 0; n < morphcount; n++) + { + float w = gstate_c.morphWeights[n]; + u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); + col[0] += w * (cdata & 0x1f) / 31.f; + col[1] += w * ((cdata>>5) & 0x1f) / 31.f; + col[2] += w * ((cdata>>10) & 0x1f) / 31.f; + col[3] += w * (cdata>>15) ? 1.0f : 0.0f; + } + for (int i = 0; i < 4; i++) { + decoded_[i] = (u8)(col[i] * 255.0f); + } + decoded_ += 4; +} + +void VertexDecoder::Step_Color4444Morph() const +{ + float col[4] = {0}; + for (int n = 0; n < morphcount; n++) + { + float w = gstate_c.morphWeights[n]; + u16 cdata = *(u16*)(ptr_ + onesize_*n + coloff); + for (int j = 0; j < 4; j++) + col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.f; + } + for (int i = 0; i < 4; i++) { + decoded_[i] = (u8)(col[i] * 255.0f); + } + decoded_ += 4; +} + +void VertexDecoder::Step_Color8888Morph() const +{ + float col[4] = {0}; + for (int n = 0; n < morphcount; n++) + { + float w = gstate_c.morphWeights[n]; + const u8 *cdata = (const u8*)(ptr_ + onesize_*n + coloff); + for (int j = 0; j < 4; j++) + col[j] += w * cdata[j]; + } + for (int i = 0; i < 4; i++) { + decoded_[i] = (u8)(col[i]); + } + decoded_ += 4; +} + +void VertexDecoder::Step_NormalS8() const +{ + float *normal = (float *)decoded_; + float multiplier = 1.0f; + if (gstate.reversenormals & 0xFFFFFF) + multiplier = -multiplier; + const s8 *sv = (const s8*)(ptr_ + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] = (sv[j]/127.0f) * multiplier; + decoded_ += 12; +} + +void VertexDecoder::Step_NormalS16() const +{ + float *normal = (float *)decoded_; + float multiplier = 1.0f; + if (gstate.reversenormals & 0xFFFFFF) + multiplier = -multiplier; + const short *sv = (const short*)(ptr_ + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] = (sv[j]/32767.0f) * multiplier; + decoded_ += 12; +} + +void VertexDecoder::Step_NormalFloat() const +{ + float *normal = (float *)decoded_; + float multiplier = 1.0f; + if (gstate.reversenormals & 0xFFFFFF) + multiplier = -multiplier; + const float *fv = (const float*)(ptr_ + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] = fv[j] * multiplier; + decoded_ += 12; +} + +void VertexDecoder::Step_NormalS8Morph() const +{ + float *normal = (float *)decoded_; + memset(normal, 0, sizeof(float)*3); + for (int n = 0; n < morphcount; n++) + { + float multiplier = gstate_c.morphWeights[n]; + if (gstate.reversenormals & 0xFFFFFF) { + multiplier = -multiplier; + } + const s8 *sv = (const s8*)(ptr_ + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += (sv[j]/32767.0f) * multiplier; + } + decoded_ += 12; +} + +void VertexDecoder::Step_NormalS16Morph() const +{ + float *normal = (float *)decoded_; + memset(normal, 0, sizeof(float)*3); + for (int n = 0; n < morphcount; n++) + { + float multiplier = gstate_c.morphWeights[n]; + if (gstate.reversenormals & 0xFFFFFF) { + multiplier = -multiplier; + } + const float *fv = (const float*)(ptr_ + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += fv[j] * multiplier; + } + decoded_ += 12; +} + +void VertexDecoder::Step_NormalFloatMorph() const +{ + float *normal = (float *)decoded_; + memset(normal, 0, sizeof(float)*3); + for (int n = 0; n < morphcount; n++) + { + float multiplier = gstate_c.morphWeights[n]; + if (gstate.reversenormals & 0xFFFFFF) { + multiplier = -multiplier; + } + const float *fv = (const float*)(ptr_ + onesize_*n + nrmoff); + for (int j = 0; j < 3; j++) + normal[j] += fv[j] * multiplier; + } + decoded_ += 12; +} + +void VertexDecoder::Step_PosS8() const +{ + float *v = (float *)decoded_; + float multiplier = 1.0f / 127.0f; + const s8 *sv = (const s8*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = sv[j] * multiplier; + decoded_ += 12; +} + +void VertexDecoder::Step_PosS16() const +{ + float *v = (float *)decoded_; + float multiplier = 1.0f / 32767.0f; + const short *sv = (const short*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = sv[j] * multiplier; + decoded_ += 12; +} + +void VertexDecoder::Step_PosFloat() const +{ + float *v = (float *)decoded_; + const float *fv = (const float*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = fv[j]; + decoded_ += 12; +} + +void VertexDecoder::Step_PosS8Through() const +{ + float *v = (float *)decoded_; + const s8 *sv = (const s8*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = sv[j]; + decoded_ += 12; +} + +void VertexDecoder::Step_PosS16Through() const +{ + float *v = (float *)decoded_; + const short *sv = (const short*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = sv[j]; + decoded_ += 12; +} + +void VertexDecoder::Step_PosFloatThrough() const +{ + float *v = (float *)decoded_; + const float *fv = (const float*)(ptr_ + posoff); + for (int j = 0; j < 3; j++) + v[j] = fv[j]; + decoded_ += 12; +} + +void VertexDecoder::Step_PosS8Morph() const +{ + float *v = (float *)decoded_; + memset(v, 0, sizeof(float) * 3); + for (int n = 0; n < morphcount; n++) { + const s8 *sv = (const s8*)(ptr_ + onesize_*n + posoff); + for (int j = 0; j < 3; j++) + v[j] += (sv[j] / 127.f) * gstate_c.morphWeights[n]; + } + decoded_ += 12; +} + +void VertexDecoder::Step_PosS16Morph() const +{ + float *v = (float *)decoded_; + memset(v, 0, sizeof(float) * 3); + for (int n = 0; n < morphcount; n++) { + float multiplier = 1.0f / 32767.0f; + const short *sv = (const short*)(ptr_ + onesize_*n + posoff); + for (int j = 0; j < 3; j++) + v[j] += (sv[j] * multiplier) * gstate_c.morphWeights[n]; + } + decoded_ += 12; +} + +void VertexDecoder::Step_PosFloatMorph() const +{ + float *v = (float *)decoded_; + memset(v, 0, sizeof(float) * 3); + for (int n = 0; n < morphcount; n++) { + const float *fv = (const float*)(ptr_ + onesize_*n + posoff); + for (int j = 0; j < 3; j++) + v[j] += fv[j] * gstate_c.morphWeights[n]; + } + decoded_ += 12; +} + +const StepFunction wtstep[4] = { + 0, + &VertexDecoder::Step_WeightsU8, + &VertexDecoder::Step_WeightsU16, + &VertexDecoder::Step_WeightsFloat, +}; + +const StepFunction tcstep[4] = { + 0, + &VertexDecoder::Step_TcU8, + &VertexDecoder::Step_TcU16, + &VertexDecoder::Step_TcFloat, +}; + +const StepFunction tcstep_through[4] = { + 0, + &VertexDecoder::Step_TcU8, + &VertexDecoder::Step_TcU16Through, + &VertexDecoder::Step_TcFloatThrough, +}; + +// TODO: Tc Morph + +const StepFunction colstep[8] = { + 0, 0, 0, 0, + &VertexDecoder::Step_Color565, + &VertexDecoder::Step_Color5551, + &VertexDecoder::Step_Color4444, + &VertexDecoder::Step_Color8888, +}; + +const StepFunction colstep_morph[8] = { + 0, 0, 0, 0, + &VertexDecoder::Step_Color565Morph, + &VertexDecoder::Step_Color5551Morph, + &VertexDecoder::Step_Color4444Morph, + &VertexDecoder::Step_Color8888Morph, +}; + +const StepFunction nrmstep[4] = { + 0, + &VertexDecoder::Step_NormalS8, + &VertexDecoder::Step_NormalS16, + &VertexDecoder::Step_NormalFloat, +}; + +const StepFunction nrmstep_morph[4] = { + 0, + &VertexDecoder::Step_NormalS8Morph, + &VertexDecoder::Step_NormalS16Morph, + &VertexDecoder::Step_NormalFloatMorph, +}; + +const StepFunction posstep[4] = { + 0, + &VertexDecoder::Step_PosS8, + &VertexDecoder::Step_PosS16, + &VertexDecoder::Step_PosFloat, +}; + +const StepFunction posstep_morph[4] = { + 0, + &VertexDecoder::Step_PosS8Morph, + &VertexDecoder::Step_PosS16Morph, + &VertexDecoder::Step_PosFloatMorph, +}; + +const StepFunction posstep_through[4] = { + 0, + &VertexDecoder::Step_PosS8Through, + &VertexDecoder::Step_PosS16Through, + &VertexDecoder::Step_PosFloatThrough, +}; + + void VertexDecoder::SetVertexType(u32 fmt) { fmt_ = fmt; throughmode = (fmt & GE_VTYPE_THROUGH) != 0; + numSteps_ = 0; int biggest = 0; size = 0; @@ -131,6 +568,8 @@ void VertexDecoder::SetVertexType(u32 fmt) { if (wtalign[weighttype] > biggest) biggest = wtalign[weighttype]; + steps_[numSteps_++] = wtstep[weighttype]; + if (nweights < 5) { decFmt.w0off = decOff; decFmt.w0fmt = DEC_FLOAT_1 + nweights - 1; @@ -150,6 +589,8 @@ void VertexDecoder::SetVertexType(u32 fmt) { if (tcalign[tc] > biggest) biggest = tcalign[tc]; + steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc]; + // All UV decode to DEC_FLOAT2 currently. decFmt.uvfmt = DEC_FLOAT_2; decFmt.uvoff = decOff; @@ -163,6 +604,8 @@ void VertexDecoder::SetVertexType(u32 fmt) { if (colalign[col] > biggest) biggest = colalign[col]; + steps_[numSteps_++] = morphcount == 1 ? colstep[col] : colstep_morph[col]; + // All color formats decode to DEC_U8_4 currently. // They can become floats later during transform though. decFmt.c0fmt = DEC_U8_4; @@ -179,12 +622,15 @@ void VertexDecoder::SetVertexType(u32 fmt) { if (nrmalign[nrm] > biggest) biggest = nrmalign[nrm]; + steps_[numSteps_++] = morphcount == 1 ? nrmstep[nrm] : nrmstep_morph[nrm]; + // The normal formats match the gl formats perfectly, let's use 'em. switch (nrm) { case GE_VTYPE_NRM_8BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S8_3; break; case GE_VTYPE_NRM_16BIT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_S16_3; break; case GE_VTYPE_NRM_FLOAT >> GE_VTYPE_NRM_SHIFT: decFmt.nrmfmt = DEC_FLOAT_3; break; } + // Actually, temporarily let's not. decFmt.nrmfmt = DEC_FLOAT_3; decFmt.nrmoff = decOff; @@ -200,8 +646,11 @@ void VertexDecoder::SetVertexType(u32 fmt) { biggest = posalign[pos]; if (throughmode) { + steps_[numSteps_++] = posstep_through[pos]; decFmt.posfmt = DEC_FLOAT_3; } else { + steps_[numSteps_++] = morphcount == 1 ? posstep[pos] : posstep_morph[pos]; + // The non-through-mode position formats match the gl formats perfectly, let's use 'em. switch (pos) { case GE_VTYPE_POS_8BIT >> GE_VTYPE_POS_SHIFT: decFmt.posfmt = DEC_S8_3; break; @@ -222,12 +671,8 @@ void VertexDecoder::SetVertexType(u32 fmt) { DEBUG_LOG(G3D,"SVT : size = %i, aligned to biggest %i", size, biggest); } -void VertexDecoder::DecodeVerts(u8 *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const +void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const { - // TODO: Remove - if (morphcount == 1) - gstate_c.morphWeights[0] = 1.0f; - // Find index bounds. Could cache this in display lists. int lowerBound = 0x7FFFFFFF; int upperBound = 0; @@ -254,261 +699,15 @@ void VertexDecoder::DecodeVerts(u8 *decoded, const void *verts, const void *inds *indexLowerBound = lowerBound; *indexUpperBound = upperBound; - // Decode the vertices within the found bounds, once each (unlike the previous way..) + // Decode the vertices within the found bounds, once each + decoded_ = decodedptr; + ptr_ = (const u8*)verts + lowerBound * size; for (int index = lowerBound; index <= upperBound; index++) { - u8 *ptr = (u8*)verts + (index * size); - - // TODO: Should weights be morphed? - float *wt = (float *)decoded; - switch (weighttype) - { - case GE_VTYPE_WEIGHT_NONE >> 9: - break; - - case GE_VTYPE_WEIGHT_8BIT >> 9: - { - const u8 *wdata = (const u8*)(ptr); - for (int j = 0; j < nweights; j++) - wt[j] = (float)wdata[j] / 128.0f; - } - break; - - case GE_VTYPE_WEIGHT_16BIT >> 9: - { - const u16 *wdata = (const u16*)(ptr); - for (int j = 0; j < nweights; j++) - wt[j] = (float)wdata[j] / 32768.0f; - } - break; - - case GE_VTYPE_WEIGHT_FLOAT >> 9: - { - const float *wdata = (const float*)(ptr+0); - for (int j = 0; j < nweights; j++) - wt[j] = wdata[j]; - } - break; + for (int i = 0; i < numSteps_; i++) { + ((*this).*steps_[i])(); } - if (weighttype) - decoded += nweights * sizeof(float); - - // TODO: Not morphing UV yet - switch (tc) - { - case GE_VTYPE_TC_NONE: - break; - - case GE_VTYPE_TC_8BIT: - { - float *uv = (float *)decoded; - const u8 *uvdata = (const u8*)(ptr + tcoff); - for (int j = 0; j < 2; j++) - uv[j] = (float)uvdata[j] / 128.0f; - decoded += 2 * sizeof(float); - break; - } - - case GE_VTYPE_TC_16BIT: - { - float *uv = (float *)decoded; - const u16 *uvdata = (const u16*)(ptr + tcoff); - if (throughmode) - { - uv[0] = (float)uvdata[0] / (float)(gstate_c.curTextureWidth); - uv[1] = (float)uvdata[1] / (float)(gstate_c.curTextureHeight); - } - else - { - uv[0] = (float)uvdata[0] / 32768.0f; - uv[1] = (float)uvdata[1] / 32768.0f; - } - decoded += 2 * sizeof(float); - } - break; - - case GE_VTYPE_TC_FLOAT: - { - float *uv = (float *)decoded; - const float *uvdata = (const float*)(ptr + tcoff); - if (throughmode) { - uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth); - uv[1] = uvdata[1] / (float)(gstate_c.curTextureHeight); - } else { - uv[0] = uvdata[0]; - uv[1] = uvdata[1]; - } - decoded += 2 * sizeof(float); - } - break; - } - - // TODO: Not morphing color yet - switch (col) - { - case GE_VTYPE_COL_4444 >> 2: - { - u8 *c = decoded; - u16 cdata = *(u16*)(ptr + coloff); - for (int j = 0; j < 4; j++) - c[j] = Convert4To8((cdata >> (j * 4)) & 0xF); - decoded += 4; - } - break; - - case GE_VTYPE_COL_565 >> 2: - { - u8 *c = decoded; - u16 cdata = *(u16*)(ptr + coloff); - c[0] = Convert5To8(cdata & 0x1f); - c[1] = Convert6To8((cdata>>5) & 0x3f); - c[2] = Convert5To8((cdata>>11) & 0x1f); - c[3] = 1.0f; - decoded += 4; - } - break; - - case GE_VTYPE_COL_5551 >> 2: - { - u8 *c = decoded; - u16 cdata = *(u16*)(ptr + coloff); - c[0] = Convert5To8(cdata & 0x1f); - c[1] = Convert5To8((cdata>>5) & 0x1f); - c[2] = Convert5To8((cdata>>10) & 0x1f); - c[3] = (cdata>>15) ? 255 : 0; - decoded += 4; - } - break; - - case GE_VTYPE_COL_8888 >> 2: - { - u8 *c = decoded; - // TODO: speedup - u8 *cdata = (u8*)(ptr + coloff); - for (int j = 0; j < 4; j++) - c[j] = cdata[j]; - decoded += 4; - } - break; - - default: - break; - } - - float *normal = (float *)decoded; - if (nrm) { - memset(normal, 0, sizeof(float)*3); - for (int n = 0; n < morphcount; n++) - { - float multiplier = gstate_c.morphWeights[n]; - if (gstate.reversenormals & 0xFFFFFF) { - multiplier = -multiplier; - } - switch (nrm) - { - case GE_VTYPE_NRM_8BIT: - { - const s8 *sv = (const s8*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += (sv[j]/127.0f) * multiplier; - } - break; - - case GE_VTYPE_NRM_FLOAT >> 5: - { - const float *fv = (const float*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += fv[j] * multiplier; - } - break; - - case GE_VTYPE_NRM_16BIT >> 5: - { - const short *sv = (const short*)(ptr + onesize_*n + nrmoff); - for (int j = 0; j < 3; j++) - normal[j] += (sv[j]/32767.0f) * multiplier; - } - break; - } - } - decoded += 12; - } - - float *v = (float *)decoded; - if (morphcount == 1) { - switch (pos) - { - case GE_VTYPE_POS_FLOAT >> 7: - { - const float *fv = (const float*)(ptr + posoff); - for (int j = 0; j < 3; j++) - v[j] = fv[j]; - } - break; - - case GE_VTYPE_POS_16BIT >> 7: - { - float multiplier = 1.0f / 32767.0f; - if (throughmode) multiplier = 1.0f; - const short *sv = (const short*)(ptr + posoff); - for (int j = 0; j < 3; j++) - v[j] = sv[j] * multiplier; - } - break; - - case GE_VTYPE_POS_8BIT >> 7: - { - float multiplier = 1.0f / 127.0f; - if (throughmode) multiplier = 1.0f; - const s8 *sv = (const s8*)(ptr + posoff); - for (int j = 0; j < 3; j++) - v[j] = sv[j] * multiplier; - } - break; - - default: - ERROR_LOG(G3D, "Unknown position format %i",pos); - break; - } - } else { - memset(v, 0, sizeof(float) * 3); - for (int n = 0; n < morphcount; n++) - { - switch (pos) - { - case GE_VTYPE_POS_FLOAT >> 7: - { - const float *fv = (const float*)(ptr + onesize_*n + posoff); - for (int j = 0; j < 3; j++) - v[j] += fv[j] * gstate_c.morphWeights[n]; - } - break; - - case GE_VTYPE_POS_16BIT >> 7: - { - float multiplier = 1.0f / 32767.0f; - if (throughmode) multiplier = 1.0f; - const short *sv = (const short*)(ptr + onesize_*n + posoff); - for (int j = 0; j < 3; j++) - v[j] += (sv[j] * multiplier) * gstate_c.morphWeights[n]; - } - break; - - case GE_VTYPE_POS_8BIT >> 7: - { - const s8 *sv = (const s8*)(ptr + onesize_*n + posoff); - for (int j = 0; j < 3; j++) - v[j] += (sv[j] / 127.f) * gstate_c.morphWeights[n]; - } - break; - - default: - ERROR_LOG(G3D,"Unknown position format %i",pos); - break; - } - } - } - decoded += 12; + ptr_ += size; } } diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 72048d9bcf..f8cdddf232 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -61,6 +61,10 @@ struct TransformedVertex DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt); +class VertexDecoder; + +typedef void (VertexDecoder::*StepFunction)() const; + // Right now // - only contains computed information @@ -86,7 +90,59 @@ public: bool hasColor() const { return col != 0; } int VertexSize() const { return size; } -private: + void Step_WeightsU8() const; + void Step_WeightsU16() const; + void Step_WeightsFloat() const; + + void Step_TcU8() const; + void Step_TcU16() const; + void Step_TcFloat() const; + void Step_TcU16Through() const; + void Step_TcFloatThrough() const; + + // TODO: tcmorph + + void Step_Color4444() const; + void Step_Color565() const; + void Step_Color5551() const; + void Step_Color8888() const; + + void Step_Color4444Morph() const; + void Step_Color565Morph() const; + void Step_Color5551Morph() const; + void Step_Color8888Morph() const; + + void Step_NormalS8() const; + void Step_NormalS16() const; + void Step_NormalFloat() const; + + void Step_NormalS8Morph() const; + void Step_NormalS16Morph() const; + void Step_NormalFloatMorph() const; + + void Step_PosS8() const; + void Step_PosS16() const; + void Step_PosFloat() const; + + void Step_PosS8Morph() const; + void Step_PosS16Morph() const; + void Step_PosFloatMorph() const; + + void Step_PosS8Through() const; + void Step_PosS16Through() const; + void Step_PosFloatThrough() const; + + + // Mutable decoder state + mutable u8 *decoded_; + mutable const u8 *ptr_; + + // "Immutable" state, set at startup + + // The decoding steps + StepFunction steps_[5]; + int numSteps_; + u32 fmt_; DecVtxFormat decFmt; diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 0f58cd8f1c..7b36bc7078 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -91,6 +91,9 @@ true true ../common;..;../native;../native/ext/glew; + false + StreamingSIMDExtensions2 + Fast true @@ -136,7 +139,9 @@ - + + AssemblyAndSourceCode + diff --git a/ext/libkirk/libkirk.vcxproj b/ext/libkirk/libkirk.vcxproj index 03cc26bc5c..3c248e88ea 100644 --- a/ext/libkirk/libkirk.vcxproj +++ b/ext/libkirk/libkirk.vcxproj @@ -91,6 +91,9 @@ MaxSpeed true true + false + StreamingSIMDExtensions2 + Fast true diff --git a/ext/zlib/zlib.vcxproj b/ext/zlib/zlib.vcxproj index b35269cd97..be9c34926c 100644 --- a/ext/zlib/zlib.vcxproj +++ b/ext/zlib/zlib.vcxproj @@ -129,6 +129,8 @@ true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) StreamingSIMDExtensions2 + false + Fast Windows diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index 6fe00a43be..e4e8907ff7 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -113,6 +113,9 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) ../Common;..;../Core;../native/ext/glew; + false + StreamingSIMDExtensions2 + Fast Console From 4f376a2c342b5c61253ed0ff081c09de71edabcd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 14:10:42 +0100 Subject: [PATCH 032/276] Hardware vertex transform, preliminary and optional. No lighting yet. Disabled until it works right... --- GPU/GLES/DisplayListInterpreter.cpp | 14 ++ GPU/GLES/DisplayListInterpreter.h | 2 + GPU/GLES/FragmentShaderGenerator.cpp | 4 +- GPU/GLES/ShaderManager.cpp | 52 ++++- GPU/GLES/ShaderManager.h | 14 +- GPU/GLES/TransformPipeline.cpp | 262 ++++++++++++---------- GPU/GLES/VertexShaderGenerator.cpp | 314 ++++++++++++++++++++++++--- GPU/GLES/VertexShaderGenerator.h | 4 +- GPU/GPUState.h | 13 +- 9 files changed, 522 insertions(+), 157 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 47ebb62592..2202a21163 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -609,21 +609,25 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXSCALEU: gstate_c.uScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); + shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: gstate_c.vScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); + shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: gstate_c.uOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); + shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: gstate_c.vOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); + shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_SCISSOR1: @@ -829,6 +833,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_MATERIALAMBIENT: DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: @@ -845,6 +851,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_MATERIALALPHA: DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: @@ -1034,6 +1042,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXENVCOLOR: DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_TEXENV); break; case GE_CMD_TEXMODE: DEBUG_LOG(G3D,"DL TexMode %08x", data); @@ -1100,6 +1110,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) if (num < 12) gstate.worldMatrix[num++] = getFloat24(data); gstate.worldmtxnum = (gstate.worldmtxnum & 0xFF000000) | (num & 0xF); + shaderManager.DirtyUniform(DIRTY_WORLDMATRIX); } break; @@ -1115,6 +1126,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) if (num < 12) gstate.viewMatrix[num++] = getFloat24(data); gstate.viewmtxnum = (gstate.viewmtxnum & 0xFF000000) | (num & 0xF); + shaderManager.DirtyUniform(DIRTY_VIEWMATRIX); } break; @@ -1146,6 +1158,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) gstate.tgenMatrix[num++] = getFloat24(data); gstate.texmtxnum = (gstate.texmtxnum & 0xFF000000) | (num & 0xF); } + shaderManager.DirtyUniform(DIRTY_TEXMATRIX); break; case GE_CMD_BONEMATRIXNUMBER: @@ -1157,6 +1170,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); { int num = gstate.boneMatrixNumber & 0x7F; + shaderManager.DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); if (num < 96) { gstate.boneMatrix[num++] = getFloat24(data); } diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index e7faf8c45a..7d3a6708b8 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -25,6 +25,7 @@ #include "gfx_es2/fbo.h" class ShaderManager; +struct DecVtxFormat; class GLES_GPU : public GPUInterface { @@ -51,6 +52,7 @@ public: private: // TransformPipeline.cpp void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); + void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); void ApplyDrawState(); void Flush(int prim); void UpdateViewportAndProjection(); diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index a7f11113bd..7cd7e2302b 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -88,7 +88,7 @@ char *GenerateFragmentShader() WRITE(p, "uniform vec3 u_texenv;\n"); WRITE(p, "varying vec4 v_color0;\n"); if (lmode) - WRITE(p, "varying vec4 v_color1;\n"); + WRITE(p, "varying vec3 v_color1;\n"); if (doTexture) WRITE(p, "varying vec2 v_texcoord;\n"); if (gstate.isFogEnabled()) @@ -107,7 +107,7 @@ char *GenerateFragmentShader() const char *secondary = ""; // Secondary color for specular on top of texture if (lmode) { - WRITE(p, " vec4 s = vec4(v_color1.xyz, 0.0);"); + WRITE(p, " vec4 s = vec4(v_color1, 0.0);"); secondary = " + s"; } else { WRITE(p, " vec4 s = vec4(0.0, 0.0, 0.0, 0.0);\n"); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 34c24c0aeb..53e994161b 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -81,6 +81,20 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) u_fogcoef = glGetUniformLocation(program, "u_fogcoef"); u_alphacolorref = glGetUniformLocation(program, "u_alphacolorref"); + // Transform + u_view = glGetUniformLocation(program, "u_view"); + u_world = glGetUniformLocation(program, "u_world"); + u_texmtx = glGetUniformLocation(program, "u_texmtx"); + for (int i = 0; i < 8; i++) { + char name[64]; + sprintf(name, "u_bone%i", i); + u_bone[i] = glGetUniformLocation(program, name); + } + + // Lighting, texturing + u_matambientalpha = glGetUniformLocation(program, "u_matambientalpha"); + u_uvscaleoffset = glGetUniformLocation(program, "u_uvscaleoffset"); + a_position = glGetAttribLocation(program, "a_position"); a_color0 = glGetAttribLocation(program, "a_color0"); a_color1 = glGetAttribLocation(program, "a_color1"); @@ -93,7 +107,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) // Default uniform values glUniform1i(u_tex, 0); // The rest, use the "dirty" mechanism. - dirtyUniforms = DIRTY_PROJMATRIX | DIRTY_PROJTHROUGHMATRIX | DIRTY_TEXENV | DIRTY_ALPHACOLORREF; + dirtyUniforms = DIRTY_ALL; } LinkedShader::~LinkedShader() { @@ -107,6 +121,12 @@ static void SetColorUniform3(int uniform, u32 color) glUniform3fv(uniform, 1, col); } +static void SetColorUniform3Alpha(int uniform, u32 color, u8 alpha) +{ + const float col[4] = { ((color & 0xFF0000) >> 16) / 255.0f, ((color & 0xFF00) >> 8) / 255.0f, ((color & 0xFF)) / 255.0f, alpha/255.0f}; + glUniform4fv(uniform, 1, col); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); @@ -149,6 +169,34 @@ void LinkedShader::use() { glUniform2fv(u_fogcoef, 1, fogcoef); } + // Texturing + if (u_uvscaleoffset != -1 && (dirtyUniforms & DIRTY_UVSCALEOFFSET)) { + const float uvscaleoff[4] = { gstate_c.uScale, gstate_c.vScale, gstate_c.uOff, gstate_c.vOff}; + glUniform4fv(u_uvscaleoffset, 1, uvscaleoff); + } + + // Transform + if (u_world != -1 && (dirtyUniforms & DIRTY_WORLDMATRIX)) { + glUniformMatrix4x3fv(u_world, 1, GL_FALSE, gstate.worldMatrix); + } + if (u_view != -1 && (dirtyUniforms & DIRTY_VIEWMATRIX)) { + glUniformMatrix4x3fv(u_view, 1, GL_FALSE, gstate.viewMatrix); + } + if (u_texmtx != -1 && (dirtyUniforms & DIRTY_TEXMATRIX)) { + glUniformMatrix4x3fv(u_texmtx, 1, GL_FALSE, gstate.tgenMatrix); + } + for (int i = 0; i < 8; i++) { + if (u_bone[i] != -1 && (dirtyUniforms & (DIRTY_BONEMATRIX0 << i))) { + glUniformMatrix4x3fv(u_bone[i], 1, GL_FALSE, gstate.boneMatrix + 12 * i); + } + } + + // Lighting + if (u_matambientalpha != -1 && (dirtyUniforms & DIRTY_MATAMBIENTALPHA)) { + SetColorUniform3Alpha(u_matambientalpha, gstate.materialambient, gstate.materialalpha & 0xFF); + } + + dirtyUniforms = 0; } @@ -211,7 +259,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim) Shader *vs; if (vsIter == vsCache.end()) { // Vertex shader not in cache. Let's compile it. - char *shaderCode = GenerateVertexShader(); + char *shaderCode = GenerateVertexShader(prim); vs = new Shader(shaderCode, GL_VERTEX_SHADER); vsCache[VSID] = vs; } else { diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index 5b4a98ee8c..e18219bf18 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -48,14 +48,21 @@ struct LinkedShader int u_proj; int u_proj_through; int u_texenv; - + int u_view; + int u_texmtx; + int u_world; + int u_bone[8]; + // Fragment processing inputs int u_alphacolorref; int u_fogcolor; int u_fogcoef; + // Texturing + int u_uvscaleoffset; + // Lighting - int u_ambientcolor; + int u_matambientalpha; int u_light[4]; // each light consist of vec4[3] }; @@ -75,10 +82,11 @@ enum DIRTY_LIGHT2 = (1 << 14), DIRTY_LIGHT3 = (1 << 15), - DIRTY_GLOBALAMBIENT = (1 << 16), + DIRTY_MATAMBIENTALPHA = (1 << 16), DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares" + DIRTY_WORLDMATRIX = (1 << 21), DIRTY_VIEWMATRIX = (1 << 22), // Maybe we'll fold this into projmatrix eventually DIRTY_TEXMATRIX = (1 << 23), DIRTY_BONEMATRIX0 = (1 << 24), diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index de27b6533f..f03c3262ac 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -143,14 +143,6 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ bool doSpecular = (comp != GE_LIGHTCOMP_ONLYDIFFUSE); bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE; - float lightScale = 1.0f; - if (type != GE_LIGHTTYPE_DIRECTIONAL) - { - float distance = toLight.Normalize(); - lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance); - if (lightScale > 1.0f) lightScale = 1.0f; - } - float dot = toLight * norm; // Clamp dot to zero. @@ -159,6 +151,14 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ if (poweredDiffuse) dot = powf(dot, specCoef_); + float lightScale = 1.0f; + if (type != GE_LIGHTTYPE_DIRECTIONAL) + { + float distance = toLight.Normalize(); + lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance); + if (lightScale > 1.0f) lightScale = 1.0f; + } + Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale); // Real PSP specular @@ -192,47 +192,59 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ } } -// This is the software transform pipeline, which is necessary for supporting RECT -// primitives correctly. Other primitives are possible to transform and light in hardware -// using vertex shader, which will be way, way faster, especially on mobile. This has -// not yet been implemented though. -void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) +struct GlTypeInfo { + GLuint type; + int count; + GLboolean normalized; +}; + +const GlTypeInfo GLComp[8] = { + {0}, // DEC_NONE, + {GL_FLOAT, 1, GL_FALSE}, // DEC_FLOAT_1, + {GL_FLOAT, 2, GL_FALSE}, // DEC_FLOAT_2, + {GL_FLOAT, 3, GL_FALSE}, // DEC_FLOAT_3, + {GL_FLOAT, 4, GL_FALSE}, // DEC_FLOAT_4, + {GL_BYTE, 3, GL_TRUE}, // DEC_S8_3, + {GL_SHORT, 3, GL_TRUE},// DEC_S16_3, + {GL_UNSIGNED_BYTE, 4, GL_TRUE},// DEC_U8_4, +}; + +static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) { + if (attrib != -1 && fmt) { + const GlTypeInfo &type = GLComp[fmt]; + glEnableVertexAttribArray(attrib); + glVertexAttribPointer(attrib, type.count, type.type, type.normalized, stride, ptr); + } +} +static inline void VertexAttribDisable(int attrib, int fmt) { + if (attrib != -1 && fmt) { + glDisableVertexAttribArray(attrib); + } +} + +// TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets +static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) { + VertexAttribSetup(program->a_weight0123, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off); + VertexAttribSetup(program->a_weight4567, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off); + VertexAttribSetup(program->a_texcoord, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff); + VertexAttribSetup(program->a_color0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off); + VertexAttribSetup(program->a_color1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off); + VertexAttribSetup(program->a_normal, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff); + VertexAttribSetup(program->a_position, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff); +} + +static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) { + VertexAttribDisable(program->a_weight0123, decFmt.w0fmt); + VertexAttribDisable(program->a_weight4567, decFmt.w1fmt); + VertexAttribDisable(program->a_texcoord, decFmt.uvfmt); + VertexAttribDisable(program->a_color0, decFmt.c0fmt); + VertexAttribDisable(program->a_color1, decFmt.c1fmt); + VertexAttribDisable(program->a_normal, decFmt.nrmfmt); + VertexAttribDisable(program->a_position, decFmt.posfmt); +} + +void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV) { - int indexLowerBound, indexUpperBound; - // First, decode the verts and apply morphing - VertexDecoder dec; - dec.SetVertexType(gstate.vertType); - dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); - if (bytesRead) - *bytesRead = vertexCount * dec.VertexSize(); - - // And here we should return, having collected the morphed but untransformed vertices. - // Note that DecodeVerts should convert strips into indexed lists etc, adding to our - // current vertex buffer and index buffer. - - // The rest below here should only execute on Flush. - -#if 0 - for (int i = indexLowerBound; i <= indexUpperBound; i++) { - PrintDecodedVertex(decoded[i], gstate.vertType); - } -#endif - bool useTexCoord = false; - - // Check if anything needs updating - if (gstate_c.textureChanged) - { - if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) - { - PSPSetTexture(); - useTexCoord = true; - } - } - gpuStats.numDrawCalls++; - gpuStats.numVertsTransformed += vertexCount; - - bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; - /* DEBUG_LOG(G3D, "View matrix:"); const float *m = &gstate.viewMatrix[0]; @@ -259,6 +271,9 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte float v2[3] = {0}; float uv2[2] = {0}; + bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; + + // TODO: Could use glDrawElements in some cases, see below. // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. @@ -270,7 +285,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte Lighter lighter; - VertexReader reader(decoded, dec.GetDecVtxFmt()); + VertexReader reader(decoded, decVtxFormat); for (int index = indexLowerBound; index <= indexUpperBound; index++) { reader.Goto(index); @@ -349,6 +364,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } + // Yes, we really must multiply by the world matrix too. Vec3ByMatrix43(out, psum.v, gstate.worldMatrix); if (reader.hasNormal()) { nsum.Normalize(); @@ -368,7 +384,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (gstate.lightingEnable & 1) { - // TODO: don't ignore gstate.lmode - we should send two colors in that case + // Don't ignore gstate.lmode - we should send two colors in that case if (gstate.lmode & 1) { // Separate colors for (int j = 0; j < 4; j++) { @@ -385,7 +401,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } else { - if(dec.hasColor()) { + if (reader.hasColor0()) { for (int j = 0; j < 4; j++) { c0[j] = unlitColor[j]; c1[j] = 0.0f; @@ -405,7 +421,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte float ruv[2]; reader.ReadUV(ruv); // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. - switch (gstate.texmapmode & 0x3) + switch (gstate.getUVGenMode()) { case 0: // UV mapping // Texture scale/offset is only performed in this mode. @@ -416,7 +432,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte { // Projection mapping Vec3 source; - switch ((gstate.texmapmode >> 8) & 0x3) + switch (gstate.getUVProjMode()) { case 0: // Use model space XYZ as source source = pos; @@ -439,12 +455,10 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } break; case 2: - // Shade mapping + // Shade mapping - use dots from light sources to generate U and V. { - int lightsource1 = gstate.texshade & 0x3; - int lightsource2 = (gstate.texshade >> 8) & 0x3; - uv[0] = dots[lightsource1]; - uv[1] = dots[lightsource2]; + uv[0] = dots[gstate.getUVLS0()]; + uv[1] = dots[gstate.getUVLS1()]; } break; case 3: @@ -569,22 +583,14 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } - // TODO: This should not be done on every drawcall, we should collect vertex data - // until critical state changes. That's when we draw (flush). - - ApplyDrawState(); - UpdateViewportAndProjection(); - - LinkedShader *program = shaderManager_->ApplyShader(prim); - // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. glEnableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); + if (program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); if (program->a_color1 != -1) glEnableVertexAttribArray(program->a_color1); const int vertexSize = sizeof(transformed[0]); glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); - if (useTexCoord && program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); + if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); @@ -594,60 +600,92 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte glDrawArrays(glprim[prim], 0, numTrans); } glDisableVertexAttribArray(program->a_position); - if (useTexCoord && program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); + if (program->a_texcoord != -1) glDisableVertexAttribArray(program->a_texcoord); if (program->a_color0 != -1) glDisableVertexAttribArray(program->a_color0); if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } -struct GlTypeInfo { - GLuint type; - int count; - GLboolean normalized; -}; +// This is the software transform pipeline, which is necessary for supporting RECT +// primitives correctly. Other primitives are possible to transform and light in hardware +// using vertex shader, which will be way, way faster, especially on mobile. This has +// not yet been implemented though. +void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) +{ + int indexLowerBound, indexUpperBound; + // First, decode the verts and apply morphing + VertexDecoder dec; + dec.SetVertexType(gstate.vertType); + dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + if (bytesRead) + *bytesRead = vertexCount * dec.VertexSize(); -const GlTypeInfo GLComp[8] = { - {0}, // DEC_NONE, - {GL_FLOAT, 1, GL_FALSE}, // DEC_FLOAT_1, - {GL_FLOAT, 2, GL_FALSE}, // DEC_FLOAT_2, - {GL_FLOAT, 3, GL_FALSE}, // DEC_FLOAT_3, - {GL_FLOAT, 4, GL_FALSE}, // DEC_FLOAT_4, - {GL_BYTE, 3, GL_TRUE}, // DEC_S8_3, - {GL_SHORT, 3, GL_TRUE},// DEC_S16_3, - {GL_BYTE, 4, GL_TRUE},// DEC_U8_4, -}; + // And here we should return, having collected the morphed but untransformed vertices. + // Note that DecodeVerts should convert strips into indexed lists etc, adding to our + // current vertex buffer and index buffer. -static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) { - if (attrib != -1 && fmt) { - const GlTypeInfo &type = GLComp[fmt]; - glEnableVertexAttribArray(attrib); - glVertexAttribPointer(attrib, type.count, type.type, type.normalized, stride, ptr); + // The rest below here should only execute on Flush. + +#if 0 + for (int i = indexLowerBound; i <= indexUpperBound; i++) { + PrintDecodedVertex(decoded[i], gstate.vertType); } -} -static inline void VertexAttribDisable(int attrib, int fmt) { - if (attrib != -1 && fmt) { - glDisableVertexAttribArray(attrib); +#endif + bool useTexCoord = false; + + // Check if anything needs updating + if (gstate_c.textureChanged) + { + if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) + { + PSPSetTexture(); + useTexCoord = true; + } } -} + gpuStats.numDrawCalls++; + gpuStats.numVertsTransformed += vertexCount; -// TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets -static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) { - VertexAttribSetup(program->a_weight0123, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off); - VertexAttribSetup(program->a_weight4567, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off); - VertexAttribSetup(program->a_texcoord, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff); - VertexAttribSetup(program->a_color0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off); - VertexAttribSetup(program->a_color1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off); - VertexAttribSetup(program->a_normal, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff); - VertexAttribSetup(program->a_position, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff); -} + // TODO: This should not be done on every drawcall, we should collect vertex data + // until critical state changes. That's when we draw (flush). -static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt) { - VertexAttribDisable(program->a_weight0123, decFmt.w0fmt); - VertexAttribDisable(program->a_weight4567, decFmt.w1fmt); - VertexAttribDisable(program->a_texcoord, decFmt.uvfmt); - VertexAttribDisable(program->a_color0, decFmt.c0fmt); - VertexAttribDisable(program->a_color1, decFmt.c1fmt); - VertexAttribDisable(program->a_normal, decFmt.nrmfmt); - VertexAttribDisable(program->a_position, decFmt.posfmt); + ApplyDrawState(); + UpdateViewportAndProjection(); + + LinkedShader *program = shaderManager_->ApplyShader(prim); + + if (CanUseHardwareTransform(prim)) { + SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), decoded); + + bool drawIndexed; + GLuint glIndexType; + int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); + if (forceIndexType != -1) { + indexType = forceIndexType; + } + int numTrans = vertexCount; + switch (indexType) { + case GE_VTYPE_IDX_8BIT: + drawIndexed = true; + glIndexType = GL_UNSIGNED_BYTE; + break; + case GE_VTYPE_IDX_16BIT: + drawIndexed = true; + glIndexType = GL_UNSIGNED_SHORT; + break; + default: + drawIndexed = false; + break; + } + // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); + if (drawIndexed) { + glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); + } else { + glDrawArrays(glprim[prim], 0, numTrans); + } + + DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); + } else { + SoftwareTransformAndDraw(prim, program, forceIndexType, vertexCount, inds, dec.GetDecVtxFmt(), indexLowerBound, indexUpperBound, customUV); + } } void GLES_GPU::Flush(int prim) { diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index d573942aa4..92c6eb9c3f 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -20,6 +20,9 @@ // the transforms ourselves. #include +#if defined(_WIN32) && defined(_DEBUG) +#include +#endif #include "../ge_constants.h" #include "../GPUState.h" @@ -36,18 +39,53 @@ static char buffer[16384]; -#define WRITE(x, ...) p+=sprintf(p, x "\n" __VA_ARGS__) +#define WRITE p+=sprintf + +bool CanUseHardwareTransform(int prim) +{ + return !gstate.isModeThrough() && false; // prim != GE_PRIM_RECTANGLES; + // return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; +} // prim so we can special case for RECTANGLES :( void ComputeVertexShaderID(VertexShaderID *id, int prim) { int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1); + bool hasColor = (gstate.vertType & GE_VTYPE_COL_MASK) != 0; + bool hasNormal = (gstate.vertType & GE_VTYPE_NRM_MASK) != 0; + bool hasBones = (gstate.vertType & GE_VTYPE_WEIGHT_MASK) != 0; + + int shadeLight0 = gstate.getUVGenMode() == 2 ? gstate.getUVLS0() : -1; + int shadeLight1 = gstate.getUVGenMode() == 2 ? gstate.getUVLS1() : -1; + memset(id->d, 0, sizeof(id->d)); id->d[0] = gstate.lmode & 1; id->d[0] |= ((int)gstate.isModeThrough()) << 1; id->d[0] |= ((int)gstate.isFogEnabled()) << 2; id->d[0] |= doTexture << 3; + id->d[0] |= (hasColor & 1) << 4; + if (CanUseHardwareTransform(prim)) { + id->d[0] |= 1 << 8; + id->d[0] |= (hasNormal & 1) << 9; + id->d[0] |= (hasBones & 1) << 10; + + // UV generation mode + id->d[0] |= gstate.getUVGenMode() << 16; + + // The next bits are used differently depending on UVgen mode + if (gstate.getUVGenMode() == 1) { + id->d[0] |= gstate.getUVProjMode() << 18; + } else if (gstate.getUVGenMode() == 2) { + id->d[0] |= gstate.getUVLS0() << 18; + id->d[0] |= gstate.getUVLS1() << 20; + } + + // Bones + id->d[0] |= (gstate.getNumBoneWeights() - 1) << 22; + + // Light bits + } // Bits that we will need: // lightenable * 4 @@ -62,56 +100,262 @@ void WriteLight(char *p, int l) { // TODO } -char *GenerateVertexShader() +const char *boneWeightAttrDecl[8] = { + "#ERROR", + "attribute vec2 a_weight0123;\n", + "attribute vec3 a_weight0123;\n", + "attribute vec4 a_weight0123;\n", + "attribute vec4 a_weight0123;\nattribute float a_weight4567;\n", + "attribute vec4 a_weight0123;\nattribute vec2 a_weight4567;\n", + "attribute vec4 a_weight0123;\nattribute vec3 a_weight4567;\n", + "attribute vec4 a_weight0123;\nattribute vec4 a_weight4567;\n", +}; + +const char *boneWeightAttr[8] = { + "a_weight0123.x", + "a_weight0123.y", + "a_weight0123.z", + "a_weight0123.w", + "a_weight4567.x", + "a_weight4567.y", + "a_weight4567.z", + "a_weight4567.w", +}; + +enum DoLightComputation { + LIGHT_OFF, + LIGHT_DOTONLY, + LIGHT_FULL, +}; + + +char *GenerateVertexShader(int prim) { char *p = buffer; #if defined(USING_GLES2) - WRITE("precision highp float;"); + WRITE(p, "precision highp float;\n"); #elif !defined(FORCE_OPENGL_2_0) - WRITE("#version 130"); + WRITE(p, "#version 130\n"); #endif int lmode = gstate.lmode & 1; - int doTexture = (gstate.textureMapEnable & 1) && !(gstate.clearmode & 1); - WRITE("attribute vec3 a_position;"); - if (doTexture) - WRITE("attribute vec2 a_texcoord;"); - WRITE("attribute vec4 a_color0;"); - if (lmode) - WRITE("attribute vec4 a_color1;"); + bool hwXForm = CanUseHardwareTransform(prim); + bool hasColor = (gstate.vertType & GE_VTYPE_COL_MASK) != 0 || !hwXForm; + bool hasNormal = (gstate.vertType & GE_VTYPE_NRM_MASK) != 0 && hwXForm; + + DoLightComputation doLight[4] = {LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF}; + if (hwXForm) { + int shadeLight0 = gstate.getUVGenMode() == 2 ? gstate.getUVLS0() : -1; + int shadeLight1 = gstate.getUVGenMode() == 2 ? gstate.getUVLS1() : -1; + for (int i = 0; i < 4; i++) { + if (!hasNormal) + continue; + if (i == shadeLight0 || i == shadeLight1) + doLight[i] = LIGHT_DOTONLY; + if ((gstate.lightingEnable & 1) && (gstate.lightEnable[i] & 1)) + doLight[i] = LIGHT_FULL; + } + } + + if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { + WRITE(p, "%s", boneWeightAttrDecl[gstate.getNumBoneWeights() - 1]); + } + + WRITE(p, "attribute vec3 a_position;\n"); + if (doTexture) WRITE(p, "attribute vec2 a_texcoord;\n"); + if (hasColor) { + WRITE(p, "attribute vec4 a_color0;\n"); + if (lmode && !hwXForm) // only software transform supplies color1 as vertex data + WRITE(p, "attribute vec3 a_color1;\n"); + } + + if (hwXForm && hasNormal) + WRITE(p, "attribute vec3 a_normal;\n"); if (gstate.isModeThrough()) { - WRITE("uniform mat4 u_proj_through;"); + WRITE(p, "uniform mat4 u_proj_through;\n"); } else { - WRITE("uniform mat4 u_proj;"); + WRITE(p, "uniform mat4 u_proj;\n"); // Add all the uniforms we'll need to transform properly. } - WRITE("varying vec4 v_color0;"); - if (lmode) - WRITE("varying vec4 v_color1;"); - if (doTexture) - WRITE("varying vec2 v_texcoord;"); - if (gstate.isFogEnabled()) - WRITE("varying float v_depth;"); - WRITE("void main() {"); - WRITE(" v_color0 = a_color0;"); - if (lmode) - WRITE(" v_color1 = a_color1;"); - if (doTexture) - WRITE(" v_texcoord = a_texcoord;"); - if (gstate.isModeThrough()) { - WRITE(" gl_Position = u_proj_through * vec4(a_position, 1.0);"); - } else { - WRITE(" gl_Position = u_proj * vec4(a_position, 1.0);"); - } - if (gstate.isFogEnabled()) { - WRITE(" v_depth = gl_Position.z;"); - } - WRITE("}"); + if (hwXForm || !hasColor) + WRITE(p, "uniform vec4 u_matambientalpha;\n"); // matambient + matalpha + if (hwXForm) { + // When transforming by hardware, we need a great deal more uniforms... + WRITE(p, "uniform mat4x3 u_world;\n"); + WRITE(p, "uniform mat4x3 u_view;\n"); + if (gstate.getUVGenMode() == 0) + WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); + else if (gstate.getUVGenMode() == 1) + WRITE(p, "uniform mat4x3 u_texmtx;\n"); + if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { + int numBones = 1 + ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); + for (int i = 0; i < numBones; i++) { + WRITE(p, "uniform mat4x3 u_bone%i;\n", i); + } + } + } + + WRITE(p, "varying vec4 v_color0;\n"); + if (lmode) WRITE(p, "varying vec3 v_color1;\n"); + if (doTexture) WRITE(p, "varying vec2 v_texcoord;\n"); + if (gstate.isFogEnabled()) WRITE(p, "varying float v_depth;\n"); + WRITE(p, "void main() {\n"); + + if (!hwXForm) { + // Simple pass-through of vertex data to fragment shader + if (doTexture) + WRITE(p, " v_texcoord = a_texcoord;\n"); + if (hasColor) { + WRITE(p, " v_color0 = a_color0;\n"); + if (lmode) + WRITE(p, " v_color1 = a_color1;\n"); + } else { + WRITE(p, " v_color0 = u_matambientalpha;\n"); + if (lmode) + WRITE(p, " v_color1 = vec3(0.0, 0.0, 0.0);\n"); + } + if (gstate.isModeThrough()) { + WRITE(p, " gl_Position = u_proj_through * vec4(a_position, 1.0);\n"); + } else { + WRITE(p, " gl_Position = u_proj * vec4(a_position, 1.0);\n"); + } + } else { + // This is the real deal. + + // Step 1: World Transform / Skinning + if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { + // No skinning, just standard T&L. + WRITE(p, " vec3 worldpos = u_world * vec4(a_position, 1.0);\n"); + if (hasNormal) + WRITE(p, " vec3 worldnormal = u_world * vec4(a_normal, 0.0);\n"); + } else { + WRITE(p, " vec3 worldpos = vec3(0.0, 0.0, 0.0);\n"); + if (hasNormal) + WRITE(p, " vec3 worldnormal = vec3(0.0, 0.0, 0.0);\n"); + int numWeights = 1 + ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); + for (int i = 0; i < numWeights; i++) { + WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0));\n", boneWeightAttr[i], i); + if (hasNormal) + WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0));\n", boneWeightAttr[i], i); + } + // Finally, multiply by world matrix (yes, we have to). + WRITE(p, " worldpos = u_world * vec4(worldpos, 1.0);\n"); + if (hasNormal) + WRITE(p, " worldnormal = u_world * vec4(worldnormal, 0.0);\n"); + } + + // Step 2: Color/Lighting + if (hasColor) { + WRITE(p, " vec4 unlitColor = a_color0;\n"); + } else { + WRITE(p, " vec4 unlitColor(1.0, 1.0, 1.0, 1.0);\n"); + } + + // TODO: Declare variables for dots for shade mapping if needed. + + const char *ambient = (gstate.materialupdate & 1) ? "a_color0" : "u_ambientalpha"; + const char *diffuse = (gstate.materialupdate & 2) ? "a_color0" : "u_matdiffuse"; + const char *specular = (gstate.materialupdate & 4) ? "a_color0" : "u_matspecular"; + + if (gstate.lightingEnable & 1) { + WRITE(p, " vec4 lightSum0 = vec4(0.0);\n"); + WRITE(p, " vec3 lightSum1 = vec3(0.0);\n"); + } + + /* + // Calculate lights if needed. If shade mapping is enabled, lights may need to be + // at least partially calculated + for (int i = 0; i < 4; i++) { + if (doLight[i] == LIGHT_OFF) + continue; + + GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3); + GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3); + + if (type == GE_LIGHTTYPE_DIRECTIONAL) + WRITE(p, " vec3 toLight%i = u_lightpos%i;\n", i, i); + else + WRITE(p, " vec3 toLight%i = u_lightpos%i - worldpos;\n", i, i); + + bool doSpecular = (comp != GE_LIGHTCOMP_ONLYDIFFUSE); + bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE; + + WRITE(p, " float dot%i = dot(tolight, worldnormal);"); + if (doLight[i] == LIGHT_DOTONLY) + continue; // Actually, might want specular dot.... TODO + + }*/ + + if (false && (gstate.lightingEnable & 1)) { + // Sum up ambient, emissive here. + WRITE(p, " v_color0 = lightSum0 + u_ambient * %s + u_matemissive;\n", ambient); + if (lmode) { + WRITE(p, " v_color1 = lightSum1;\n"); + } else { + WRITE(p, " v_color0 += vec4(lightSum1, 0.0);\n"); + } + } else { + // Lighting doesn't affect color. + if (hasColor) { + WRITE(p, " v_color0 = unlitColor;\n"); + } else { + WRITE(p, " v_color0 = u_matambientalpha;\n"); + } + if (lmode) + WRITE(p, " v_color1 = vec3(0.0, 0.0, 0.0);\n"); + } + + // Step 3: UV generation + if (doTexture) { + switch (gstate.getUVGenMode()) { + case 0: // Scale-offset. Easy. + WRITE(p, " v_texcoord = a_texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); + break; + + case 1: // Projection mapping. + switch (gstate.getUVProjMode()) { + case 0: // Use model space XYZ as source + WRITE(p, " vec3 temp_tc = a_position;\n"); + break; + case 1: // Use unscaled UV as source + WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy, 0.0);\n"); + break; + case 2: // Use normalized transformed normal as source + WRITE(p, " vec3 temp_tc = normalize(v_normal);\n"); + break; + case 3: // Use non-normalized transformed normal as source + WRITE(p, " vec3 temp_tc = normalize(v_normal);\n"); + break; + } + // Transform by texture matrix + WRITE(p, " v_texcoord = (u_texmtx * temp_tc).xy;\n"); + break; + + case 2: // Shade mapping - use dots from light sources. + WRITE(p, " v_texcoord = vec2(dot%i, dot%i);\n", gstate.getUVLS0(), gstate.getUVLS1()); + break; + + case 3: + // ILLEGAL + break; + } + } + // Step 4: Final view and projection transforms. + WRITE(p, " gl_Position = u_proj * vec4(u_view * vec4(worldpos, 1.0), 1.0);\n"); + } + if (gstate.isFogEnabled()) + WRITE(p, " v_depth = gl_Position.z;\n"); + WRITE(p, "}\n"); + + // DEBUG_LOG(HLE, "\n%s", buffer); +#if defined(_WIN32) && defined(_DEBUG) + OutputDebugString(buffer); +#endif return buffer; } diff --git a/GPU/GLES/VertexShaderGenerator.h b/GPU/GLES/VertexShaderGenerator.h index 4ce2bdb87b..92d7efec45 100644 --- a/GPU/GLES/VertexShaderGenerator.h +++ b/GPU/GLES/VertexShaderGenerator.h @@ -46,7 +46,9 @@ struct VertexShaderID } }; +bool CanUseHardwareTransform(int prim); + void ComputeVertexShaderID(VertexShaderID *id, int prim); // The return value is only valid until the function is called again. -char *GenerateVertexShader(); +char *GenerateVertexShader(int prim); diff --git a/GPU/GPUState.h b/GPU/GPUState.h index a111b09418..35640c18eb 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -252,9 +252,18 @@ struct GPUgstate bool isDepthWriteEnabled() const { return !(zmsk & 1); } int getDepthTestFunc() const { return ztestfunc & 0x7; } bool isFogEnabled() const { return fogEnable & 1; } -}; -// Real data in the context ends here + int getUVGenMode() const { return texmapmode & 3;} // 2 bits + int getUVProjMode() const { return (texmapmode >> 8) & 3;} // 2 bits + int getUVLS0() const { return texshade & 0x3; } // 2 bits + int getUVLS1() const { return (texshade >> 8) & 0x3; } // 2 bits + + int getNumBoneWeights() const { + return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); + } +// Real data in the context ends here +}; + // The rest is cached simplified/converted data for fast access. // Does not need to be saved when saving/restoring context. struct GPUStateCache From 6a7e77ce1db6fe52fce8b5bdbc0df90a0183eef5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 14:35:47 +0100 Subject: [PATCH 033/276] Prevent crashes on bad vertex / index addresses --- GPU/GLES/DisplayListInterpreter.cpp | 12 ++++++++++++ GPU/GLES/VertexDecoder.h | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 2202a21163..cc772c2ac9 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -400,12 +400,24 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) }; DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) + { + ERROR_LOG(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); + break; + } // TODO: Split this so that we can collect sequences of primitives, can greatly speed things up // on platforms where draw calls are expensive like mobile and D3D void *verts = Memory::GetPointer(gstate_c.vertexAddr); void *inds = 0; if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) + { + if (!Memory::IsValidAddress(gstate_c.indexAddr)) + { + ERROR_LOG(G3D, "Bad index address %08x!", gstate_c.indexAddr); + break; + } inds = Memory::GetPointer(gstate_c.indexAddr); + } // Seems we have to advance the vertex addr, at least in some cases. // Question: Should we also advance the index addr? diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index f8cdddf232..bc2c14786c 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -192,6 +192,9 @@ public: pos[i] = p[i] / 127.0f; } break; + default: + ERROR_LOG(G3D, "Reader: Unsupported Pos Format"); + break; } } @@ -214,6 +217,9 @@ public: nrm[i] = p[i] / 127.0f; } break; + default: + ERROR_LOG(G3D, "Reader: Unsupported Nrm Format"); + break; } } @@ -221,6 +227,9 @@ public: switch (decFmt_.uvfmt) { case DEC_FLOAT_2: memcpy(uv, data_ + decFmt_.uvoff, 8); break; + default: + ERROR_LOG(G3D, "Reader: Unsupported UV Format"); + break; } } @@ -235,6 +244,9 @@ public: break; case DEC_FLOAT_4: memcpy(color, data_ + decFmt_.c0off, 16); break; + default: + ERROR_LOG(G3D, "Reader: Unsupported C0 Format"); + break; } } @@ -249,6 +261,9 @@ public: break; case DEC_FLOAT_4: memcpy(color, data_ + decFmt_.c1off, 16); break; + default: + ERROR_LOG(G3D, "Reader: Unsupported C1 Format"); + break; } } @@ -258,12 +273,18 @@ public: case DEC_FLOAT_2: memcpy(weights, data_ + decFmt_.w0off, 8); break; case DEC_FLOAT_3: memcpy(weights, data_ + decFmt_.w0off, 12); break; case DEC_FLOAT_4: memcpy(weights, data_ + decFmt_.w0off, 16); break; + default: + ERROR_LOG(G3D, "Reader: Unsupported W0 Format"); + break; } switch (decFmt_.w1fmt) { case DEC_FLOAT_1: memcpy(weights + 4, data_ + decFmt_.w1off, 4); break; case DEC_FLOAT_2: memcpy(weights + 4, data_ + decFmt_.w1off, 8); break; case DEC_FLOAT_3: memcpy(weights + 4, data_ + decFmt_.w1off, 12); break; case DEC_FLOAT_4: memcpy(weights + 4, data_ + decFmt_.w1off, 16); break; + default: + ERROR_LOG(G3D, "Reader: Unsupported W1 Format"); + break; } } From 39cae09eaddf0d512971e48d65735b8399558997 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 15:06:38 +0100 Subject: [PATCH 034/276] Change some warn logging to debug logging, it's fine --- Core/HLE/sceAudio.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index bcfcb6300c..fcb869687c 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -288,7 +288,7 @@ u32 sceAudioEnd() u32 sceAudioOutput2Reserve(u32 sampleCount) { - ERROR_LOG(HLE,"sceAudioOutput2Reserve(%i)", sampleCount); + DEBUG_LOG(HLE,"sceAudioOutput2Reserve(%i)", sampleCount); chans[0].sampleCount = sampleCount; chans[0].reserved = true; return 0; @@ -305,20 +305,20 @@ u32 sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) u32 sceAudioOutput2ChangeLength(u32 sampleCount) { - WARN_LOG(HLE,"sceAudioOutput2ChangeLength(%i)", sampleCount); + DEBUG_LOG(HLE,"sceAudioOutput2ChangeLength(%i)", sampleCount); chans[0].sampleCount = sampleCount; return 0; } u32 sceAudioOutput2GetRestSample() { - WARN_LOG(HLE,"UNTESTED sceAudioOutput2GetRestSample()"); + DEBUG_LOG(HLE,"UNTESTED sceAudioOutput2GetRestSample()"); return chans[0].sampleQueue.size() * 2; } u32 sceAudioOutput2Release() { - WARN_LOG(HLE,"sceAudioOutput2Release()"); + DEBUG_LOG(HLE,"sceAudioOutput2Release()"); chans[0].reserved = false; return 0; } From 8104a4af5bf9b6caf7da709f58433f6aa65fcd6f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 15:23:15 +0100 Subject: [PATCH 035/276] Prettify logging of context switches --- Core/HLE/sceKernelThread.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 2f119152a4..c6b608da39 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1739,14 +1739,22 @@ ThreadWaitInfo Thread::getWaitInfo() void __KernelSwitchContext(Thread *target, const char *reason) { + u32 oldPC = 0; + u32 oldUID = 0; + const char *oldName = "(none)"; if (currentThread) // It might just have been deleted. { __KernelSaveContext(¤tThread->context); - DEBUG_LOG(HLE,"Context saved (%s): %i - %s - pc: %08x", reason, currentThread->GetUID(), currentThread->GetName(), currentMIPS->pc); + oldPC = currentMIPS->pc; + oldUID = currentThread->GetUID(); + oldName = currentThread->GetName(); } currentThread = target; __KernelLoadContext(¤tThread->context); - DEBUG_LOG(HLE,"Context loaded (%s): %i - %s - pc: %08x", reason, currentThread->GetUID(), currentThread->GetName(), currentMIPS->pc); + DEBUG_LOG(HLE,"Context switched: %s -> %s (%s) (%i - pc: %08x -> %i - pc: %08)", + oldName, currentThread->GetName(), + reason, + oldUID, oldPC, currentThread->GetUID(), currentMIPS->pc); // No longer waiting. currentThread->nt.waitType = WAITTYPE_NONE; From 7d949bbee04e08c6e9835e1f95162f6941bb8882 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 16:03:40 +0100 Subject: [PATCH 036/276] VertexDecoder: Respect lowerbound of verts to transform. Make decoding a little safer. --- GPU/GLES/VertexDecoder.cpp | 95 ++++++++++++++------------------------ 1 file changed, 35 insertions(+), 60 deletions(-) diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index fee736172c..ffc8b7aa0f 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -74,7 +74,7 @@ int DecFmtSize(u8 fmt) { return 0; } } - +#if 0 // This is what the software transform spits out, and thus w DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { DecVtxFormat tfm = {0}; @@ -103,6 +103,7 @@ DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { tfm.stride = offset; return tfm; } +#endif void VertexDecoder::Step_WeightsU8() const { @@ -110,7 +111,6 @@ void VertexDecoder::Step_WeightsU8() const const u8 *wdata = (const u8*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = (float)wdata[j] / 128.0f; - decoded_ += nweights * sizeof(float); } void VertexDecoder::Step_WeightsU16() const @@ -119,7 +119,6 @@ void VertexDecoder::Step_WeightsU16() const const u16 *wdata = (const u16*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = (float)wdata[j] / 32768.0f; - decoded_ += nweights * sizeof(float); } void VertexDecoder::Step_WeightsFloat() const @@ -128,7 +127,6 @@ void VertexDecoder::Step_WeightsFloat() const const float *wdata = (const float*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = wdata[j]; - decoded_ += nweights * sizeof(float); } void VertexDecoder::Step_TcU8() const @@ -137,7 +135,6 @@ void VertexDecoder::Step_TcU8() const const u8 *uvdata = (const u8*)(ptr_ + tcoff); for (int j = 0; j < 2; j++) uv[j] = (float)uvdata[j] / 128.0f; - decoded_ += 2 * sizeof(float); } void VertexDecoder::Step_TcU16() const @@ -146,7 +143,6 @@ void VertexDecoder::Step_TcU16() const const u16 *uvdata = (const u16*)(ptr_ + tcoff); uv[0] = (float)uvdata[0] / 32768.0f; uv[1] = (float)uvdata[1] / 32768.0f; - decoded_ += 2 * sizeof(float); } void VertexDecoder::Step_TcU16Through() const @@ -155,7 +151,6 @@ void VertexDecoder::Step_TcU16Through() const const u16 *uvdata = (const u16*)(ptr_ + tcoff); uv[0] = (float)uvdata[0] / (float)(gstate_c.curTextureWidth); uv[1] = (float)uvdata[1] / (float)(gstate_c.curTextureHeight); - decoded_ += 2 * sizeof(float); } void VertexDecoder::Step_TcFloat() const @@ -164,7 +159,6 @@ void VertexDecoder::Step_TcFloat() const const float *uvdata = (const float*)(ptr_ + tcoff); uv[0] = uvdata[0]; uv[1] = uvdata[1]; - decoded_ += 2 * sizeof(float); } void VertexDecoder::Step_TcFloatThrough() const @@ -173,48 +167,43 @@ void VertexDecoder::Step_TcFloatThrough() const const float *uvdata = (const float*)(ptr_ + tcoff); uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth); uv[1] = uvdata[1] / (float)(gstate_c.curTextureHeight); - decoded_ += 2 * sizeof(float); } void VertexDecoder::Step_Color565() const { - u8 *c = decoded_; + u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16*)(ptr_ + coloff); c[0] = Convert5To8(cdata & 0x1f); c[1] = Convert6To8((cdata>>5) & 0x3f); c[2] = Convert5To8((cdata>>11) & 0x1f); c[3] = 1.0f; - decoded_ += 4; } void VertexDecoder::Step_Color5551() const { - u8 *c = decoded_; + u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16*)(ptr_ + coloff); c[0] = Convert5To8(cdata & 0x1f); c[1] = Convert5To8((cdata>>5) & 0x1f); c[2] = Convert5To8((cdata>>10) & 0x1f); c[3] = (cdata>>15) ? 255 : 0; - decoded_ += 4; } void VertexDecoder::Step_Color4444() const { - u8 *c = decoded_; + u8 *c = decoded_ + decFmt.c0off; u16 cdata = *(u16*)(ptr_ + coloff); for (int j = 0; j < 4; j++) c[j] = Convert4To8((cdata >> (j * 4)) & 0xF); - decoded_ += 4; } void VertexDecoder::Step_Color8888() const { - u8 *c = decoded_; + u8 *c = decoded_ + decFmt.c0off; // TODO: speedup - u8 *cdata = (u8*)(ptr_ + coloff); + const u8 *cdata = (const u8*)(ptr_ + coloff); for (int j = 0; j < 4; j++) c[j] = cdata[j]; - decoded_ += 4; } void VertexDecoder::Step_Color565Morph() const @@ -228,11 +217,11 @@ void VertexDecoder::Step_Color565Morph() const col[1] += w * ((cdata>>5) & 0x3f) / 63.f; col[2] += w * ((cdata>>11) & 0x1f) / 31.f; } + u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 3; i++) { - decoded_[i] = (u8)(col[i] * 255.0f); + c[i] = (u8)(col[i] * 255.0f); } - decoded_[3] = 255; - decoded_ += 4; + c[3] = 255; } void VertexDecoder::Step_Color5551Morph() const @@ -247,10 +236,10 @@ void VertexDecoder::Step_Color5551Morph() const col[2] += w * ((cdata>>10) & 0x1f) / 31.f; col[3] += w * (cdata>>15) ? 1.0f : 0.0f; } + u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 4; i++) { - decoded_[i] = (u8)(col[i] * 255.0f); + c[i] = (u8)(col[i] * 255.0f); } - decoded_ += 4; } void VertexDecoder::Step_Color4444Morph() const @@ -263,10 +252,10 @@ void VertexDecoder::Step_Color4444Morph() const for (int j = 0; j < 4; j++) col[j] += w * ((cdata >> (j * 4)) & 0xF) / 15.f; } + u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 4; i++) { - decoded_[i] = (u8)(col[i] * 255.0f); + c[i] = (u8)(col[i] * 255.0f); } - decoded_ += 4; } void VertexDecoder::Step_Color8888Morph() const @@ -279,51 +268,48 @@ void VertexDecoder::Step_Color8888Morph() const for (int j = 0; j < 4; j++) col[j] += w * cdata[j]; } + u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 4; i++) { - decoded_[i] = (u8)(col[i]); + c[i] = (u8)(col[i]); } - decoded_ += 4; } void VertexDecoder::Step_NormalS8() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); float multiplier = 1.0f; if (gstate.reversenormals & 0xFFFFFF) multiplier = -multiplier; const s8 *sv = (const s8*)(ptr_ + nrmoff); for (int j = 0; j < 3; j++) - normal[j] = (sv[j]/127.0f) * multiplier; - decoded_ += 12; + normal[j] = (sv[j] / 127.0f) * multiplier; } void VertexDecoder::Step_NormalS16() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); float multiplier = 1.0f; if (gstate.reversenormals & 0xFFFFFF) multiplier = -multiplier; const short *sv = (const short*)(ptr_ + nrmoff); for (int j = 0; j < 3; j++) - normal[j] = (sv[j]/32767.0f) * multiplier; - decoded_ += 12; + normal[j] = (sv[j] / 32767.0f) * multiplier; } void VertexDecoder::Step_NormalFloat() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); float multiplier = 1.0f; if (gstate.reversenormals & 0xFFFFFF) multiplier = -multiplier; const float *fv = (const float*)(ptr_ + nrmoff); for (int j = 0; j < 3; j++) normal[j] = fv[j] * multiplier; - decoded_ += 12; } void VertexDecoder::Step_NormalS8Morph() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); memset(normal, 0, sizeof(float)*3); for (int n = 0; n < morphcount; n++) { @@ -335,12 +321,11 @@ void VertexDecoder::Step_NormalS8Morph() const for (int j = 0; j < 3; j++) normal[j] += (sv[j]/32767.0f) * multiplier; } - decoded_ += 12; } void VertexDecoder::Step_NormalS16Morph() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); memset(normal, 0, sizeof(float)*3); for (int n = 0; n < morphcount; n++) { @@ -352,12 +337,11 @@ void VertexDecoder::Step_NormalS16Morph() const for (int j = 0; j < 3; j++) normal[j] += fv[j] * multiplier; } - decoded_ += 12; } void VertexDecoder::Step_NormalFloatMorph() const { - float *normal = (float *)decoded_; + float *normal = (float *)(decoded_ + decFmt.nrmoff); memset(normal, 0, sizeof(float)*3); for (int n = 0; n < morphcount; n++) { @@ -369,80 +353,72 @@ void VertexDecoder::Step_NormalFloatMorph() const for (int j = 0; j < 3; j++) normal[j] += fv[j] * multiplier; } - decoded_ += 12; } void VertexDecoder::Step_PosS8() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); float multiplier = 1.0f / 127.0f; const s8 *sv = (const s8*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = sv[j] * multiplier; - decoded_ += 12; } void VertexDecoder::Step_PosS16() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); float multiplier = 1.0f / 32767.0f; const short *sv = (const short*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = sv[j] * multiplier; - decoded_ += 12; } void VertexDecoder::Step_PosFloat() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); const float *fv = (const float*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = fv[j]; - decoded_ += 12; } void VertexDecoder::Step_PosS8Through() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); const s8 *sv = (const s8*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = sv[j]; - decoded_ += 12; } void VertexDecoder::Step_PosS16Through() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); const short *sv = (const short*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = sv[j]; - decoded_ += 12; } void VertexDecoder::Step_PosFloatThrough() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); const float *fv = (const float*)(ptr_ + posoff); for (int j = 0; j < 3; j++) v[j] = fv[j]; - decoded_ += 12; } void VertexDecoder::Step_PosS8Morph() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); memset(v, 0, sizeof(float) * 3); for (int n = 0; n < morphcount; n++) { const s8 *sv = (const s8*)(ptr_ + onesize_*n + posoff); for (int j = 0; j < 3; j++) v[j] += (sv[j] / 127.f) * gstate_c.morphWeights[n]; } - decoded_ += 12; } void VertexDecoder::Step_PosS16Morph() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); memset(v, 0, sizeof(float) * 3); for (int n = 0; n < morphcount; n++) { float multiplier = 1.0f / 32767.0f; @@ -450,19 +426,17 @@ void VertexDecoder::Step_PosS16Morph() const for (int j = 0; j < 3; j++) v[j] += (sv[j] * multiplier) * gstate_c.morphWeights[n]; } - decoded_ += 12; } void VertexDecoder::Step_PosFloatMorph() const { - float *v = (float *)decoded_; + float *v = (float *)(decoded_ + decFmt.posoff); memset(v, 0, sizeof(float) * 3); for (int n = 0; n < morphcount; n++) { const float *fv = (const float*)(ptr_ + onesize_*n + posoff); for (int j = 0; j < 3; j++) v[j] += fv[j] * gstate_c.morphWeights[n]; } - decoded_ += 12; } const StepFunction wtstep[4] = { @@ -700,7 +674,7 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *i *indexUpperBound = upperBound; // Decode the vertices within the found bounds, once each - decoded_ = decodedptr; + decoded_ = decodedptr + lowerBound * decFmt.stride; ptr_ = (const u8*)verts + lowerBound * size; for (int index = lowerBound; index <= upperBound; index++) { @@ -708,6 +682,7 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *i ((*this).*steps_[i])(); } ptr_ += size; + decoded_ += decFmt.stride; } } From c3b778daab029440ecde527e38dea45edb6fafc6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 18:31:21 +0100 Subject: [PATCH 037/276] More work on hw transform. --- GPU/GLES/DisplayListInterpreter.cpp | 16 ++++++ GPU/GLES/ShaderManager.cpp | 48 +++++++++++++++++ GPU/GLES/ShaderManager.h | 23 ++++++-- GPU/GLES/TransformPipeline.cpp | 12 ++--- GPU/GLES/VertexDecoder.cpp | 16 +++--- GPU/GLES/VertexShaderGenerator.cpp | 83 ++++++++++++++++++++++------- 6 files changed, 158 insertions(+), 40 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index cc772c2ac9..3f317513eb 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -851,14 +851,20 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_MATERIALDIFFUSE: DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: @@ -869,6 +875,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_MATERIALSPECULARCOEF: DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); + if (diff) + shaderManager.DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_LIGHTTYPE0: @@ -889,6 +897,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) float val = getFloat24(data); DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); gstate_c.lightpos[l][c] = val; + if (diff) + shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -903,6 +913,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) float val = getFloat24(data); DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); gstate_c.lightdir[l][c] = val; + if (diff) + shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -917,6 +929,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) float val = getFloat24(data); DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); gstate_c.lightatt[l][c] = val; + if (diff) + shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -934,6 +948,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) gstate_c.lightColor[t][l].r = r; gstate_c.lightColor[t][l].g = g; gstate_c.lightColor[t][l].b = b; + if (diff) + shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); } break; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 53e994161b..3b4e6691e6 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -92,9 +92,29 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) } // Lighting, texturing + u_ambient = glGetUniformLocation(program, "u_ambient"); u_matambientalpha = glGetUniformLocation(program, "u_matambientalpha"); + u_matdiffuse = glGetUniformLocation(program, "u_matdiffuse"); + u_matspecular = glGetUniformLocation(program, "u_matspecular"); + u_matemissive = glGetUniformLocation(program, "u_matemissive"); u_uvscaleoffset = glGetUniformLocation(program, "u_uvscaleoffset"); + for (int i = 0; i < 4; i++) { + char temp[64]; + sprintf(temp, "u_lightpos%i", i); + u_lightpos[i] = glGetUniformLocation(program, temp); + sprintf(temp, "u_lightdir%i", i); + u_lightdir[i] = glGetUniformLocation(program, temp); + sprintf(temp, "u_lightatt%i", i); + u_lightatt[i] = glGetUniformLocation(program, temp); + sprintf(temp, "u_lightambient%i", i); + u_lightambient[i] = glGetUniformLocation(program, temp); + sprintf(temp, "u_lightdiffuse%i", i); + u_lightdiffuse[i] = glGetUniformLocation(program, temp); + sprintf(temp, "u_lightspecular%i", i); + u_lightspecular[i] = glGetUniformLocation(program, temp); + } + a_position = glGetAttribLocation(program, "a_position"); a_color0 = glGetAttribLocation(program, "a_color0"); a_color1 = glGetAttribLocation(program, "a_color1"); @@ -127,6 +147,12 @@ static void SetColorUniform3Alpha(int uniform, u32 color, u8 alpha) glUniform4fv(uniform, 1, col); } +static void SetColorUniform3ExtraFloat(int uniform, u32 color, float extra) +{ + const float col[4] = { ((color & 0xFF0000) >> 16) / 255.0f, ((color & 0xFF00) >> 8) / 255.0f, ((color & 0xFF)) / 255.0f, extra}; + glUniform4fv(uniform, 1, col); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); @@ -192,10 +218,32 @@ void LinkedShader::use() { } // Lighting + if (u_ambient != -1 && (dirtyUniforms & DIRTY_MATDIFFUSE)) { + SetColorUniform3Alpha(u_ambient, gstate.ambientcolor, gstate.ambientalpha & 0xFF); + } if (u_matambientalpha != -1 && (dirtyUniforms & DIRTY_MATAMBIENTALPHA)) { SetColorUniform3Alpha(u_matambientalpha, gstate.materialambient, gstate.materialalpha & 0xFF); } + if (u_matdiffuse != -1 && (dirtyUniforms & DIRTY_MATDIFFUSE)) { + SetColorUniform3(u_matdiffuse, gstate.materialdiffuse); + } + if (u_matemissive != -1 && (dirtyUniforms & DIRTY_MATEMISSIVE)) { + SetColorUniform3(u_matemissive, gstate.materialemissive); + } + if (u_matspecular != -1 && (dirtyUniforms & DIRTY_MATSPECULAR)) { + SetColorUniform3ExtraFloat(u_matemissive, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); + } + for (int i = 0; i < 4; i++) { + if (u_lightdiffuse[i] != -1 && (dirtyUniforms & (DIRTY_LIGHT0 << i))) { + glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]); + glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]); + glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]); + glUniform3fv(u_lightambient[i], 1, &gstate_c.lightColor[0][i].r); + glUniform3fv(u_lightdiffuse[i], 1, &gstate_c.lightColor[1][i].r); + glUniform3fv(u_lightspecular[i], 1, &gstate_c.lightColor[2][i].r); + } + } dirtyUniforms = 0; } diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index e18219bf18..6b1a480bc5 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -62,8 +62,17 @@ struct LinkedShader int u_uvscaleoffset; // Lighting + int u_ambient; int u_matambientalpha; - int u_light[4]; // each light consist of vec4[3] + int u_matdiffuse; + int u_matspecular; + int u_matemissive; + int u_lightpos[4]; + int u_lightdir[4]; + int u_lightatt[4]; // attenuation + int u_lightdiffuse[4]; // each light consist of vec4[3] + int u_lightspecular[4]; // attenuation + int u_lightambient[4]; // attenuation }; // Will reach 32 bits soon :P @@ -77,11 +86,15 @@ enum DIRTY_ALPHACOLORREF = (1 << 5), DIRTY_COLORREF = (1 << 6), - DIRTY_LIGHT0 = (1 << 12), - DIRTY_LIGHT1 = (1 << 13), - DIRTY_LIGHT2 = (1 << 14), - DIRTY_LIGHT3 = (1 << 15), + DIRTY_LIGHT0 = (1 << 8), + DIRTY_LIGHT1 = (1 << 9), + DIRTY_LIGHT2 = (1 << 10), + DIRTY_LIGHT3 = (1 << 11), + DIRTY_MATDIFFUSE = (1 << 12), + DIRTY_MATSPECULAR = (1 << 13), + DIRTY_MATEMISSIVE = (1 << 14), + DIRTY_AMBIENT = (1 << 15), DIRTY_MATAMBIENTALPHA = (1 << 16), DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares" diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index f03c3262ac..48656df277 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -64,7 +64,7 @@ private: Color4 materialDiffuse; Color4 materialSpecular; float specCoef_; - Vec3 viewer_; + // Vec3 viewer_; bool doShadeMapping_; int materialUpdate_; }; @@ -87,7 +87,7 @@ Lighter::Lighter() { materialSpecular.GetFromRGB(gstate.materialspecular); materialSpecular.a = 1.0f; specCoef_ = getFloat24(gstate.materialspecularcoef); - viewer_ = Vec3(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); + // viewer_ = Vec3(-gstate.viewMatrix[9], -gstate.viewMatrix[10], -gstate.viewMatrix[11]); materialUpdate_ = gstate.materialupdate & 7; } @@ -322,7 +322,7 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for { // We do software T&L for now float out[3], norm[3]; - float pos[3], nrm[3]; + float pos[3], nrm[3] = {0}; reader.ReadPos(pos); if (reader.hasNormal()) reader.ReadNrm(nrm); @@ -339,12 +339,6 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for else { float weights[8]; - reader.ReadPos(pos); - if (reader.hasNormal()) { - reader.ReadNrm(nrm); - } else { - memset(nrm, 0, 12); - } reader.ReadWeights(weights); // Skinning Vec3 psum(0,0,0); diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index ffc8b7aa0f..dce69038f7 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -107,7 +107,7 @@ DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt) { void VertexDecoder::Step_WeightsU8() const { - float *wt = (float *)decoded_; + float *wt = (float *)(decoded_ + decFmt.w0off); const u8 *wdata = (const u8*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = (float)wdata[j] / 128.0f; @@ -115,7 +115,7 @@ void VertexDecoder::Step_WeightsU8() const void VertexDecoder::Step_WeightsU16() const { - float *wt = (float *)decoded_; + float *wt = (float *)(decoded_ + decFmt.w0off); const u16 *wdata = (const u16*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = (float)wdata[j] / 32768.0f; @@ -123,7 +123,7 @@ void VertexDecoder::Step_WeightsU16() const void VertexDecoder::Step_WeightsFloat() const { - float *wt = (float *)decoded_; + float *wt = (float *)(decoded_ + decFmt.w0off); const float *wdata = (const float*)(ptr_); for (int j = 0; j < nweights; j++) wt[j] = wdata[j]; @@ -131,7 +131,7 @@ void VertexDecoder::Step_WeightsFloat() const void VertexDecoder::Step_TcU8() const { - float *uv = (float *)decoded_; + float *uv = (float *)(decoded_ + decFmt.uvoff); const u8 *uvdata = (const u8*)(ptr_ + tcoff); for (int j = 0; j < 2; j++) uv[j] = (float)uvdata[j] / 128.0f; @@ -139,7 +139,7 @@ void VertexDecoder::Step_TcU8() const void VertexDecoder::Step_TcU16() const { - float *uv = (float *)decoded_; + float *uv = (float *)(decoded_ + decFmt.uvoff); const u16 *uvdata = (const u16*)(ptr_ + tcoff); uv[0] = (float)uvdata[0] / 32768.0f; uv[1] = (float)uvdata[1] / 32768.0f; @@ -147,7 +147,7 @@ void VertexDecoder::Step_TcU16() const void VertexDecoder::Step_TcU16Through() const { - float *uv = (float *)decoded_; + float *uv = (float *)(decoded_ + decFmt.uvoff); const u16 *uvdata = (const u16*)(ptr_ + tcoff); uv[0] = (float)uvdata[0] / (float)(gstate_c.curTextureWidth); uv[1] = (float)uvdata[1] / (float)(gstate_c.curTextureHeight); @@ -155,7 +155,7 @@ void VertexDecoder::Step_TcU16Through() const void VertexDecoder::Step_TcFloat() const { - float *uv = (float *)decoded_; + float *uv = (float *)(decoded_ + decFmt.uvoff); const float *uvdata = (const float*)(ptr_ + tcoff); uv[0] = uvdata[0]; uv[1] = uvdata[1]; @@ -163,7 +163,7 @@ void VertexDecoder::Step_TcFloat() const void VertexDecoder::Step_TcFloatThrough() const { - float *uv = (float *)decoded_; + float *uv = (float *)(decoded_ + decFmt.uvoff); const float *uvdata = (const float*)(ptr_ + tcoff); uv[0] = uvdata[0] / (float)(gstate_c.curTextureWidth); uv[1] = uvdata[1] / (float)(gstate_c.curTextureHeight); diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 92c6eb9c3f..27b52449bf 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -85,6 +85,11 @@ void ComputeVertexShaderID(VertexShaderID *id, int prim) id->d[0] |= (gstate.getNumBoneWeights() - 1) << 22; // Light bits + for (int i = 0; i < 4; i++) { + id->d[1] |= (gstate.ltype[i] & 3) << (i * 4); + id->d[1] |= ((gstate.ltype[i] >> 8) & 3) << (i * 4 + 2); + } + id->d[1] |= (gstate.materialupdate & 7) << 16; } // Bits that we will need: @@ -101,7 +106,7 @@ void WriteLight(char *p, int l) { } const char *boneWeightAttrDecl[8] = { - "#ERROR", + "attribute float a_weight0123;\n", "attribute vec2 a_weight0123;\n", "attribute vec3 a_weight0123;\n", "attribute vec4 a_weight0123;\n", @@ -198,6 +203,28 @@ char *GenerateVertexShader(int prim) WRITE(p, "uniform mat4x3 u_bone%i;\n", i); } } + if (gstate.lightingEnable & 1) { + WRITE(p, "uniform vec4 u_ambient;\n"); + if ((gstate.materialupdate & 2) == 0) + WRITE(p, "uniform vec3 u_matdiffuse;\n"); + // if ((gstate.materialupdate & 4) == 0) + WRITE(p, "uniform vec4 u_matspecular;\n"); // Specular coef is contained in alpha + WRITE(p, "uniform vec3 u_matemissive;\n"); + } + for (int i = 0; i < 4; i++) { + if (doLight[i] != LIGHT_OFF) { + // These are needed for dot product only (for shade mapping) + WRITE(p, "uniform vec3 u_lightpos%i;\n", i); + WRITE(p, "uniform vec3 u_lightdir%i;\n", i); + WRITE(p, "uniform vec3 u_lightatt%i;\n", i); + } + if (doLight[i] == LIGHT_FULL) { + // These are needed for the full thing + WRITE(p, "uniform vec3 u_lightambient%i;\n", i); + WRITE(p, "uniform vec3 u_lightdiffuse%i;\n", i); + WRITE(p, "uniform vec3 u_lightspecular%i;\n", i); + } + } } WRITE(p, "varying vec4 v_color0;\n"); @@ -239,9 +266,13 @@ char *GenerateVertexShader(int prim) WRITE(p, " vec3 worldnormal = vec3(0.0, 0.0, 0.0);\n"); int numWeights = 1 + ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); for (int i = 0; i < numWeights; i++) { - WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0));\n", boneWeightAttr[i], i); + const char *weightAttr = boneWeightAttr[i]; + // workaround for "cant do .x of scalar" issue + if (numWeights == 1 && i == 0) weightAttr = "a_weight0123"; + if (numWeights == 5 && i == 4) weightAttr = "a_weight4567"; + WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0));\n", weightAttr, i); if (hasNormal) - WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0));\n", boneWeightAttr[i], i); + WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0));\n", weightAttr, i); } // Finally, multiply by world matrix (yes, we have to). WRITE(p, " worldpos = u_world * vec4(worldpos, 1.0);\n"); @@ -251,23 +282,21 @@ char *GenerateVertexShader(int prim) // Step 2: Color/Lighting if (hasColor) { - WRITE(p, " vec4 unlitColor = a_color0;\n"); + WRITE(p, " vec3 unlitColor = a_color0.rgb;\n"); } else { - WRITE(p, " vec4 unlitColor(1.0, 1.0, 1.0, 1.0);\n"); + WRITE(p, " vec3 unlitColor = vec3(1.0, 1.0, 1.0);\n"); } - // TODO: Declare variables for dots for shade mapping if needed. - const char *ambient = (gstate.materialupdate & 1) ? "a_color0" : "u_ambientalpha"; - const char *diffuse = (gstate.materialupdate & 2) ? "a_color0" : "u_matdiffuse"; - const char *specular = (gstate.materialupdate & 4) ? "a_color0" : "u_matspecular"; + const char *ambient = (gstate.materialupdate & 1) ? "unlitColor" : "u_matambientalpha.rgb"; + const char *diffuse = (gstate.materialupdate & 2) ? "unlitColor" : "u_matdiffuse"; + const char *specular = (gstate.materialupdate & 4) ? "unlitColor" : "u_matspecular"; if (gstate.lightingEnable & 1) { WRITE(p, " vec4 lightSum0 = vec4(0.0);\n"); WRITE(p, " vec3 lightSum1 = vec3(0.0);\n"); } - /* // Calculate lights if needed. If shade mapping is enabled, lights may need to be // at least partially calculated for (int i = 0; i < 4; i++) { @@ -285,15 +314,33 @@ char *GenerateVertexShader(int prim) bool doSpecular = (comp != GE_LIGHTCOMP_ONLYDIFFUSE); bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE; - WRITE(p, " float dot%i = dot(tolight, worldnormal);"); + WRITE(p, " float dot%i = dot(toLight%i, worldnormal);\n", i, i); + if (poweredDiffuse) { + WRITE(p, " dot%i = pow(dot%i, materialspecular.a);\n"); + } + if (doLight[i] == LIGHT_DOTONLY) continue; // Actually, might want specular dot.... TODO - }*/ + WRITE(p, " float lightScale%i = 1.0f;\n", i); + if (type != GE_LIGHTTYPE_DIRECTIONAL) { + // Attenuation + WRITE(p, " float distance = length(toLight%i);\n", i); + WRITE(p, " lightScale%i = dot(u_lightatt%i, vec3(1.0, distance, distance*distance));\n", i, i); + } + WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (dot%i * lightScale%i);\n", i, i, diffuse, i, i); + if (doSpecular) { + WRITE(p, " vec3 halfVec%i = normalize(toLight%i + vec3(0, 0, 1));\n", i, i); + WRITE(p, " dot%i = dot(halfVec%i, worldnormal);\n", i); + WRITE(p, " if (dot%i > 0.0)\n", i); + WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot, materialspecular.a) * lightScale);\n", i); + } + WRITE(p, " lightSum0 += vec4(u_lightambient%i, 0.0) + diffuse%i;\n", i, i); + } - if (false && (gstate.lightingEnable & 1)) { + if (gstate.lightingEnable & 1) { // Sum up ambient, emissive here. - WRITE(p, " v_color0 = lightSum0 + u_ambient * %s + u_matemissive;\n", ambient); + WRITE(p, " v_color0 = lightSum0 + u_ambient * vec4(%s, 1.0) + vec4(u_matemissive, 0.0);\n", ambient); if (lmode) { WRITE(p, " v_color1 = lightSum1;\n"); } else { @@ -302,7 +349,7 @@ char *GenerateVertexShader(int prim) } else { // Lighting doesn't affect color. if (hasColor) { - WRITE(p, " v_color0 = unlitColor;\n"); + WRITE(p, " v_color0 = a_color0;\n"); } else { WRITE(p, " v_color0 = u_matambientalpha;\n"); } @@ -326,14 +373,14 @@ char *GenerateVertexShader(int prim) WRITE(p, " vec3 temp_tc = vec3(a_texcoord.xy, 0.0);\n"); break; case 2: // Use normalized transformed normal as source - WRITE(p, " vec3 temp_tc = normalize(v_normal);\n"); + WRITE(p, " vec3 temp_tc = normalize(worldnormal);\n"); break; case 3: // Use non-normalized transformed normal as source - WRITE(p, " vec3 temp_tc = normalize(v_normal);\n"); + WRITE(p, " vec3 temp_tc = worldnormal;\n"); break; } // Transform by texture matrix - WRITE(p, " v_texcoord = (u_texmtx * temp_tc).xy;\n"); + WRITE(p, " v_texcoord = (u_texmtx * vec4(temp_tc, 1.0)).xy;\n"); break; case 2: // Shade mapping - use dots from light sources. From c279b88e28a33170a89a9d48bc16468c0e04e170 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 22:44:28 +0100 Subject: [PATCH 038/276] Add check for invalid VAG audio addresses --- Core/HLE/sceSas.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index c19ae2c5bd..56dcc7ffbd 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -114,6 +114,11 @@ u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) return ERROR_SAS_INVALID_VOICE; } + if (!Memory::IsValidAddress(vagAddr)) { + ERROR_LOG(HLE, "Ignoring invalid VAG audio address %08x", vagAddr); + return 0; + } + //Real VAG header is 0x30 bytes behind the vagAddr SasVoice &v = sas->voices[voiceNum]; v.type = VOICETYPE_VAG; @@ -126,7 +131,7 @@ u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) 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); + 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; From 1551aea902c652bf60895a549420fa7332bff401 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 22:44:49 +0100 Subject: [PATCH 039/276] HW transform bugfixes --- GPU/GLES/VertexShaderGenerator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 27b52449bf..33dd402490 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -316,7 +316,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " float dot%i = dot(toLight%i, worldnormal);\n", i, i); if (poweredDiffuse) { - WRITE(p, " dot%i = pow(dot%i, materialspecular.a);\n"); + WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n"); } if (doLight[i] == LIGHT_DOTONLY) @@ -325,17 +325,17 @@ char *GenerateVertexShader(int prim) WRITE(p, " float lightScale%i = 1.0f;\n", i); if (type != GE_LIGHTTYPE_DIRECTIONAL) { // Attenuation - WRITE(p, " float distance = length(toLight%i);\n", i); - WRITE(p, " lightScale%i = dot(u_lightatt%i, vec3(1.0, distance, distance*distance));\n", i, i); + WRITE(p, " float distance%i = length(toLight%i);\n", i, i); + WRITE(p, " lightScale%i = dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i));\n", i, i, i, i, i); } WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (dot%i * lightScale%i);\n", i, i, diffuse, i, i); if (doSpecular) { WRITE(p, " vec3 halfVec%i = normalize(toLight%i + vec3(0, 0, 1));\n", i, i); - WRITE(p, " dot%i = dot(halfVec%i, worldnormal);\n", i); + WRITE(p, " dot%i = dot(halfVec%i, worldnormal);\n", i, i); WRITE(p, " if (dot%i > 0.0)\n", i); - WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot, materialspecular.a) * lightScale);\n", i); + WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot%i, u_matspecular.a) * lightScale%i);\n", i, specular, i, i); } - WRITE(p, " lightSum0 += vec4(u_lightambient%i, 0.0) + diffuse%i;\n", i, i); + WRITE(p, " lightSum0 += vec4(u_lightambient%i + diffuse%i, 0.0);\n", i, i); } if (gstate.lightingEnable & 1) { From 79bd4e3d4130c90d1c2a48bd220a6dc610fb45f0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 23:28:58 +0100 Subject: [PATCH 040/276] Lighting fixes (sw + hw) --- GPU/GLES/ShaderManager.cpp | 4 ++-- GPU/GLES/TransformPipeline.cpp | 12 ++++++++---- GPU/GLES/VertexDecoder.h | 2 +- GPU/GLES/VertexShaderGenerator.cpp | 13 +++++++------ 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 3b4e6691e6..e86db1dc34 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -218,7 +218,7 @@ void LinkedShader::use() { } // Lighting - if (u_ambient != -1 && (dirtyUniforms & DIRTY_MATDIFFUSE)) { + if (u_ambient != -1 && (dirtyUniforms & DIRTY_AMBIENT)) { SetColorUniform3Alpha(u_ambient, gstate.ambientcolor, gstate.ambientalpha & 0xFF); } if (u_matambientalpha != -1 && (dirtyUniforms & DIRTY_MATAMBIENTALPHA)) { @@ -231,7 +231,7 @@ void LinkedShader::use() { SetColorUniform3(u_matemissive, gstate.materialemissive); } if (u_matspecular != -1 && (dirtyUniforms & DIRTY_MATSPECULAR)) { - SetColorUniform3ExtraFloat(u_matemissive, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); + SetColorUniform3ExtraFloat(u_matspecular, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); } for (int i = 0; i < 4; i++) { diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 48656df277..eade9e4b7b 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -152,9 +152,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ dot = powf(dot, specCoef_); float lightScale = 1.0f; + float distance = toLight.Normalize(); if (type != GE_LIGHTTYPE_DIRECTIONAL) { - float distance = toLight.Normalize(); lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distance + gstate_c.lightatt[l][2]*distance*distance); if (lightScale > 1.0f) lightScale = 1.0f; } @@ -361,7 +361,6 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for // Yes, we really must multiply by the world matrix too. Vec3ByMatrix43(out, psum.v, gstate.worldMatrix); if (reader.hasNormal()) { - nsum.Normalize(); Norm3ByMatrix43(norm, nsum.v, gstate.worldMatrix); } } @@ -371,6 +370,11 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for float unlitColor[4] = {1, 1, 1, 1}; if (reader.hasColor0()) { reader.ReadColor0(unlitColor); + } else { + unlitColor[0] = (gstate.materialambient & 0xFF) / 255.f; + unlitColor[1] = ((gstate.materialambient >> 8) & 0xFF) / 255.f; + unlitColor[2] = ((gstate.materialambient >> 16) & 0xFF) / 255.f; + unlitColor[3] = (gstate.materialalpha & 0xFF) / 255.f; } float litColor0[4]; float litColor1[4]; @@ -472,7 +476,7 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for memcpy(&transformed[index].x, v, 3 * sizeof(float)); memcpy(&transformed[index].uv, uv, 2 * sizeof(float)); memcpy(&transformed[index].color0, c0, 4 * sizeof(float)); - memcpy(&transformed[index].color1, c1, 4 * sizeof(float)); + memcpy(&transformed[index].color1, c1, 3 * sizeof(float)); } // Step 2: Expand using the index buffer, and expand rectangles. @@ -586,7 +590,7 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer); if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); - if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); + if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); if (drawIndexed) { glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index bc2c14786c..4e5e2ac97f 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -56,7 +56,7 @@ struct TransformedVertex float x, y, z; // in case of morph, preblend during decode float uv[2]; // scaled by uscale, vscale, if there float color0[4]; // prelit - float color1[4]; // prelit + float color1[3]; // prelit }; DecVtxFormat GetTransformedVtxFormat(const DecVtxFormat &fmt); diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 33dd402490..121ec44cc9 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -44,7 +44,7 @@ static char buffer[16384]; bool CanUseHardwareTransform(int prim) { return !gstate.isModeThrough() && false; // prim != GE_PRIM_RECTANGLES; - // return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; + //return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; } // prim so we can special case for RECTANGLES :( @@ -259,7 +259,7 @@ char *GenerateVertexShader(int prim) // No skinning, just standard T&L. WRITE(p, " vec3 worldpos = u_world * vec4(a_position, 1.0);\n"); if (hasNormal) - WRITE(p, " vec3 worldnormal = u_world * vec4(a_normal, 0.0);\n"); + WRITE(p, " vec3 worldnormal = normalize(u_world * vec4(a_normal, 0.0));\n"); } else { WRITE(p, " vec3 worldpos = vec3(0.0, 0.0, 0.0);\n"); if (hasNormal) @@ -314,7 +314,7 @@ char *GenerateVertexShader(int prim) bool doSpecular = (comp != GE_LIGHTCOMP_ONLYDIFFUSE); bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE; - WRITE(p, " float dot%i = dot(toLight%i, worldnormal);\n", i, i); + WRITE(p, " float dot%i = dot(normalize(toLight%i), worldnormal);\n", i, i); if (poweredDiffuse) { WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n"); } @@ -326,14 +326,15 @@ char *GenerateVertexShader(int prim) if (type != GE_LIGHTTYPE_DIRECTIONAL) { // Attenuation WRITE(p, " float distance%i = length(toLight%i);\n", i, i); - WRITE(p, " lightScale%i = dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i));\n", i, i, i, i, i); + WRITE(p, " lightScale%i = 1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i));\n", i, i, i, i, i); + WRITE(p, " if (lightScale%i > 1.0) lightScale%i = 1.0;\n", i, i); } WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (dot%i * lightScale%i);\n", i, i, diffuse, i, i); if (doSpecular) { - WRITE(p, " vec3 halfVec%i = normalize(toLight%i + vec3(0, 0, 1));\n", i, i); + WRITE(p, " vec3 halfVec%i = normalize(normalize(toLight%i) + vec3(0, 0, 1));\n", i, i); WRITE(p, " dot%i = dot(halfVec%i, worldnormal);\n", i, i); WRITE(p, " if (dot%i > 0.0)\n", i); - WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot%i, u_matspecular.a) * lightScale%i);\n", i, specular, i, i); + WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot%i, u_matspecular.a) * (dot%i * lightScale%i));\n", i, specular, i, i, i); } WRITE(p, " lightSum0 += vec4(u_lightambient%i + diffuse%i, 0.0);\n", i, i); } From 19391541fbc68306b07a82051163b682c6a9d0f9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Dec 2012 23:47:10 +0100 Subject: [PATCH 041/276] HW transform: Fix too-harsh lighting --- GPU/GLES/TransformPipeline.cpp | 1 + GPU/GLES/VertexShaderGenerator.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index eade9e4b7b..f618ebb843 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -638,6 +638,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte PSPSetTexture(); useTexCoord = true; } + gstate_c.textureChanged = false; } gpuStats.numDrawCalls++; gpuStats.numVertsTransformed += vertexCount; diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 121ec44cc9..359c46f053 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -329,7 +329,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " lightScale%i = 1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i));\n", i, i, i, i, i); WRITE(p, " if (lightScale%i > 1.0) lightScale%i = 1.0;\n", i, i); } - WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (dot%i * lightScale%i);\n", i, i, diffuse, i, i); + WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (max(dot%i, 0.0) * lightScale%i);\n", i, i, diffuse, i, i); if (doSpecular) { WRITE(p, " vec3 halfVec%i = normalize(normalize(toLight%i) + vec3(0, 0, 1));\n", i, i); WRITE(p, " dot%i = dot(halfVec%i, worldnormal);\n", i, i); From b7ef3ad9e98f1acfad9b9de46e5b284796fba218 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 21 Dec 2012 11:05:53 +0800 Subject: [PATCH 042/276] Implement Vsocp --- Core/MIPS/MIPSIntVFPU.cpp | 23 +++++++++++++++++++++++ Core/MIPS/MIPSIntVFPU.h | 1 + Core/MIPS/MIPSTables.cpp | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index b3045b9a4b..4b25af5631 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -506,6 +506,29 @@ namespace MIPSInt PC += 4; EatPrefixes(); } + + void Int_Vsocp(u32 op) + { + float s[4], d[4]; + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + int n=GetNumVectorElements(sz); + float x = s[0]; + d[0] = std::min(std::max(0.0f, 1.0f - x), 1.0f); + d[1] = std::min(std::max(0.0f, x), 1.0f); + if (n > 1) { + float y = s[1]; + d[2] = std::min(std::max(0.0f, 1.0f - y), 1.0f); + d[3] = std::min(std::max(0.0f, y), 1.0f); + } + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } void Int_Vsgn(u32 op) { diff --git a/Core/MIPS/MIPSIntVFPU.h b/Core/MIPS/MIPSIntVFPU.h index 50e7229366..ebcd1c4362 100644 --- a/Core/MIPS/MIPSIntVFPU.h +++ b/Core/MIPS/MIPSIntVFPU.h @@ -42,6 +42,7 @@ namespace MIPSInt void Int_Vavg(u32 op); void Int_Vfad(u32 op); void Int_Vocp(u32 op); + void Int_Vsocp(u32 op); void Int_Vsgn(u32 op); void Int_Vtfm(u32 op); void Int_Viim(u32 op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 67d9b70e92..93b636f873 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -691,7 +691,7 @@ MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU), //4 INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU), // one's complement - INSTR("vsocp", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), + INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU), INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU), INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU), //8 From aadbe50357dd94e88c9156bc390ec35983dcde99 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 18 Dec 2012 23:47:57 -0800 Subject: [PATCH 043/276] Implement the basic functionality of alarms. They only fire the once though, and the use of subintr might be a bit naive, may need internal funcs. --- Core/HLE/sceKernel.cpp | 8 +-- Core/HLE/sceKernelAlarm.cpp | 100 +++++++++++++++++++++++++++++++----- Core/HLE/sceKernelAlarm.h | 8 +-- 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 9e8fd755db..cb876fc381 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -412,10 +412,10 @@ const HLEFunction ThreadManForUser[] = {0x64D4540E,0,"sceKernelReferThreadProfiler"}, //Fifa Street 2 uses alarms - {0x6652b8ca,sceKernelSetAlarm,"sceKernelSetAlarm"}, - {0xB2C25152,sceKernelSetSysClockAlarm,"sceKernelSetSysClockAlarm"}, - {0x7e65b999,sceKernelCancelAlarm,"sceKernelCancelAlarm"}, - {0xDAA3F564,sceKernelReferAlarmStatus,"sceKernelReferAlarmStatus"}, + {0x6652b8ca,WrapI_UUU,"sceKernelSetAlarm"}, + {0xB2C25152,WrapI_UUU,"sceKernelSetSysClockAlarm"}, + {0x7e65b999,WrapI_I,"sceKernelCancelAlarm"}, + {0xDAA3F564,WrapI_IU,"sceKernelReferAlarmStatus"}, {0xba6b92e2,sceKernelSysClock2USec,"sceKernelSysClock2USec"}, {0x110DEC9A,0,"sceKernelUSec2SysClock"}, diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 8f4cd961b2..ed46393c2e 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -17,28 +17,104 @@ #include "sceKernel.h" #include "sceKernelAlarm.h" +#include "sceKernelInterrupt.h" #include "HLE.h" +#include "../../Core/CoreTiming.h" -void sceKernelSetAlarm() +struct NativeAlarm { - ERROR_LOG(HLE,"UNIMPL sceKernelSetAlarm"); - RETURN(-1); + SceSize size; + u64 schedule; + u32 handlerPtr; + u32 commonPtr; +}; + +struct Alarm : public KernelObject +{ + const char *GetName() {return "[Alarm]";} + const char *GetTypeName() {return "Alarm";} + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; } + int GetIDType() const { return SCE_KERNEL_TMID_Alarm; } + NativeAlarm alm; +}; + +bool alarmInitComplete = false; +int alarmTimer = 0; + +void __KernelTriggerAlarm(u64 userdata, int cyclesLate); + +void __KernelAlarmInit() +{ + alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); + + alarmInitComplete = true; } -void sceKernelSetSysClockAlarm() +void __KernelTriggerAlarm(u64 userdata, int cyclesLate) { - ERROR_LOG(HLE,"UNIMPL sceKernelSetSysClockAlarm"); - RETURN(-1); + int uid = (int) userdata; + + u32 error; + Alarm *alarm = kernelObjects.Get(uid, error); + + // TODO: Need to find out the return value. + if (alarm) + __TriggerInterruptWithArg(PSP_SYSTIMER0_INTR, uid, alarm->alm.commonPtr); } -void sceKernelCancelAlarm() +SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) { - ERROR_LOG(HLE,"UNIMPL sceKernelCancelAlarm"); - RETURN(-1); + if (!alarmInitComplete) + __KernelAlarmInit(); + + Alarm *alarm = new Alarm; + SceUID uid = kernelObjects.Create(alarm); + + alarm->alm.size = sizeof(NativeAlarm); + alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.handlerPtr = handlerPtr; + alarm->alm.commonPtr = commonPtr; + + sceKernelRegisterSubIntrHandler(PSP_SYSTIMER0_INTR, uid, handlerPtr, commonPtr); + sceKernelEnableSubIntr(PSP_SYSTIMER0_INTR, uid); + CoreTiming::ScheduleEvent(ticks, alarmTimer, uid); + + return uid; } -void sceKernelReferAlarmStatus() +SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { - ERROR_LOG(HLE,"UNIMPL sceKernelReferAlarmStatus"); - RETURN(-1); + ERROR_LOG(HLE, "HACK sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles((int) micro), handlerPtr, commonPtr); +} + +SceUID sceKernelSetSysClockAlarm(u32 ticksPtr, u32 handlerPtr, u32 commonPtr) +{ + u64 ticks; + + if (Memory::IsValidAddress(ticksPtr)) + ticks = Memory::Read_U64(ticksPtr); + // TODO: What to do when invalid? + else + return -1; + + ERROR_LOG(HLE, "UNIMPL sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); + // TODO: Is this precise or is this relative? + return __KernelSetAlarm(ticks, handlerPtr, commonPtr); +} + +int sceKernelCancelAlarm(SceUID uid) +{ + DEBUG_LOG(HLE, "sceKernelCancelAlarm(%08x)", uid); + + CoreTiming::UnscheduleEvent(alarmTimer, uid); + sceKernelReleaseSubIntrHandler(PSP_SYSTIMER0_INTR, uid); + + return kernelObjects.Destroy(uid); +} + +int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) +{ + ERROR_LOG(HLE, "UNIMPL sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); + return -1; } \ No newline at end of file diff --git a/Core/HLE/sceKernelAlarm.h b/Core/HLE/sceKernelAlarm.h index 56b004f0fc..f430a20da9 100644 --- a/Core/HLE/sceKernelAlarm.h +++ b/Core/HLE/sceKernelAlarm.h @@ -17,7 +17,7 @@ #pragma once -void sceKernelSetAlarm(); -void sceKernelSetSysClockAlarm(); -void sceKernelCancelAlarm(); -void sceKernelReferAlarmStatus(); \ No newline at end of file +SceUID sceKernelSetAlarm(SceUInt clock, u32 handlerPtr, u32 commonPtr); +SceUID sceKernelSetSysClockAlarm(u32 sysClockPtr, u32 handlerPtr, u32 commonPtr); +int sceKernelCancelAlarm(SceUID uid); +int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); \ No newline at end of file From d6d1f687a8f2bcdeeaa2221423e9800448efac29 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 07:38:35 -0800 Subject: [PATCH 044/276] Make the intr handler public, will need for timers. The idea here is that alarm/vtimers/etc. can implement a subclass to pass more arguments / do whatever they need to. --- Core/HLE/sceKernelInterrupt.cpp | 152 +++++++++++++++----------------- Core/HLE/sceKernelInterrupt.h | 35 ++++++++ 2 files changed, 104 insertions(+), 83 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 7d38ff6802..bc335bbf04 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -35,9 +35,9 @@ struct Interrupt // Yeah, this bit is a bit silly. static int interruptsEnabled = 1; - static bool inInterrupt; + void __InterruptsInit() { interruptsEnabled = 1; @@ -127,74 +127,19 @@ bool __CanExecuteInterrupt() return !inInterrupt; } -class AllegrexInterruptHandler; - -struct PendingInterrupt { - AllegrexInterruptHandler *handler; - int arg; - bool hasArg; -}; - - -class AllegrexInterruptHandler -{ -public: - virtual ~AllegrexInterruptHandler() {} - virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; - virtual void queueUp() = 0; - virtual void queueUpWithArg(int arg) = 0; -}; - -std::list pendingInterrupts; - -class SubIntrHandler : public AllegrexInterruptHandler -{ -public: - SubIntrHandler() {} - virtual void queueUp() - { - if (!enabled) - return; - PendingInterrupt pend; - pend.handler = this; - pend.hasArg = false; - pendingInterrupts.push_back(pend); - } - virtual void queueUpWithArg(int arg) - { - if (!enabled) - return; - PendingInterrupt pend; - pend.handler = this; - pend.arg = arg; - pend.hasArg = true; - pendingInterrupts.push_back(pend); - } - - virtual void copyArgsToCPU(const PendingInterrupt &pend) - { - DEBUG_LOG(CPU, "Entering interrupt handler %08x", handlerAddress); - currentMIPS->pc = handlerAddress; - currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number; - currentMIPS->r[MIPS_REG_A1] = handlerArg; - // RA is already taken care of - } - - bool enabled; - int number; - u32 handlerAddress; - u32 handlerArg; -}; - class IntrHandler { public: - void add(int subIntrNum, SubIntrHandler handler) + void add(int subIntrNum, SubIntrHandler *handler) { subIntrHandlers[subIntrNum] = handler; } void remove(int subIntrNum) { - subIntrHandlers.erase(subIntrNum); + if (has(subIntrNum)) + { + delete subIntrHandlers[subIntrNum]; + subIntrHandlers.erase(subIntrNum); + } } bool has(int subIntrNum) const { @@ -203,7 +148,7 @@ public: SubIntrHandler *get(int subIntrNum) { if (has(subIntrNum)) - return &subIntrHandlers[subIntrNum]; + return subIntrHandlers[subIntrNum]; else return 0; // what to do, what to do... @@ -213,10 +158,10 @@ public: { // Just call execute on all the subintr handlers for this interrupt. // They will get queued up. - for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) + for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) { if (subintr == -1 || iter->first == subintr) - iter->second.queueUp(); + iter->second->queueUp(); } } @@ -224,18 +169,17 @@ public: { // Just call execute on all the subintr handlers for this interrupt. // They will get queued up. - for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) + for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) { if (subintr == -1 || iter->first == subintr) - iter->second.queueUpWithArg(arg); + iter->second->queueUpWithArg(arg); } } private: - std::map subIntrHandlers; + std::map subIntrHandlers; }; - class InterruptState { public: @@ -261,11 +205,43 @@ public: InterruptState intState; IntrHandler intrHandlers[PSP_NUMBER_INTERRUPTS]; +std::list pendingInterrupts; + // http://forums.ps2dev.org/viewtopic.php?t=5687 // http://www.google.se/url?sa=t&rct=j&q=&esrc=s&source=web&cd=7&ved=0CFYQFjAG&url=http%3A%2F%2Fdev.psnpt.com%2Fredmine%2Fprojects%2Fuofw%2Frepository%2Frevisions%2F65%2Fraw%2Ftrunk%2Finclude%2Finterruptman.h&ei=J4pCUKvyK4nl4QSu-YC4Cg&usg=AFQjCNFxJcgzQnv6dK7aiQlht_BM9grfQQ&sig2=GGk5QUEWI6qouYDoyE07YQ +void SubIntrHandler::queueUp() +{ + if (!enabled) + return; + PendingInterrupt pend; + pend.handler = this; + pend.hasArg = false; + pendingInterrupts.push_back(pend); +}; + +void SubIntrHandler::queueUpWithArg(int arg) +{ + if (!enabled) + return; + PendingInterrupt pend; + pend.handler = this; + pend.arg = arg; + pend.hasArg = true; + pendingInterrupts.push_back(pend); +} + +void SubIntrHandler::copyArgsToCPU(const PendingInterrupt &pend) +{ + DEBUG_LOG(CPU, "Entering interrupt handler %08x", handlerAddress); + currentMIPS->pc = handlerAddress; + currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number; + currentMIPS->r[MIPS_REG_A1] = handlerArg; + // RA is already taken care of +} + // Returns true if anything was executed. bool __RunOnePendingInterrupt() @@ -331,6 +307,24 @@ void __KernelReturnFromInterrupt() } } +u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler) +{ + subIntrHandler->number = subIntrNumber; + intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); + return 0; +} + +u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber) +{ + if (!intrHandlers[intrNumber].has(subIntrNumber)) + return -1; + + // TODO: should check if it's pending and remove it from pending list! (although that's probably unlikely) + + intrHandlers[intrNumber].remove(subIntrNumber); + return 0; +} + u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg) { DEBUG_LOG(HLE,"sceKernelRegisterSubIntrHandler(%i, %i, %08x, %08x)", intrNumber, subIntrNumber, handler, handlerArg); @@ -338,29 +332,21 @@ u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handl if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - SubIntrHandler subIntrHandler; - subIntrHandler.number = subIntrNumber; - subIntrHandler.enabled = false; - subIntrHandler.handlerAddress = handler; - subIntrHandler.handlerArg = handlerArg; - intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); - return 0; + SubIntrHandler *subIntrHandler = new SubIntrHandler(); + subIntrHandler->enabled = false; + subIntrHandler->handlerAddress = handler; + subIntrHandler->handlerArg = handlerArg; + return __RegisterSubInterruptHandler(intrNumber, subIntrNumber, subIntrHandler); } u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) { DEBUG_LOG(HLE,"sceKernelReleaseSubIntrHandler(%i, %i)", PARAM(0), PARAM(1)); - // TODO: should check if it's pending and remove it from pending list! (although that's probably unlikely) - if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - if (!intrHandlers[intrNumber].has(subIntrNumber)) - return -1; - - intrHandlers[intrNumber].remove(subIntrNumber); - return 0; + return __ReleaseSubInterruptHandler(intrNumber, subIntrNumber); } u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index adc13e5bcd..87228f4d55 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -54,6 +54,38 @@ enum PSPGeSubInterrupts { PSP_GE_SUBINTR_SIGNAL = 15 }; +class AllegrexInterruptHandler; + +struct PendingInterrupt { + AllegrexInterruptHandler *handler; + int arg; + bool hasArg; +}; + + +class AllegrexInterruptHandler +{ +public: + virtual ~AllegrexInterruptHandler() {} + virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; + virtual void queueUp() = 0; + virtual void queueUpWithArg(int arg) = 0; +}; + +class SubIntrHandler : public AllegrexInterruptHandler +{ +public: + SubIntrHandler() {} + virtual void queueUp(); + virtual void queueUpWithArg(int arg); + virtual void copyArgsToCPU(const PendingInterrupt &pend); + + bool enabled; + int number; + u32 handlerAddress; + u32 handlerArg; +}; + bool __IsInInterrupt(); void __InterruptsInit(); void __InterruptsShutdown(); @@ -62,6 +94,9 @@ void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg); // Fo bool __RunOnePendingInterrupt(); void __KernelReturnFromInterrupt(); +u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler); +u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber); + u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber); u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber); From 529818c9cdd6c8de2e0ffd858872a77d5b0ce27b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 08:10:48 -0800 Subject: [PATCH 045/276] Handle interrupt return values. --- Core/HLE/sceKernelInterrupt.cpp | 7 ++++++- Core/HLE/sceKernelInterrupt.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index bc335bbf04..77c59fd96f 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -259,7 +259,6 @@ bool __RunOnePendingInterrupt() __KernelSwitchOffThread("interrupt"); PendingInterrupt pend = pendingInterrupts.front(); - pendingInterrupts.pop_front(); intState.save(); pend.handler->copyArgsToCPU(pend); @@ -294,6 +293,12 @@ void __KernelReturnFromInterrupt() { DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); inInterrupt = false; + + // This is what we just ran. + PendingInterrupt pend = pendingInterrupts.front(); + pendingInterrupts.pop_front(); + pend.handler->handleResult(currentMIPS->r[MIPS_REG_V0]); + // Restore context after running the interrupt. intState.restore(); // All should now be back to normal, including PC. diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index 87228f4d55..adf0f4399b 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -70,6 +70,7 @@ public: virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; virtual void queueUp() = 0; virtual void queueUpWithArg(int arg) = 0; + virtual void handleResult(int result) = 0; }; class SubIntrHandler : public AllegrexInterruptHandler @@ -79,6 +80,7 @@ public: virtual void queueUp(); virtual void queueUpWithArg(int arg); virtual void copyArgsToCPU(const PendingInterrupt &pend); + virtual void handleResult(int result) {} bool enabled; int number; From 0f364182fc6f373ab5c6c4846aca2cd24d1bb2a6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 08:17:09 -0800 Subject: [PATCH 046/276] Alarms now fire again based on return value. --- Core/HLE/sceKernelAlarm.cpp | 53 ++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index ed46393c2e..964c0f9746 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -38,6 +38,38 @@ struct Alarm : public KernelObject NativeAlarm alm; }; +void __KernelScheduleAlarm(Alarm *alarm, int ticks); + +class AlarmIntrHandler : public SubIntrHandler +{ +public: + AlarmIntrHandler(Alarm *alarm) + { + this->alarm = alarm; + handlerAddress = alarm->alm.handlerPtr; + enabled = true; + } + + virtual void copyArgsToCPU(const PendingInterrupt &pend) + { + SubIntrHandler::copyArgsToCPU(pend); + + currentMIPS->r[MIPS_REG_A0] = alarm->alm.commonPtr; + } + + virtual void handleResult(int result) + { + // A non-zero result means to reschedule. + // TODO: Do sysclock alarms return a different value unit? + if (result > 0) + __KernelScheduleAlarm(alarm, usToCycles(result)); + else if (result < 0) + WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); + } + + Alarm *alarm; +}; + bool alarmInitComplete = false; int alarmTimer = 0; @@ -59,7 +91,13 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) // TODO: Need to find out the return value. if (alarm) - __TriggerInterruptWithArg(PSP_SYSTIMER0_INTR, uid, alarm->alm.commonPtr); + __TriggerInterrupt(PSP_SYSTIMER0_INTR, uid); +} + +void __KernelScheduleAlarm(Alarm *alarm, int ticks) +{ + alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + CoreTiming::ScheduleEvent((int) ticks, alarmTimer, alarm->GetUID()); } SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) @@ -75,16 +113,17 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) alarm->alm.handlerPtr = handlerPtr; alarm->alm.commonPtr = commonPtr; - sceKernelRegisterSubIntrHandler(PSP_SYSTIMER0_INTR, uid, handlerPtr, commonPtr); - sceKernelEnableSubIntr(PSP_SYSTIMER0_INTR, uid); - CoreTiming::ScheduleEvent(ticks, alarmTimer, uid); + u32 error = __RegisterSubInterruptHandler(PSP_SYSTIMER0_INTR, uid, new AlarmIntrHandler(alarm)); + if (error != 0) + return error; + __KernelScheduleAlarm(alarm, (int) ticks); return uid; } SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { - ERROR_LOG(HLE, "HACK sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); + DEBUG_LOG(HLE, "sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); return __KernelSetAlarm(usToCycles((int) micro), handlerPtr, commonPtr); } @@ -98,7 +137,7 @@ SceUID sceKernelSetSysClockAlarm(u32 ticksPtr, u32 handlerPtr, u32 commonPtr) else return -1; - ERROR_LOG(HLE, "UNIMPL sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); + ERROR_LOG(HLE, "UNTESTED sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); // TODO: Is this precise or is this relative? return __KernelSetAlarm(ticks, handlerPtr, commonPtr); } @@ -108,7 +147,7 @@ int sceKernelCancelAlarm(SceUID uid) DEBUG_LOG(HLE, "sceKernelCancelAlarm(%08x)", uid); CoreTiming::UnscheduleEvent(alarmTimer, uid); - sceKernelReleaseSubIntrHandler(PSP_SYSTIMER0_INTR, uid); + __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, uid); return kernelObjects.Destroy(uid); } From 99b24720b81675373ecc0269928bb85a00d91bdf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 19 Dec 2012 22:30:50 -0800 Subject: [PATCH 047/276] Oops, not a real pointer, use 0 not NULL. --- Core/HLE/sceKernelEventFlag.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 2ba4f23cf3..ed237a1e25 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -397,7 +397,7 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti th.bits = bits; th.wait = wait; // If < 5ms, sometimes hardware doesn't write this, but it's unpredictable. - th.outAddr = timeout == 0 ? NULL : outBitsPtr; + th.outAddr = timeout == 0 ? 0 : outBitsPtr; e->waitingThreads.push_back(th); __KernelSetEventFlagTimeout(e, timeoutPtr); @@ -450,7 +450,7 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 th.bits = bits; th.wait = wait; // If < 5ms, sometimes hardware doesn't write this, but it's unpredictable. - th.outAddr = timeout == 0 ? NULL : outBitsPtr; + th.outAddr = timeout == 0 ? 0 : outBitsPtr; e->waitingThreads.push_back(th); __KernelSetEventFlagTimeout(e, timeoutPtr); From 9034cfbfd3fc09ffdb41d8270e367dc340c60179 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 20 Dec 2012 21:54:40 -0800 Subject: [PATCH 048/276] Defer HLE interrupts, vblank only when enabled. Based on tests, vblank doesn't queue up (makes sense) while interrupts are disabled. I'm not 100% sure about the GPU stuff but it seems to only come from HLE via sceGe, so this should fix those return values. --- Core/HLE/HLE.cpp | 11 +++++++++ Core/HLE/HLE.h | 2 ++ Core/HLE/sceDisplay.cpp | 2 +- Core/HLE/sceKernelAlarm.cpp | 4 +--- Core/HLE/sceKernelInterrupt.cpp | 36 +++++++++++++++++++++-------- Core/HLE/sceKernelInterrupt.h | 13 +++++++++-- GPU/GLES/DisplayListInterpreter.cpp | 6 +++-- GPU/Null/NullGpu.cpp | 6 +++-- 8 files changed, 60 insertions(+), 20 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 69af4be0c0..9bfce5b5a7 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -26,6 +26,7 @@ #include "sceAudio.h" #include "sceKernelMemory.h" #include "sceKernelThread.h" +#include "sceKernelInterrupt.h" #include "../MIPS/MIPSCodeUtils.h" enum @@ -40,6 +41,8 @@ enum HLE_AFTER_ALL_CALLBACKS = 0x04, // Reschedule and process current thread's callbacks after the syscall. HLE_AFTER_RESCHED_CALLBACKS = 0x08, + // Run interrupts (and probably reschedule) after the syscall. + HLE_AFTER_RUN_INTERRUPTS = 0x10, }; static std::vector moduleDB; @@ -231,11 +234,19 @@ void hleReSchedule(bool callbacks, const char *reason) hleAfterSyscall |= HLE_AFTER_RESCHED_CALLBACKS; } +void hleRunInterrupts() +{ + hleAfterSyscall |= HLE_AFTER_RUN_INTERRUPTS; +} + inline void hleFinishSyscall() { if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); + if ((hleAfterSyscall & HLE_AFTER_RUN_INTERRUPTS) != 0) + __RunOnePendingInterrupt(); + // Rescheduling will also do HLE_AFTER_ALL_CALLBACKS. if ((hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) != 0) __KernelReSchedule(true, hleAfterSyscallReschedReason); diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 83633b134f..05ff70c612 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -81,6 +81,8 @@ void hleCheckAllCallbacks(); void hleReSchedule(const char *reason); // Reschedule and go into a callback processing state after the syscall finishes. void hleReSchedule(bool callbacks, const char *reason); +// Run interrupts after the syscall finishes. +void hleRunInterrupts(); void HLEInit(); void HLEShutdown(); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 39c673b5c8..8b0fca887e 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -151,7 +151,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) vblankWaitingThreads.clear(); // Trigger VBlank interrupt handlers. - __TriggerInterrupt(PSP_VBLANK_INTR); + __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED, PSP_VBLANK_INTR); CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 964c0f9746..ee6657e670 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -88,10 +88,8 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) u32 error; Alarm *alarm = kernelObjects.Get(uid, error); - - // TODO: Need to find out the return value. if (alarm) - __TriggerInterrupt(PSP_SYSTIMER0_INTR, uid); + __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); } void __KernelScheduleAlarm(Alarm *alarm, int ticks) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 77c59fd96f..1c44b069d6 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -273,20 +273,36 @@ bool __RunOnePendingInterrupt() } } -void __TriggerInterrupt(PSPInterrupt intno, int subintr) +void __TriggerInterrupt(int type, PSPInterrupt intno, int subintr) { - intrHandlers[intno].queueUp(subintr); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); - if (!inInterrupt) - __RunOnePendingInterrupt(); + if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) + { + intrHandlers[intno].queueUp(subintr); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); + if (!inInterrupt) + { + if ((type & PSP_INTR_HLE) != 0) + hleRunInterrupts(); + else + __RunOnePendingInterrupt(); + } + } } -void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg) +void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int arg) { - intrHandlers[intno].queueUpWithArg(subintr, arg); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); - if (!inInterrupt) - __RunOnePendingInterrupt(); + if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) + { + intrHandlers[intno].queueUpWithArg(subintr, arg); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); + if (!inInterrupt) + { + if ((type & PSP_INTR_HLE) != 0) + hleRunInterrupts(); + else + __RunOnePendingInterrupt(); + } + } } void __KernelReturnFromInterrupt() diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index adf0f4399b..1e553ed472 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -54,6 +54,15 @@ enum PSPGeSubInterrupts { PSP_GE_SUBINTR_SIGNAL = 15 }; +enum PSPInterruptTriggerType { + // Trigger immediately, for CoreTiming events. + PSP_INTR_IMMEDIATE = 0x0, + // Trigger after the HLE syscall finishes. + PSP_INTR_HLE = 0x1, + // Only trigger (as above) if interrupts are not suspended. + PSP_INTR_ONLY_IF_ENABLED = 0x2, +}; + class AllegrexInterruptHandler; struct PendingInterrupt { @@ -91,8 +100,8 @@ public: bool __IsInInterrupt(); void __InterruptsInit(); void __InterruptsShutdown(); -void __TriggerInterrupt(PSPInterrupt intno, int subInterrupts = -1); -void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg); // For GE "callbacks" +void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1); +void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int arg); // For GE "callbacks" bool __RunOnePendingInterrupt(); void __KernelReturnFromInterrupt(); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 3f317513eb..7a4e5d952c 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -488,8 +488,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FINISH: DEBUG_LOG(G3D,"DL CMD FINISH"); + // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) - __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); + __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; case GE_CMD_END: @@ -525,8 +526,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) ERROR_LOG(G3D, "UNKNOWN Signal UNIMPLEMENTED %i ! signal/end: %04x %04x", behaviour, signal, enddata); break; } + // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) - __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); + __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); } break; case GE_CMD_FINISH: diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 7174166e66..f983d6b688 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -206,8 +206,9 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) int behaviour = (data >> 16) & 0xFF; int signal = data & 0xFFFF; + // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) - __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); + __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); } break; @@ -237,8 +238,9 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FINISH: DEBUG_LOG(G3D,"DL CMD FINISH"); + // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) - __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); + __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; case GE_CMD_END: From 4fb6c8c0acd25f42375d6f0e47504b4eaf7c6cc7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 20 Dec 2012 21:59:10 -0800 Subject: [PATCH 049/276] Reschedule after interrupts run. It'll reschedule anyway, so this will just give us a message. Hardware seems to reschedule, not just go back to the original thread, but there may be more to it than that. --- Core/HLE/sceKernelInterrupt.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 1c44b069d6..2ee1f49137 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -320,12 +320,8 @@ void __KernelReturnFromInterrupt() // All should now be back to normal, including PC. // Alright, let's see if there's any more interrupts queued... - if (!__RunOnePendingInterrupt()) - { - // Hmmm... - //__KernelReSchedule("return from interrupt"); - } + __KernelReSchedule("return from interrupt"); } u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler) From 84b6c3a7c21c024f93e267269774d42e9ad2939c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 20 Dec 2012 22:48:59 -0800 Subject: [PATCH 050/276] Improve accuratcy of CoreTiming::ScheduleEvent(). --- Core/CoreTiming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 6cffd3d3eb..fc33e988d7 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -245,7 +245,7 @@ void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata) Event *ne = GetNewEvent(); ne->userdata = userdata; ne->type = event_type; - ne->time = globalTimer + cyclesIntoFuture; + ne->time = GetTicks() + cyclesIntoFuture; AddEventToQueue(ne); } From 12fb91b7b594fdf2b08d304ee9cbc52383838811 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 20 Dec 2012 22:49:48 -0800 Subject: [PATCH 051/276] Don't run interrupts while they're suspended. --- Core/HLE/sceKernelInterrupt.cpp | 44 +++++++++++++++++++++------------ Core/HLE/sceKernelInterrupt.h | 3 +++ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 2ee1f49137..a8eaa41e3c 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -89,6 +89,7 @@ void sceKernelCpuResumeIntr(u32 enable) if (enable) { __EnableInterrupts(); + hleRunInterrupts(); } else { @@ -219,6 +220,8 @@ void SubIntrHandler::queueUp() PendingInterrupt pend; pend.handler = this; pend.hasArg = false; + pend.intr = intrNumber; + pend.subintr = number; pendingInterrupts.push_back(pend); }; @@ -230,6 +233,8 @@ void SubIntrHandler::queueUpWithArg(int arg) pend.handler = this; pend.arg = arg; pend.hasArg = true; + pend.intr = intrNumber; + pend.subintr = number; pendingInterrupts.push_back(pend); } @@ -246,7 +251,7 @@ void SubIntrHandler::copyArgsToCPU(const PendingInterrupt &pend) // Returns true if anything was executed. bool __RunOnePendingInterrupt() { - if (inInterrupt) + if (inInterrupt || !interruptsEnabled) { // Already in an interrupt! We'll keep going when it's done. return false; @@ -273,19 +278,25 @@ bool __RunOnePendingInterrupt() } } +void __TriggerRunInterrupts(int type) +{ + // If interrupts aren't enabled, we run them later. + if (interruptsEnabled && !inInterrupt) + { + if ((type & PSP_INTR_HLE) != 0) + hleRunInterrupts(); + else + __RunOnePendingInterrupt(); + } +} + void __TriggerInterrupt(int type, PSPInterrupt intno, int subintr) { if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) { intrHandlers[intno].queueUp(subintr); DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); - if (!inInterrupt) - { - if ((type & PSP_INTR_HLE) != 0) - hleRunInterrupts(); - else - __RunOnePendingInterrupt(); - } + __TriggerRunInterrupts(type); } } @@ -295,13 +306,7 @@ void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int ar { intrHandlers[intno].queueUpWithArg(subintr, arg); DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); - if (!inInterrupt) - { - if ((type & PSP_INTR_HLE) != 0) - hleRunInterrupts(); - else - __RunOnePendingInterrupt(); - } + __TriggerRunInterrupts(type); } } @@ -327,6 +332,7 @@ void __KernelReturnFromInterrupt() u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler) { subIntrHandler->number = subIntrNumber; + subIntrHandler->intrNumber = intrNumber; intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); return 0; } @@ -336,7 +342,13 @@ u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber) if (!intrHandlers[intrNumber].has(subIntrNumber)) return -1; - // TODO: should check if it's pending and remove it from pending list! (although that's probably unlikely) + for (std::list::iterator it = pendingInterrupts.begin(); it != pendingInterrupts.end(); ) + { + if (it->intr == intrNumber && it->subintr == subIntrNumber) + pendingInterrupts.erase(it++); + else + ++it; + } intrHandlers[intrNumber].remove(subIntrNumber); return 0; diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index 1e553ed472..af57d6f3f4 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -69,6 +69,8 @@ struct PendingInterrupt { AllegrexInterruptHandler *handler; int arg; bool hasArg; + int intr; + int subintr; }; @@ -92,6 +94,7 @@ public: virtual void handleResult(int result) {} bool enabled; + int intrNumber; int number; u32 handlerAddress; u32 handlerArg; From ab0253d71cc7aaaca12426ce4fbe4c3faa1b5ddc Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 21 Dec 2012 14:30:34 +0800 Subject: [PATCH 052/276] Implement Vsrt1,Vsrt2,Vsrt3,Vsrt4 --- Core/MIPS/MIPSIntVFPU.cpp | 92 +++++++++++++++++++++++++++++++++++++++ Core/MIPS/MIPSIntVFPU.h | 4 ++ Core/MIPS/MIPSTables.cpp | 8 ++-- 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index b3045b9a4b..153d02c2b2 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -882,7 +882,99 @@ namespace MIPSInt PC += 4; EatPrefixes(); } + + void Int_Vsrt1(u32 op) + { + float s[4]; + float d[4]; + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + float x = s[0]; + float y = s[1]; + float z = s[2]; + float w = s[3]; + d[0] = std::min(x, y); + d[1] = std::max(x, y); + d[2] = std::min(z, w); + d[3] = std::max(z, w); + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + void Int_Vsrt2(u32 op) + { + float s[4]; + float d[4]; + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + float x = s[0]; + float y = s[1]; + float z = s[2]; + float w = s[3]; + d[0] = std::min(x, w); + d[1] = std::min(y, z); + d[2] = std::max(y, z); + d[3] = std::max(x, w); + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + + void Int_Vsrt3(u32 op) + { + float s[4]; + float d[4]; + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + float x = s[0]; + float y = s[1]; + float z = s[2]; + float w = s[3]; + d[0] = std::max(x, y); + d[1] = std::min(x, y); + d[2] = std::max(z, w); + d[3] = std::min(z, w); + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + + void Int_Vsrt4(u32 op) + { + float s[4]; + float d[4]; + int vd = _VD; + int vs = _VS; + VectorSize sz = GetVecSize(op); + ReadVector(s, sz, vs); + ApplySwizzleS(s, sz); + float x = s[0]; + float y = s[1]; + float z = s[2]; + float w = s[3]; + d[0] = std::max(x, w); + d[1] = std::max(y, z); + d[2] = std::min(y, z); + d[3] = std::min(x, w); + ApplyPrefixD(d, sz); + WriteVector(d, sz, vd); + PC += 4; + EatPrefixes(); + } + void Int_Vcrs(u32 op) { //half a cross product diff --git a/Core/MIPS/MIPSIntVFPU.h b/Core/MIPS/MIPSIntVFPU.h index 50e7229366..0ab0c54f82 100644 --- a/Core/MIPS/MIPSIntVFPU.h +++ b/Core/MIPS/MIPSIntVFPU.h @@ -55,6 +55,10 @@ namespace MIPSInt void Int_VPFX(u32 op); void Int_Vflush(u32 op); void Int_Vbfy(u32 op); + void Int_Vsrt1(u32 op); + void Int_Vsrt2(u32 op); + void Int_Vsrt3(u32 op); + void Int_Vsrt4(u32 op); void Int_Vf2i(u32 op); void Int_Vi2f(u32 op); void Int_Vi2x(u32 op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 67d9b70e92..8c457dae17 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -685,8 +685,8 @@ MIPSInstruction tableVFPUMatrixSet1[16] = //111100 11100 0xxxx (rm x is 16) MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx { - INSTR("vsrt1", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), - INSTR("vsrt2", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), + INSTR("vsrt1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt1, IS_VFPU), + INSTR("vsrt2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt2, IS_VFPU), INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU), INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU), //4 @@ -695,8 +695,8 @@ MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU), INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU), //8 - INSTR("vsrt3", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), - INSTR("vsrt4", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU), + INSTR("vsrt3", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt3, IS_VFPU), + INSTR("vsrt4", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt4, IS_VFPU), INSTR("vsgn", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsgn, IS_VFPU), {-2}, //12 From e9bf6da934c289fc8654e1ee2bb11f2843da6a15 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 00:23:55 -0800 Subject: [PATCH 053/276] Add alarm test. --- pspautotests | 2 +- test.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pspautotests b/pspautotests index 8c1284c758..9e55680fca 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 8c1284c758c05811517c043bbc781ba8ab724d5e +Subproject commit 9e55680fca5100bd94d3c1b710d08a918f79cad6 diff --git a/test.py b/test.py index 4ac98e263e..14f3746193 100755 --- a/test.py +++ b/test.py @@ -58,6 +58,7 @@ tests_good = [ "misc/testgp", "string/string", "gpu/callbacks/ge_callbacks", + "threads/alarm/alarm", "threads/events/events", "threads/events/cancel/cancel", "threads/events/clear/clear", From 5a501bb5ff55ef59ad3bd7e5727e653954d3ced2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 01:03:46 -0800 Subject: [PATCH 054/276] Fix minor typo. --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index c6b608da39..cd82d8fa48 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1751,7 +1751,7 @@ void __KernelSwitchContext(Thread *target, const char *reason) } currentThread = target; __KernelLoadContext(¤tThread->context); - DEBUG_LOG(HLE,"Context switched: %s -> %s (%s) (%i - pc: %08x -> %i - pc: %08)", + DEBUG_LOG(HLE,"Context switched: %s -> %s (%s) (%i - pc: %08x -> %i - pc: %08x)", oldName, currentThread->GetName(), reason, oldUID, oldPC, currentThread->GetUID(), currentMIPS->pc); From 52cf324e9edd10ef8163f67f29a36ab4273db501 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 10:18:06 +0100 Subject: [PATCH 055/276] Try to fix "W1" vertex error --- GPU/GLES/VertexDecoder.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 4e5e2ac97f..6e6bc887ea 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -278,6 +278,9 @@ public: break; } switch (decFmt_.w1fmt) { + case 0: + // It's fine for there to be w0 weights but not w1. + break; case DEC_FLOAT_1: memcpy(weights + 4, data_ + decFmt_.w1off, 4); break; case DEC_FLOAT_2: memcpy(weights + 4, data_ + decFmt_.w1off, 8); break; case DEC_FLOAT_3: memcpy(weights + 4, data_ + decFmt_.w1off, 12); break; From 4d4370232cf5730ee1f37a3246590b74456cf1dd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 10:18:52 +0100 Subject: [PATCH 056/276] Assorted minor cleanup and fixes. --- Core/CoreTiming.cpp | 1 + Core/HLE/HLE.cpp | 2 +- Core/HLE/HLETables.cpp | 6 +++--- Core/HLE/sceIo.cpp | 29 +++++++++++++++++++++++++---- Core/HLE/sceKernel.cpp | 10 +++++++--- Core/HLE/sceKernel.h | 5 +++-- GPU/GLES/DisplayListInterpreter.cpp | 1 + GPU/GLES/VertexShaderGenerator.cpp | 1 + pspautotests | 2 +- 9 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index fc33e988d7..74eb4f4c91 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -79,6 +79,7 @@ void (*advanceCallback)(int cyclesExecuted) = NULL; void SetClockFrequencyMHz(int cpuMhz) { CPU_HZ = cpuMhz * 1000000; + // TODO: Rescale times of scheduled events? } int GetClockFrequencyMHz() diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 9bfce5b5a7..2126ce2024 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -264,7 +264,7 @@ void CallSyscall(u32 op) u32 callno = (op >> 6) & 0xFFFFF; //20 bits int funcnum = callno & 0xFFF; int modulenum = (callno & 0xFF000) >> 12; - if (funcnum == 0xfff) + if (funcnum == 0xfff || op == 0xffff) { _dbg_assert_msg_(HLE,0,"Unknown syscall"); ERROR_LOG(HLE,"Unknown syscall: Module: %s", moduleDB[modulenum].name); diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index a2e2f5a634..7a8aba3661 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -77,7 +77,7 @@ const HLEFunction UtilsForUser[] = {0x91E4F6A7, WrapU_V, "sceKernelLibcClock"}, {0x27CC57F0, sceKernelLibcTime, "sceKernelLibcTime"}, {0x71EC4271, sceKernelLibcGettimeofday, "sceKernelLibcGettimeofday"}, - {0xBFA98062, 0, "sceKernelDcacheInvalidateRange"}, + {0xBFA98062, WrapV_UI, "sceKernelDcacheInvalidateRange"}, {0xC8186A58, 0, "sceKernelUtilsMd5Digest"}, {0x9E5C5086, 0, "sceKernelUtilsMd5BlockInit"}, {0x61E1E525, 0, "sceKernelUtilsMd5BlockUpdate"}, @@ -92,8 +92,8 @@ const HLEFunction UtilsForUser[] = {0x6AD345D7, sceKernelSetGPO, "sceKernelSetGPO"}, {0x79D1C3FA, sceKernelDcacheWritebackAll, "sceKernelDcacheWritebackAll"}, {0xB435DEC5, sceKernelDcacheWritebackInvalidateAll, "sceKernelDcacheWritebackInvalidateAll"}, - {0x3EE30821, sceKernelDcacheWritebackRange, "sceKernelDcacheWritebackRange"}, - {0x34B9FA9E, sceKernelDcacheWritebackInvalidateRange, "sceKernelDcacheWritebackInvalidateRange"}, + {0x3EE30821, WrapV_UI, "sceKernelDcacheWritebackRange"}, + {0x34B9FA9E, WrapV_UI, "sceKernelDcacheWritebackInvalidateRange"}, {0xC2DF770E, 0, "sceKernelIcacheInvalidateRange"}, {0x80001C4C, 0, "sceKernelDcacheProbe"}, {0x16641D70, 0, "sceKernelDcacheReadTag"}, diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index aa6e540c74..c485ecc999 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -522,7 +522,7 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, u32 sectorCount = memStickSectorSize / sectorSize; u64 freeSize = 1 * 1024 * 1024 * 1024; DeviceSize deviceSize; - deviceSize.maxClusters = (freeSize * 95 / 100) / (sectorSize * sectorCount); + deviceSize.maxClusters = (u32)((freeSize * 95 / 100) / (sectorSize * sectorCount)); deviceSize.freeClusters = deviceSize.maxClusters; deviceSize.maxSectors = deviceSize.maxClusters; deviceSize.sectorSize = sectorSize; @@ -593,7 +593,7 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, u32 sectorCount = memStickSectorSize / sectorSize; u64 freeSize = 1 * 1024 * 1024 * 1024; DeviceSize deviceSize; - deviceSize.maxClusters = (freeSize * 95 / 100) / (sectorSize * sectorCount); + deviceSize.maxClusters = (u32)((freeSize * 95 / 100) / (sectorSize * sectorCount)); deviceSize.freeClusters = deviceSize.maxClusters; deviceSize.maxSectors = deviceSize.maxClusters; deviceSize.sectorSize = sectorSize; @@ -883,8 +883,29 @@ u32 sceIoDclose(int id) { u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen) { - ERROR_LOG(HLE, "UNIMPL 0=sceIoIoctrl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outLen %08x", id,cmd,indataPtr,inlen,outdataPtr,outlen); - return 0; + ERROR_LOG(HLE, "UNIMPL PARTIAL 0=sceIoIoctl id: %08x, cmd %08x, indataPtr %08x, inlen %08x, outdataPtr %08x, outLen %08x", id,cmd,indataPtr,inlen,outdataPtr,outlen); + + u32 error; + FileNode *f = kernelObjects.Get(id, error); + if (error) { + return error; + } + + //KD Hearts: + //56:46:434 HLE\sceIo.cpp:886 E[HLE]: UNIMPL 0=sceIoIoctrl id: 0000011f, cmd 04100001, indataPtr 08b313d8, inlen 00000010, outdataPtr 00000000, outLen 0 + // 0000000 + switch (cmd) { + case 0x04100001: // Define decryption key (amctrl.prx DRM) + if (Memory::IsValidAddress(indataPtr) && inlen == 16) { + u8 keybuf[16]; + memcpy(keybuf, Memory::GetPointer(indataPtr), 16); + ERROR_LOG(HLE, "PGD DRM not yet supported, sorry."); + } + break; + + } + + return 0; } const HLEFunction IoFileMgrForUser[] = { diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index cb876fc381..c99b4b6a2a 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -183,14 +183,18 @@ void sceKernelGetGPI() } // Don't even log these, they're spammy and we probably won't -// need to emulate them. +// need to emulate them. Might be useful for invalidating cached +// textures, and in the future display lists, in some cases though. +void sceKernelDcacheInvalidateRange(u32 addr, int size) +{ +} void sceKernelDcacheWritebackAll() { } -void sceKernelDcacheWritebackRange() +void sceKernelDcacheWritebackRange(u32 addr, int size) { } -void sceKernelDcacheWritebackInvalidateRange() +void sceKernelDcacheWritebackInvalidateRange(u32 addr, int size) { } void sceKernelDcacheWritebackInvalidateAll() diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 2876906894..bf5d609c10 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -283,9 +283,10 @@ void sceKernelFindModuleByName(); void sceKernelSetGPO(); void sceKernelGetGPI(); +void sceKernelDcacheInvalidateRange(u32 addr, int size); void sceKernelDcacheWritebackAll(); -void sceKernelDcacheWritebackRange(); -void sceKernelDcacheWritebackInvalidateRange(); +void sceKernelDcacheWritebackRange(u32 addr, int size); +void sceKernelDcacheWritebackInvalidateRange(u32 addr, int size); void sceKernelDcacheWritebackInvalidateAll(); void sceKernelGetThreadStackFreeSize(); void sceKernelIcacheInvalidateAll(); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 7a4e5d952c..4d28d02e91 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -499,6 +499,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_SIGNAL: { + // TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935# int behaviour = (prev >> 16) & 0xFF; int signal = prev & 0xFFFF; int enddata = data & 0xFFFF; diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 359c46f053..5021255f88 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -41,6 +41,7 @@ static char buffer[16384]; #define WRITE p+=sprintf + bool CanUseHardwareTransform(int prim) { return !gstate.isModeThrough() && false; // prim != GE_PRIM_RECTANGLES; diff --git a/pspautotests b/pspautotests index 9e55680fca..6bd9d261e6 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 9e55680fca5100bd94d3c1b710d08a918f79cad6 +Subproject commit 6bd9d261e6014d371b917e50d2e18d5fc986a8c3 From fb773b5acf0ab044864b4adc49848df0a62e58cf Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 21 Dec 2012 17:30:17 +0800 Subject: [PATCH 057/276] Fix tab issue --- Core/MIPS/MIPSIntVFPU.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 4b25af5631..d80ca2764d 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -517,13 +517,13 @@ namespace MIPSInt ApplySwizzleS(s, sz); int n=GetNumVectorElements(sz); float x = s[0]; - d[0] = std::min(std::max(0.0f, 1.0f - x), 1.0f); - d[1] = std::min(std::max(0.0f, x), 1.0f); - if (n > 1) { - float y = s[1]; - d[2] = std::min(std::max(0.0f, 1.0f - y), 1.0f); - d[3] = std::min(std::max(0.0f, y), 1.0f); - } + d[0] = std::min(std::max(0.0f, 1.0f - x), 1.0f); + d[1] = std::min(std::max(0.0f, x), 1.0f); + if (n > 1) { + float y = s[1]; + d[2] = std::min(std::max(0.0f, 1.0f - y), 1.0f); + d[3] = std::min(std::max(0.0f, y), 1.0f); + } ApplyPrefixD(d, sz); WriteVector(d, sz, vd); PC += 4; From 4bf2e526237299cf5d526b90877aea8d151671c8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 11:08:54 +0100 Subject: [PATCH 058/276] HW transform: Avoid 4x3 matrices for GLES 2.0 compat. Add option to turn hw transform on. --- Core/Config.cpp | 2 ++ Core/Config.h | 3 +++ GPU/GLES/ShaderManager.cpp | 29 +++++++++++++++++++++++++---- GPU/GLES/VertexShaderGenerator.cpp | 30 +++++++++++++++++------------- Windows/WndMainWindow.cpp | 6 ++++++ Windows/ppsspp.rc | 1 + Windows/resource.h | 3 ++- android/jni/MenuScreens.cpp | 2 +- 8 files changed, 57 insertions(+), 19 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index befe00334f..135d0a26eb 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -57,6 +57,7 @@ void CConfig::Load(const char *iniFileName) graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false); graphics->Get("WindowZoom", &iWindowZoom, 1); graphics->Get("BufferedRendering", &bBufferedRendering, true); + graphics->Get("HardwareTransform", &bHardwareTransform, false); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Get("Enable", &bEnableSound, true); @@ -93,6 +94,7 @@ void CConfig::Save() graphics->Set("DisplayFramebuffer", bDisplayFramebuffer); graphics->Set("WindowZoom", iWindowZoom); graphics->Set("BufferedRendering", bBufferedRendering); + graphics->Set("HardwareTransform", bHardwareTransform); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Set("Enable", bEnableSound); diff --git a/Core/Config.h b/Core/Config.h index 461859e4aa..240b0fddb7 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -41,7 +41,10 @@ public: bool bSpeedLimit; bool bConfirmOnQuit; bool bIgnoreBadMemAccess; + + // GFX bool bDisplayFramebuffer; + bool bHardwareTransform; bool bBufferedRendering; bool bDrawWireframe; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index e86db1dc34..41ac53c8e3 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -153,6 +153,27 @@ static void SetColorUniform3ExtraFloat(int uniform, u32 color, float extra) glUniform4fv(uniform, 1, col); } +static void SetMatrix4x3(int uniform, const float *m4x3) { + float m4x4[16]; + m4x4[0] = m4x3[0]; + m4x4[1] = m4x3[1]; + m4x4[2] = m4x3[2]; + m4x4[3] = 0.0f; + m4x4[4] = m4x3[3]; + m4x4[5] = m4x3[4]; + m4x4[6] = m4x3[5]; + m4x4[7] = 0.0f; + m4x4[8] = m4x3[6]; + m4x4[9] = m4x3[7]; + m4x4[10] = m4x3[8]; + m4x4[11] = 0.0f; + m4x4[12] = m4x3[9]; + m4x4[13] = m4x3[10]; + m4x4[14] = m4x3[11]; + m4x4[15] = 1.0f; + glUniformMatrix4fv(uniform, 1, GL_FALSE, m4x4); +} + void LinkedShader::use() { glUseProgram(program); glUniform1i(u_tex, 0); @@ -203,17 +224,17 @@ void LinkedShader::use() { // Transform if (u_world != -1 && (dirtyUniforms & DIRTY_WORLDMATRIX)) { - glUniformMatrix4x3fv(u_world, 1, GL_FALSE, gstate.worldMatrix); + SetMatrix4x3(u_world, gstate.worldMatrix); } if (u_view != -1 && (dirtyUniforms & DIRTY_VIEWMATRIX)) { - glUniformMatrix4x3fv(u_view, 1, GL_FALSE, gstate.viewMatrix); + SetMatrix4x3(u_view, gstate.viewMatrix); } if (u_texmtx != -1 && (dirtyUniforms & DIRTY_TEXMATRIX)) { - glUniformMatrix4x3fv(u_texmtx, 1, GL_FALSE, gstate.tgenMatrix); + SetMatrix4x3(u_texmtx, gstate.tgenMatrix); } for (int i = 0; i < 8; i++) { if (u_bone[i] != -1 && (dirtyUniforms & (DIRTY_BONEMATRIX0 << i))) { - glUniformMatrix4x3fv(u_bone[i], 1, GL_FALSE, gstate.boneMatrix + 12 * i); + SetMatrix4x3(u_bone[i], gstate.boneMatrix + 12 * i); } } diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 5021255f88..77276b76d9 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -26,6 +26,7 @@ #include "../ge_constants.h" #include "../GPUState.h" +#include "../../Core/Config.h" #include "VertexShaderGenerator.h" @@ -44,8 +45,9 @@ static char buffer[16384]; bool CanUseHardwareTransform(int prim) { - return !gstate.isModeThrough() && false; // prim != GE_PRIM_RECTANGLES; - //return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; + if (!g_Config.bHardwareTransform) + return false; + return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES; } // prim so we can special case for RECTANGLES :( @@ -192,16 +194,16 @@ char *GenerateVertexShader(int prim) if (hwXForm) { // When transforming by hardware, we need a great deal more uniforms... - WRITE(p, "uniform mat4x3 u_world;\n"); - WRITE(p, "uniform mat4x3 u_view;\n"); + WRITE(p, "uniform mat4 u_world;\n"); + WRITE(p, "uniform mat4 u_view;\n"); if (gstate.getUVGenMode() == 0) WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); else if (gstate.getUVGenMode() == 1) - WRITE(p, "uniform mat4x3 u_texmtx;\n"); + WRITE(p, "uniform mat4 u_texmtx;\n"); if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { int numBones = 1 + ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); for (int i = 0; i < numBones; i++) { - WRITE(p, "uniform mat4x3 u_bone%i;\n", i); + WRITE(p, "uniform mat4 u_bone%i;\n", i); } } if (gstate.lightingEnable & 1) { @@ -258,9 +260,9 @@ char *GenerateVertexShader(int prim) // Step 1: World Transform / Skinning if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { // No skinning, just standard T&L. - WRITE(p, " vec3 worldpos = u_world * vec4(a_position, 1.0);\n"); + WRITE(p, " vec3 worldpos = (u_world * vec4(a_position, 1.0)).xyz;\n"); if (hasNormal) - WRITE(p, " vec3 worldnormal = normalize(u_world * vec4(a_normal, 0.0));\n"); + WRITE(p, " vec3 worldnormal = (u_world * vec4(a_normal, 0.0)).xyz;\n"); } else { WRITE(p, " vec3 worldpos = vec3(0.0, 0.0, 0.0);\n"); if (hasNormal) @@ -271,15 +273,17 @@ char *GenerateVertexShader(int prim) // workaround for "cant do .x of scalar" issue if (numWeights == 1 && i == 0) weightAttr = "a_weight0123"; if (numWeights == 5 && i == 4) weightAttr = "a_weight4567"; - WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0));\n", weightAttr, i); + WRITE(p, " worldpos += %s * (u_bone%i * vec4(a_position, 1.0)).xyz;\n", weightAttr, i); if (hasNormal) - WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0));\n", weightAttr, i); + WRITE(p, " worldnormal += %s * (u_bone%i * vec4(a_normal, 0.0)).xyz;\n", weightAttr, i); } // Finally, multiply by world matrix (yes, we have to). - WRITE(p, " worldpos = u_world * vec4(worldpos, 1.0);\n"); + WRITE(p, " worldpos = (u_world * vec4(worldpos, 1.0)).xyz;\n"); if (hasNormal) - WRITE(p, " worldnormal = u_world * vec4(worldnormal, 0.0);\n"); + WRITE(p, " worldnormal = (u_world * vec4(worldnormal, 0.0)).xyz;\n"); } + if (hasNormal) + WRITE(p, " worldnormal = normalize(worldnormal);\n"); // Step 2: Color/Lighting if (hasColor) { @@ -395,7 +399,7 @@ char *GenerateVertexShader(int prim) } } // Step 4: Final view and projection transforms. - WRITE(p, " gl_Position = u_proj * vec4(u_view * vec4(worldpos, 1.0), 1.0);\n"); + WRITE(p, " gl_Position = u_proj * (u_view * vec4(worldpos, 1.0));\n"); } if (gstate.isFogEnabled()) WRITE(p, " v_depth = gl_Position.z;\n"); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 51664cc983..9146e38696 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -353,6 +353,11 @@ namespace MainWindow UpdateMenus(); break; + case ID_OPTIONS_HARDWARETRANSFORM: + g_Config.bHardwareTransform = !g_Config.bHardwareTransform; + UpdateMenus(); + break; + case ID_FILE_EXIT: DestroyWindow(hWnd); break; @@ -632,6 +637,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering); CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); + CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); BOOL enable = !Core_IsStepping(); EnableMenuItem(menu,ID_EMULATION_RUN,enable); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 4d12eb0163..70e0d2bd13 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -214,6 +214,7 @@ BEGIN MENUITEM "&Toggle Full Screen\tF12", ID_OPTIONS_FULLSCREEN MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING + MENUITEM "&Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS MENUITEM SEPARATOR diff --git a/Windows/resource.h b/Windows/resource.h index 631760dffe..fbaf91b309 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -244,13 +244,14 @@ #define ID_CPU_FASTINTERPRETER 40121 #define ID_OPTIONS_SHOWDEBUGSTATISTICS 40122 #define ID_OPTIONS_WIREFRAME 40123 +#define ID_OPTIONS_HARDWARETRANSFORM 40124 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40124 +#define _APS_NEXT_COMMAND_VALUE 40125 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 6cdbd87488..8052c357ca 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -241,7 +241,7 @@ void SettingsScreen::render() { int y = 50; UICheckBox(GEN_ID, x, y += 50, "Enable Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound); UICheckBox(GEN_ID, x, y += 50, "Buffered Rendering (may fix flicker)", ALIGN_TOPLEFT, &g_Config.bBufferedRendering); - + UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform); bool useFastInt = g_Config.iCpuCore == CPU_FASTINTERPRETER; UICheckBox(GEN_ID, x, y += 50, "Slightly faster interpreter (may crash)", ALIGN_TOPLEFT, &useFastInt); From 9db065a97933923b35b8fda2ffbf1423ea27d70f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 11:24:38 +0100 Subject: [PATCH 059/276] add #version to the framebuffer drawing shader for compat --- GPU/GLES/Framebuffer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index f458916fb4..f3a6519fa0 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -37,14 +37,17 @@ const char tex_fs[] = "}\n"; const char basic_vs[] = +#ifndef USING_GLES2 + "#version 120\n" +#endif "attribute vec4 a_position;\n" "attribute vec2 a_texcoord0;\n" "uniform mat4 u_viewproj;\n" "varying vec4 v_color;\n" "varying vec2 v_texcoord0;\n" "void main() {\n" - " v_texcoord0 = a_texcoord0;\n" - " gl_Position = u_viewproj * a_position;\n" + " v_texcoord0 = a_texcoord0;\n" + " gl_Position = u_viewproj * a_position;\n" "}\n"; FramebufferManager::FramebufferManager() { From ab2f0b89e633c7d2b4d4cb18cfdf85be489d0897 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 21 Dec 2012 19:57:38 +0800 Subject: [PATCH 060/276] Change to DEBUG for BBOX JUMP/TEST .Fix massive slowdown when hit them . --- GPU/GLES/DisplayListInterpreter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 1f84c5ed1f..838f25eba0 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -450,7 +450,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_SIGNAL: { - ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); + DEBUG_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); // Processed in GE_END. } break; @@ -509,12 +509,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_BJUMP: // bounding box jump. Let's just not jump, for now. - ERROR_LOG(G3D,"DL BBOX JUMP - unimplemented"); + DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); break; case GE_CMD_BOUNDINGBOX: // bounding box test. Let's do nothing. - ERROR_LOG(G3D,"DL BBOX TEST - unimplemented"); + DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); break; case GE_CMD_ORIGIN: From 4efb66fdb63d684684286fcbeaf8e39a47bb6f5a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 12:57:43 +0100 Subject: [PATCH 061/276] Fix hw transform and audio on android, misc --- Core/HLE/sceKernelThread.cpp | 4 ++-- GPU/GLES/VertexDecoder.cpp | 2 +- GPU/GLES/VertexShaderGenerator.cpp | 2 +- android/jni/NativeApp.cpp | 2 +- android/src/org/ppsspp/ppsspp/PpssppActivity.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index cd82d8fa48..6523d8ba3a 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1136,10 +1136,10 @@ void sceKernelExitDeleteThread() Thread *t = kernelObjects.Get(threadHandle, error); if (t) { - ERROR_LOG(HLE,"sceKernelExitDeleteThread()"); + INFO_LOG(HLE,"sceKernelExitDeleteThread()"); currentThread->nt.status = THREADSTATUS_DORMANT; currentThread->nt.exitStatus = PARAM(0); - __KernelFireThreadEnd(currentThread); + __KernelFireThreadEnd(currentThread); //userMemory.Free(currentThread->stackBlock); currentThread->stackBlock = 0; diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index dce69038f7..8f7b7fb0b3 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -648,6 +648,7 @@ void VertexDecoder::SetVertexType(u32 fmt) { void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const { // Find index bounds. Could cache this in display lists. + // Also, this could be greatly sped up with SSE2, although rarely a bottleneck. int lowerBound = 0x7FFFFFFF; int upperBound = 0; if (idx == (GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT)) { @@ -685,4 +686,3 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *i decoded_ += decFmt.stride; } } - diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 77276b76d9..395021ce56 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -327,7 +327,7 @@ char *GenerateVertexShader(int prim) if (doLight[i] == LIGHT_DOTONLY) continue; // Actually, might want specular dot.... TODO - WRITE(p, " float lightScale%i = 1.0f;\n", i); + WRITE(p, " float lightScale%i = 1.0;\n", i); if (type != GE_LIGHTTYPE_DIRECTIONAL) { // Attenuation WRITE(p, " float distance%i = length(toLight%i);\n", i, i); diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 6f0ae119e7..8f6b959cc4 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -133,7 +133,7 @@ void NativeMix(short *audio, int num_samples) { if (g_mixer) { - g_mixer->Mix(audio, num_samples/2); + g_mixer->Mix(audio, num_samples); } else { diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index be46ac6038..bd7cd15d12 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -15,4 +15,4 @@ public class PpssppActivity extends NativeActivity { { return false; } -} \ No newline at end of file +} \ No newline at end of file From f5efd6f2b13f1f5267200343957ce9e446f6f172 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 16:49:02 +0100 Subject: [PATCH 062/276] JIT: add option to enable/disable jit of memory instructions. for crash safety. --- Core/Config.cpp | 3 +++ Core/Config.h | 1 + Core/MIPS/x86/CompFPU.cpp | 5 +++++ Core/MIPS/x86/CompLoadStore.cpp | 7 ++++++- Windows/WndMainWindow.cpp | 6 ++++-- Windows/ppsspp.rc | 1 + Windows/resource.h | 3 ++- android/jni/EmuScreen.cpp | 1 - android/jni/MenuScreens.cpp | 2 +- 9 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 135d0a26eb..60529a4f67 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -49,8 +49,10 @@ void CConfig::Load(const char *iniFileName) general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true); general->Get("CurrentDirectory", ¤tDirectory, ""); general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false); + IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Get("Core", &iCpuCore, 0); + cpu->Get("FastMemory", &bFastMemory, false); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); graphics->Get("ShowFPSCounter", &bShowFPSCounter, false); @@ -88,6 +90,7 @@ void CConfig::Save() general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Set("Core", iCpuCore); + cpu->Set("FastMemory", bFastMemory); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); graphics->Set("ShowFPSCounter", bShowFPSCounter); diff --git a/Core/Config.h b/Core/Config.h index 240b0fddb7..e70ca017d2 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -41,6 +41,7 @@ public: bool bSpeedLimit; bool bConfirmOnQuit; bool bIgnoreBadMemAccess; + bool bFastMemory; // GFX bool bDisplayFramebuffer; diff --git a/Core/MIPS/x86/CompFPU.cpp b/Core/MIPS/x86/CompFPU.cpp index f14ac8911d..b3bbf7a694 100644 --- a/Core/MIPS/x86/CompFPU.cpp +++ b/Core/MIPS/x86/CompFPU.cpp @@ -17,6 +17,7 @@ #include "../MIPS.h" +#include "../../Config.h" #include "Common/Common.h" #include "Jit.h" #include "RegCache.h" @@ -86,6 +87,10 @@ void Jit::Comp_FPU3op(u32 op) void Jit::Comp_FPULS(u32 op) { CONDITIONAL_DISABLE; + if (!g_Config.bFastMemory) { + DISABLE; + } + s32 offset = (s16)(op&0xFFFF); int ft = ((op>>16)&0x1f); diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 69560307f8..631dc803aa 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -17,6 +17,7 @@ #include "../../MemMap.h" #include "../MIPSAnalyst.h" +#include "../../Config.h" #include "Jit.h" #include "RegCache.h" @@ -42,7 +43,11 @@ namespace MIPSComp { void Jit::Comp_ITypeMem(u32 op) { - // OLDD + if (!g_Config.bFastMemory) + { + DISABLE; + } + int offset = (signed short)(op&0xFFFF); int rt = _RT; int rs = _RS; diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 9146e38696..679459b1d6 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -112,8 +112,9 @@ namespace MainWindow AdjustWindowRect(&rcOuter, WS_OVERLAPPEDWINDOW, TRUE); } - void SetZoom(int zoom) { - g_Config.iWindowZoom = zoom; + void SetZoom(float zoom) { + if (zoom < 5) + g_Config.iWindowZoom = zoom; RECT rc, rcOuter; GetWindowRectAtZoom(zoom, rc, rcOuter); MoveWindow(hwndMain, rcOuter.left, rcOuter.top, rcOuter.right - rcOuter.left, rcOuter.bottom - rcOuter.top, TRUE); @@ -638,6 +639,7 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats); CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe); CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); + CHECKITEM(ID_OPTIONS_FASTMEMORY, g_Config.bFastMemory); BOOL enable = !Core_IsStepping(); EnableMenuItem(menu,ID_EMULATION_RUN,enable); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 70e0d2bd13..64c8282667 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -215,6 +215,7 @@ BEGIN MENUITEM "&Display Raw Framebuffer", ID_OPTIONS_DISPLAYRAWFRAMEBUFFER MENUITEM "&Buffered Rendering\tF5", ID_OPTIONS_BUFFEREDRENDERING MENUITEM "&Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM + MENUITEM "&Fast Memory (dynarec, unstable)", ID_OPTIONS_FASTMEMORY MENUITEM "&Wireframe (experimental)", ID_OPTIONS_WIREFRAME MENUITEM "&Show Debug Statistics", ID_OPTIONS_SHOWDEBUGSTATISTICS MENUITEM SEPARATOR diff --git a/Windows/resource.h b/Windows/resource.h index fbaf91b309..09a16838bb 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -245,13 +245,14 @@ #define ID_OPTIONS_SHOWDEBUGSTATISTICS 40122 #define ID_OPTIONS_WIREFRAME 40123 #define ID_OPTIONS_HARDWARETRANSFORM 40124 +#define ID_OPTIONS_FASTMEMORY 40125 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40125 +#define _APS_NEXT_COMMAND_VALUE 40126 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/android/jni/EmuScreen.cpp b/android/jni/EmuScreen.cpp index b21ab0b36c..62db3b03f1 100644 --- a/android/jni/EmuScreen.cpp +++ b/android/jni/EmuScreen.cpp @@ -179,7 +179,6 @@ void EmuScreen::render() ui_draw2d.Begin(DBMODE_NORMAL); - // Make this configurable. if (g_Config.bShowTouchControls) DrawGamepad(ui_draw2d); diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 8052c357ca..7fe29c5d9d 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -239,7 +239,7 @@ void SettingsScreen::render() { // VLinear vlinear(10, 80, 10); int x = 30; int y = 50; - UICheckBox(GEN_ID, x, y += 50, "Enable Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound); + UICheckBox(GEN_ID, x, y += 50, "Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound); UICheckBox(GEN_ID, x, y += 50, "Buffered Rendering (may fix flicker)", ALIGN_TOPLEFT, &g_Config.bBufferedRendering); UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform); From 91744a03b09bded341b0f11d0e8d14203926fd9d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 16:49:34 +0100 Subject: [PATCH 063/276] Warning fixes --- Core/Dialog/PSPOskDialog.cpp | 2 +- Core/HLE/sceDisplay.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 66981f7910..4312295612 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -160,7 +160,7 @@ void PSPOskDialog::HackyGetStringWide(std::string& _string, const u32 em_address char *string = stringBuffer; char c; u32 addr = em_address; - while ((c = (Memory::Read_U16(addr)))) + while ((c = (char)(Memory::Read_U16(addr)))) { *string++ = c; addr+=2; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 8b0fca887e..a417ea9cdc 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -145,7 +145,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) __DisplayFireVblank(); // Wake up threads waiting for VBlank - for (int i = 0; i < vblankWaitingThreads.size(); i++) { + for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0); } vblankWaitingThreads.clear(); From 4c23d668e1302aa90183695ced35b3d151e28ef4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 16:49:42 +0100 Subject: [PATCH 064/276] Cleanup and reorganize gpu code a little --- GPU/GLES/DisplayListInterpreter.cpp | 17 ++- GPU/GLES/DisplayListInterpreter.h | 3 +- GPU/GLES/ShaderManager.cpp | 6 +- GPU/GLES/ShaderManager.h | 10 +- GPU/GLES/StateMapping.cpp | 169 +++++++++++++++++++++ GPU/GLES/TransformPipeline.cpp | 228 ++++------------------------ GPU/GLES/TransformPipeline.h | 50 +++++- GPU/GPUState.h | 69 ++------- GPU/Null/NullGpu.cpp | 6 +- 9 files changed, 288 insertions(+), 270 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 79dd01d42a..d516cfe9e4 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -948,9 +948,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; - gstate_c.lightColor[t][l].r = r; - gstate_c.lightColor[t][l].g = g; - gstate_c.lightColor[t][l].b = b; + gstate_c.lightColor[t][l][0] = r; + gstate_c.lightColor[t][l][1] = g; + gstate_c.lightColor[t][l][2] = b; if (diff) shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); } @@ -1236,7 +1236,7 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; u32 diff = op ^ gstate.cmdmem[cmd]; - gstate.cmdmem[cmd] = op; // crashes if I try to put the whole op there?? + gstate.cmdmem[cmd] = op; ExecuteOp(op, diff); @@ -1257,6 +1257,15 @@ void GLES_GPU::UpdateStats() void GLES_GPU::DoBlockTransfer() { + // TODO: This is used a lot to copy data around between render targets and textures, + // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: + // * Does dstBasePtr point to an existing texture? If so invalidate it and reload it immediately. + // + // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so + // either copy between rt and texture or reassign the texture to point to the render target + // + // etc.... + u32 srcBasePtr = (gstate.transfersrc & 0xFFFFFF) | ((gstate.transfersrcw & 0xFF0000) << 8); u32 srcStride = gstate.transfersrcw & 0x3FF; diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 7d3a6708b8..690088e98e 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -25,6 +25,7 @@ #include "gfx_es2/fbo.h" class ShaderManager; +class LinkedShader; struct DecVtxFormat; class GLES_GPU : public GPUInterface @@ -52,7 +53,7 @@ public: private: // TransformPipeline.cpp void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); - void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); + //void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); void ApplyDrawState(); void Flush(int prim); void UpdateViewportAndProjection(); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 41ac53c8e3..819b2815b7 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -260,9 +260,9 @@ void LinkedShader::use() { glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]); glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]); glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]); - glUniform3fv(u_lightambient[i], 1, &gstate_c.lightColor[0][i].r); - glUniform3fv(u_lightdiffuse[i], 1, &gstate_c.lightColor[1][i].r); - glUniform3fv(u_lightspecular[i], 1, &gstate_c.lightColor[2][i].r); + glUniform3fv(u_lightambient[i], 1, gstate_c.lightColor[0][i]); + glUniform3fv(u_lightdiffuse[i], 1, gstate_c.lightColor[1][i]); + glUniform3fv(u_lightspecular[i], 1, gstate_c.lightColor[2][i]); } } diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index 6b1a480bc5..c7cf3d1040 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -23,10 +23,11 @@ #include "VertexShaderGenerator.h" #include "FragmentShaderGenerator.h" -struct Shader; +class Shader; -struct LinkedShader +class LinkedShader { +public: LinkedShader(Shader *vs, Shader *fs); ~LinkedShader(); @@ -116,11 +117,12 @@ enum // Real public interface -struct Shader -{ +class Shader { +public: Shader(const char *code, uint32_t shaderType); uint32_t shader; const std::string &source() const { return source_; } + private: std::string source_; }; diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index dd4b58b6f2..7b6dcd32b2 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -1,4 +1,11 @@ #include "StateMapping.h" +#include "../../native/gfx_es2/gl_state.h" + +#include "../Math3D.h" +#include "../GPUState.h" +#include "../ge_constants.h" +#include "DisplayListInterpreter.h" +#include "ShaderManager.h" const GLint aLookup[] = { GL_DST_COLOR, @@ -51,3 +58,165 @@ const GLuint ztests[] = GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL, }; + +void GLES_GPU::ApplyDrawState() +{ + + // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. + + // TODO: The top bit of the alpha channel should be written to the stencil bit somehow. This appears to require very expensive multipass rendering :( Alternatively, one could do a + // single fullscreen pass that converts alpha to stencil (or 2 passes, to set both the 0 and 1 values) very easily. + + // Set cull + bool wantCull = !gstate.isModeClear() && !gstate.isModeThrough() && gstate.isCullEnabled(); + glstate.cullFace.set(wantCull); + + if(wantCull) { + u8 cullMode = gstate.getCullMode(); + glstate.cullFaceMode.set(cullingMode[cullMode]); + } + + // Set blend + bool wantBlend = !gstate.isModeClear() && (gstate.alphaBlendEnable & 1); + glstate.blend.set(wantBlend); + if(wantBlend) { + // This can't be done exactly as there are several PSP blend modes that are impossible to do on OpenGL ES 2.0, and some even on regular OpenGL for desktop. + // HOWEVER - we should be able to approximate the 2x modes in the shader, although they will clip wrongly. + + // Examples of seen unimplementable blend states: + // Mortal Kombat Unchained: FixA=0000ff FixB=000080 FuncA=10 FuncB=10 + + int blendFuncA = gstate.getBlendFuncA(); + int blendFuncB = gstate.getBlendFuncB(); + int blendFuncEq = gstate.getBlendEq(); + + glstate.blendEquation.set(eqLookup[blendFuncEq]); + + if (blendFuncA != GE_SRCBLEND_FIXA && blendFuncB != GE_DSTBLEND_FIXB) { + // All is valid, no blendcolor needed + glstate.blendFunc.set(aLookup[blendFuncA], bLookup[blendFuncB]); + } else { + 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 == GL_INVALID_ENUM && blendFuncA == GE_SRCBLEND_FIXA) { + if (fixA == 0xFFFFFF) + glBlendFuncA = GL_ONE; + else if (fixA == 0) + glBlendFuncA = GL_ZERO; + } + if (glBlendFuncB == GL_INVALID_ENUM && blendFuncB == GE_DSTBLEND_FIXB) { + if (fixB == 0xFFFFFF) + glBlendFuncB = GL_ONE; + else if (fixB == 0) + glBlendFuncB = GL_ZERO; + } + 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 != 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 == 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; + const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f}; + glstate.blendColor.set(blendColor); + } else if (fixA == fixB) { + glBlendFuncA = GL_CONSTANT_COLOR; + glBlendFuncB = GL_CONSTANT_COLOR; + const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f}; + glstate.blendColor.set(blendColor); + } else { + DEBUG_LOG(HLE, "ERROR INVALID blendcolorstate: FixA=%06x FixB=%06x FuncA=%i FuncB=%i", gstate.getFixA(), gstate.getFixB(), gstate.getBlendFuncA(), gstate.getBlendFuncB()); + glBlendFuncA = GL_ONE; + glBlendFuncB = GL_ONE; + } + } + // At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set somehow. + + glstate.blendFunc.set(glBlendFuncA, glBlendFuncB); + } + } + + bool wantDepthTest = gstate.isModeClear() || gstate.isDepthTestEnabled(); + glstate.depthTest.set(wantDepthTest); + if(wantDepthTest) { + // Force GL_ALWAYS if mode clear + int depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc(); + glstate.depthFunc.set(ztests[depthTestFunc]); + } + + bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled(); + glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE); + + float depthRangeMin = gstate_c.zOff - gstate_c.zScale; + float depthRangeMax = gstate_c.zOff + gstate_c.zScale; + glstate.depthRange.set(depthRangeMin, depthRangeMax); +} + +void GLES_GPU::UpdateViewportAndProjection() +{ + bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; + + // We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1 + int regionX1 = gstate.region1 & 0x3FF; + int regionY1 = (gstate.region1 >> 10) & 0x3FF; + int regionX2 = (gstate.region2 & 0x3FF) + 1; + int regionY2 = ((gstate.region2 >> 10) & 0x3FF) + 1; + + float offsetX = (float)(gstate.offsetx & 0xFFFF) / 16.0f; + float offsetY = (float)(gstate.offsety & 0xFFFF) / 16.0f; + + if (throughmode) { + // No viewport transform here. Let's experiment with using region. + return; + glViewport((0 + regionX1) * renderWidthFactor_, (0 - regionY1) * renderHeightFactor_, (regionX2 - regionX1) * renderWidthFactor_, (regionY2 - regionY1) * renderHeightFactor_); + } else { + // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. + float vpXa = getFloat24(gstate.viewportx1); + float vpXb = getFloat24(gstate.viewportx2); + float vpYa = getFloat24(gstate.viewporty1); + float vpYb = getFloat24(gstate.viewporty2); + float vpZa = getFloat24(gstate.viewportz1); // / 65536.0f should map it to OpenGL's 0.0-1.0 Z range + float vpZb = getFloat24(gstate.viewportz2); // / 65536.0f + + // The viewport transform appears to go like this: + // Xscreen = -offsetX + vpXb + vpXa * Xview + // Yscreen = -offsetY + vpYb + vpYa * Yview + // Zscreen = vpZb + vpZa * Zview + + // This means that to get the analogue glViewport we must: + float vpX0 = vpXb - offsetX - vpXa; + float vpY0 = vpYb - offsetY + vpYa; // Need to account for sign of Y + gstate_c.vpWidth = vpXa * 2; + gstate_c.vpHeight = -vpYa * 2; + + return; + + float vpWidth = fabsf(gstate_c.vpWidth); + float vpHeight = fabsf(gstate_c.vpHeight); + + // TODO: These two should feed into glDepthRange somehow. + float vpZ0 = (vpZb - vpZa) / 65536.0f; + float vpZ1 = (vpZa * 2) / 65536.0f; + + vpX0 *= renderWidthFactor_; + vpY0 *= renderHeightFactor_; + vpWidth *= renderWidthFactor_; + vpHeight *= renderHeightFactor_; + + // Flip vpY0 to match the OpenGL coordinate system. + vpY0 = renderHeight_ - (vpY0 + vpHeight); + glViewport(vpX0, vpY0, vpWidth, vpHeight); + // Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh. + shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); + } +} diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index f618ebb843..91a8548749 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -31,8 +31,7 @@ #include "ShaderManager.h" #include "DisplayListInterpreter.h" -GLuint glprim[8] = -{ +const GLuint glprim[8] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, @@ -43,9 +42,11 @@ GLuint glprim[8] = }; u8 decoded[65536 * 32]; +// uint16_t decIndex[65536]; // Unused + TransformedVertex transformed[65536]; TransformedVertex transformedExpanded[65536]; -uint16_t indexBuffer[65536]; // Unused + // TODO: This should really return 2 colors, one for specular and one for diffuse. @@ -159,7 +160,8 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ if (lightScale > 1.0f) lightScale = 1.0f; } - Color4 diff = (gstate_c.lightColor[1][l] * *diffuse) * (dot * lightScale); + Color4 lightDiff(gstate_c.lightColor[1][l], 0.0f); + Color4 diff = (lightDiff * *diffuse) * (dot * lightScale); // Real PSP specular Vec3 toViewer(0,0,1); @@ -175,13 +177,15 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ dot = halfVec * norm; if (dot >= 0) { - lightSum1 += (gstate_c.lightColor[2][l] * *specular * (powf(dot, specCoef_)*lightScale)); + Color4 lightSpec(gstate_c.lightColor[2][l], 0.0f); + lightSum1 += (lightSpec * *specular * (powf(dot, specCoef_)*lightScale)); } } dots[l] = dot; if (gstate.lightEnable[l] & 1) { - lightSum0 += gstate_c.lightColor[0][l] * *ambient + diff; + Color4 lightAmbient(gstate_c.lightColor[2][l], 1.0f); + lightSum0 += lightAmbient * *ambient + diff; } } @@ -243,7 +247,22 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF VertexAttribDisable(program->a_position, decFmt.posfmt); } -void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV) +// This is the software transform pipeline, which is necessary for supporting RECT +// primitives correctly, and may be easier to use for debugging than the hardware +// transform pipeline. + +// There's code here that simply expands transformed RECTANGLES into plain triangles. + +// We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0. +// Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of +// this code. + +// Actually, if we find the camera-relative right and down vectors, it might even be possible to add the extra points in pre-transformed +// space and thus make decent use of hardware transform. + +// Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for +// GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. +void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV) { /* DEBUG_LOG(G3D, "View matrix:"); @@ -254,28 +273,12 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for DEBUG_LOG(G3D, "%f %f %f", m[9], m[10], m[11]); */ - // Then, transform and draw in one big swoop (urgh!) - // need to move this to the shader. - - // We're gonna have to keep software transforming RECTANGLES, unless we use a geom shader which we can't on OpenGL ES 2.0. - // Usually, though, these primitives don't use lighting etc so it's no biggie performance wise, but it would be nice to get rid of - // this code. - - // Actually, if we find the camera-relative right and down vectors, it might even be possible to add the extra points in pre-transformed - // space and thus make decent use of hardware transform. - - // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for - // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. - // Temporary storage for RECTANGLES emulation float v2[3] = {0}; float uv2[2] = {0}; bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; - - // TODO: Could use glDrawElements in some cases, see below. - // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. #if defined(USING_GLES2) @@ -453,7 +456,7 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for } break; case 2: - // Shade mapping - use dots from light sources to generate U and V. + // Shade mapping - use dot products from light sources to generate U and V. { uv[0] = dots[gstate.getUVLS0()]; uv[1] = dots[gstate.getUVLS1()]; @@ -466,21 +469,17 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for } // Transform the coord by the view matrix. - // We only really need to do it here for RECTANGLES drawing. However, - // there's no point in optimizing it out because all other primitives - // will be moved to hardware transform anyway. Vec3ByMatrix43(v, out, gstate.viewMatrix); } - // TODO: Write to a flexible buffer. + // TODO: Write to a flexible buffer, we don't always need all four components. memcpy(&transformed[index].x, v, 3 * sizeof(float)); memcpy(&transformed[index].uv, uv, 2 * sizeof(float)); memcpy(&transformed[index].color0, c0, 4 * sizeof(float)); memcpy(&transformed[index].color1, c1, 3 * sizeof(float)); } - // Step 2: Expand using the index buffer, and expand rectangles. - + // Step 2: expand rectangles. const TransformedVertex *drawBuffer = transformed; int numTrans = 0; @@ -488,7 +487,6 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for if (forceIndexType != -1) { indexType = forceIndexType; } - bool drawIndexed = false; GLuint glIndexType = 0; @@ -581,7 +579,8 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for } } - // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, these spam the gDebugger log. + // TODO: Make a cache for glEnableVertexAttribArray and glVertexAttribPtr states, + // these spam the gDebugger log. glEnableVertexAttribArray(program->a_position); if (program->a_texcoord != -1) glEnableVertexAttribArray(program->a_texcoord); if (program->a_color0 != -1) glEnableVertexAttribArray(program->a_color0); @@ -591,7 +590,6 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 3 * 4); if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); - // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); if (drawIndexed) { glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); } else { @@ -603,10 +601,6 @@ void GLES_GPU::SoftwareTransformAndDraw(int prim, LinkedShader *program, int for if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } -// This is the software transform pipeline, which is necessary for supporting RECT -// primitives correctly. Other primitives are possible to transform and light in hardware -// using vertex shader, which will be way, way faster, especially on mobile. This has -// not yet been implemented though. void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { int indexLowerBound, indexUpperBound; @@ -653,7 +647,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (CanUseHardwareTransform(prim)) { SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), decoded); - bool drawIndexed; GLuint glIndexType; int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); @@ -680,7 +673,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } else { glDrawArrays(glprim[prim], 0, numTrans); } - DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { SoftwareTransformAndDraw(prim, program, forceIndexType, vertexCount, inds, dec.GetDecVtxFmt(), indexLowerBound, indexUpperBound, customUV); @@ -690,161 +682,3 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte void GLES_GPU::Flush(int prim) { // TODO } - -void GLES_GPU::ApplyDrawState() -{ - - // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. - - // TODO: The top bit of the alpha channel should be written to the stencil bit somehow. This appears to require very expensive multipass rendering :( Alternatively, one could do a - // single fullscreen pass that converts alpha to stencil (or 2 passes, to set both the 0 and 1 values) very easily. - - // Set cull - bool wantCull = !gstate.isModeClear() && !gstate.isModeThrough() && gstate.isCullEnabled(); - glstate.cullFace.set(wantCull); - - if(wantCull) { - u8 cullMode = gstate.getCullMode(); - glstate.cullFaceMode.set(cullingMode[cullMode]); - } - - // Set blend - bool wantBlend = !gstate.isModeClear() && (gstate.alphaBlendEnable & 1); - glstate.blend.set(wantBlend); - if(wantBlend) { - // This can't be done exactly as there are several PSP blend modes that are impossible to do on OpenGL ES 2.0, and some even on regular OpenGL for desktop. - // HOWEVER - we should be able to approximate the 2x modes in the shader, although they will clip wrongly. - int blendFuncA = gstate.getBlendFuncA(); - int blendFuncB = gstate.getBlendFuncB(); - int blendFuncEq = gstate.getBlendEq(); - - glstate.blendEquation.set(eqLookup[blendFuncEq]); - - if (blendFuncA != GE_SRCBLEND_FIXA && blendFuncB != GE_DSTBLEND_FIXB) { - // All is valid, no blendcolor needed - glstate.blendFunc.set(aLookup[blendFuncA], bLookup[blendFuncB]); - } else { - 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 == GL_INVALID_ENUM && blendFuncA == GE_SRCBLEND_FIXA) { - if (fixA == 0xFFFFFF) - glBlendFuncA = GL_ONE; - else if (fixA == 0) - glBlendFuncA = GL_ZERO; - } - if (glBlendFuncB == GL_INVALID_ENUM && blendFuncB == GE_DSTBLEND_FIXB) { - if (fixB == 0xFFFFFF) - glBlendFuncB = GL_ONE; - else if (fixB == 0) - glBlendFuncB = GL_ZERO; - } - 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 != 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 == 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; - const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f}; - glstate.blendColor.set(blendColor); - } else if (fixA == fixB) { - glBlendFuncA = GL_CONSTANT_COLOR; - glBlendFuncB = GL_CONSTANT_COLOR; - const float blendColor[4] = {(fixA & 0xFF)/255.0f, ((fixA >> 8) & 0xFF)/255.0f, ((fixA >> 16) & 0xFF)/255.0f, 1.0f}; - glstate.blendColor.set(blendColor); - } else { - NOTICE_LOG(HLE, "ERROR INVALID blendcolorstate: FixA=%06x FixB=%06x FuncA=%i FuncB=%i", gstate.getFixA(), gstate.getFixB(), gstate.getBlendFuncA(), gstate.getBlendFuncB()); - glBlendFuncA = GL_ONE; - glBlendFuncB = GL_ONE; - } - } - // At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set somehow. - - glstate.blendFunc.set(glBlendFuncA, glBlendFuncB); - } - } - - bool wantDepthTest = gstate.isModeClear() || gstate.isDepthTestEnabled(); - glstate.depthTest.set(wantDepthTest); - if(wantDepthTest) { - // Force GL_ALWAYS if mode clear - int depthTestFunc = gstate.isModeClear() ? 1 : gstate.getDepthTestFunc(); - glstate.depthFunc.set(ztests[depthTestFunc]); - } - - bool wantDepthWrite = gstate.isModeClear() || gstate.isDepthWriteEnabled(); - glstate.depthWrite.set(wantDepthWrite ? GL_TRUE : GL_FALSE); - - float depthRangeMin = gstate_c.zOff - gstate_c.zScale; - float depthRangeMax = gstate_c.zOff + gstate_c.zScale; - glstate.depthRange.set(depthRangeMin, depthRangeMax); -} - -void GLES_GPU::UpdateViewportAndProjection() -{ - bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; - - // We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1 - int regionX1 = gstate.region1 & 0x3FF; - int regionY1 = (gstate.region1 >> 10) & 0x3FF; - int regionX2 = (gstate.region2 & 0x3FF) + 1; - int regionY2 = ((gstate.region2 >> 10) & 0x3FF) + 1; - - float offsetX = (float)(gstate.offsetx & 0xFFFF) / 16.0f; - float offsetY = (float)(gstate.offsety & 0xFFFF) / 16.0f; - - if (throughmode) { - // No viewport transform here. Let's experiment with using region. - return; - glViewport((0 + regionX1) * renderWidthFactor_, (0 - regionY1) * renderHeightFactor_, (regionX2 - regionX1) * renderWidthFactor_, (regionY2 - regionY1) * renderHeightFactor_); - } else { - // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. - float vpXa = getFloat24(gstate.viewportx1); - float vpXb = getFloat24(gstate.viewportx2); - float vpYa = getFloat24(gstate.viewporty1); - float vpYb = getFloat24(gstate.viewporty2); - float vpZa = getFloat24(gstate.viewportz1); // / 65536.0f should map it to OpenGL's 0.0-1.0 Z range - float vpZb = getFloat24(gstate.viewportz2); // / 65536.0f - - // The viewport transform appears to go like this: - // Xscreen = -offsetX + vpXb + vpXa * Xview - // Yscreen = -offsetY + vpYb + vpYa * Yview - // Zscreen = vpZb + vpZa * Zview - - // This means that to get the analogue glViewport we must: - float vpX0 = vpXb - offsetX - vpXa; - float vpY0 = vpYb - offsetY + vpYa; // Need to account for sign of Y - gstate_c.vpWidth = vpXa * 2; - gstate_c.vpHeight = -vpYa * 2; - - return; - - float vpWidth = fabsf(gstate_c.vpWidth); - float vpHeight = fabsf(gstate_c.vpHeight); - - // TODO: These two should feed into glDepthRange somehow. - float vpZ0 = (vpZb - vpZa) / 65536.0f; - float vpZ1 = (vpZa * 2) / 65536.0f; - - vpX0 *= renderWidthFactor_; - vpY0 *= renderHeightFactor_; - vpWidth *= renderWidthFactor_; - vpHeight *= renderHeightFactor_; - - // Flip vpY0 to match the OpenGL coordinate system. - vpY0 = renderHeight_ - (vpY0 + vpHeight); - glViewport(vpX0, vpY0, vpWidth, vpHeight); - // Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh. - shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); - } -} diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 1abecce3ef..5314e152f6 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -17,4 +17,52 @@ #pragma once -struct LinkedShader; +class LinkedShader; +struct DecVtxFormat; + +// Only used by SW transform +struct Color4 +{ + float r,g,b,a; + Color4() : r(0), g(0), b(0), a(0) { } + Color4(float _r, float _g, float _b, float _a=1.0f) + { + r=_r; g=_g; b=_b; a=_a; + } + Color4(const float in[4]) {r=in[0];g=in[1];b=in[2];a=in[3];} + Color4(const float in[3], float alpha) {r=in[0];g=in[1];b=in[2];a=alpha;} + + const float &operator [](int i) const {return *(&r + i);} + + Color4 operator *(float f) const + { + return Color4(f*r,f*g,f*b,f*a); + } + Color4 operator *(const Color4 &c) const + { + return Color4(r*c.r,g*c.g,b*c.b,a*c.a); + } + Color4 operator +(const Color4 &c) const + { + return Color4(r+c.r,g+c.g,b+c.b,a+c.a); + } + void operator +=(const Color4 &c) + { + r+=c.r; + g+=c.g; + b+=c.b; + a+=c.a; + } + void GetFromRGB(u32 col) + { + r = ((col>>16) & 0xff)/255.0f; + g = ((col>>8) & 0xff)/255.0f; + b = ((col>>0) & 0xff)/255.0f; + } + void GetFromA(u32 col) + { + a = (col&0xff)/255.0f; + } +}; + +void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 35640c18eb..66cb21d90b 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -22,58 +22,10 @@ #include "ge_constants.h" #include -// TODO: this doesn't belong here -struct Color4 -{ - float r,g,b,a; - Color4() : r(0), g(0), b(0), a(0) { } - Color4(float _r, float _g, float _b, float _a=1.0f) - { - r=_r; g=_g; b=_b; a=_a; - } - Color4(const float in[4]) {r=in[0];g=in[1];b=in[2];a=in[3];} - - float &operator [](int i) {return *(&r + i);} - const float &operator [](int i) const {return *(&r + i);} - - Color4 operator *(float f) const - { - return Color4(f*r,f*g,f*b,f*a); - } - Color4 operator *(const Color4 &c) const - { - return Color4(r*c.r,g*c.g,b*c.b,a*c.a); - } - void operator *=(const Color4 &c) - { - r*=c.r,g*=c.g,b*=c.b,a*=c.a; - } - Color4 operator +(const Color4 &c) const - { - return Color4(r+c.r,g+c.g,b+c.b,a+c.a); - } - void operator +=(const Color4 &c) - { - r+=c.r; - g+=c.g; - b+=c.b; - a+=c.a; - } - void GetFromRGB(u32 col) - { - r = ((col>>16)&0xff)/255.0f; - g = ((col>>8)&0xff)/255.0f; - b = ((col>>0)&0xff)/255.0f; - } - void GetFromA(u32 col) - { - a = (col&0xff)/255.0f; - } -}; - - struct GPUgstate { + // Getting rid of this ugly union in favor of the accessor functions + // might be a good idea.... union { u32 cmdmem[256]; @@ -239,25 +191,28 @@ struct GPUgstate float tgenMatrix[12]; float boneMatrix[12 * 8]; // Eight bone matrices. - bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; } + // Pixel Pipeline bool isModeClear() const { return clearmode & 1; } bool isCullEnabled() const { return cullfaceEnable & 1; } - int getCullMode() const { return cullmode & 1; } - int getBlendFuncA() const { return blend & 0xF; } + int getCullMode() const { return cullmode & 1; } + int getBlendFuncA() const { return blend & 0xF; } u32 getFixA() const { return blendfixa & 0xFFFFFF; } u32 getFixB() const { return blendfixb & 0xFFFFFF; } - int getBlendFuncB() const { return (blend >> 4) & 0xF; } - int getBlendEq() const { return (blend >> 8) & 0x7; } + int getBlendFuncB() const { return (blend >> 4) & 0xF; } + int getBlendEq() const { return (blend >> 8) & 0x7; } bool isDepthTestEnabled() const { return zTestEnable & 1; } bool isDepthWriteEnabled() const { return !(zmsk & 1); } - int getDepthTestFunc() const { return ztestfunc & 0x7; } + int getDepthTestFunc() const { return ztestfunc & 0x7; } bool isFogEnabled() const { return fogEnable & 1; } + // UV gen int getUVGenMode() const { return texmapmode & 3;} // 2 bits int getUVProjMode() const { return (texmapmode >> 8) & 3;} // 2 bits int getUVLS0() const { return texshade & 0x3; } // 2 bits int getUVLS1() const { return (texshade >> 8) & 0x3; } // 2 bits + // Vertex type + bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; } int getNumBoneWeights() const { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); } @@ -279,7 +234,7 @@ struct GPUStateCache float lightpos[4][3]; float lightdir[4][3]; float lightatt[4][3]; - Color4 lightColor[3][4]; //Amtient Diffuse Specular + float lightColor[3][4][3]; //Amtient Diffuse Specular float morphWeights[8]; // bezier patch subdivision diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index f983d6b688..c327266a02 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -596,9 +596,9 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; - gstate_c.lightColor[t][l].r = r; - gstate_c.lightColor[t][l].g = g; - gstate_c.lightColor[t][l].b = b; + gstate_c.lightColor[t][l][0] = r; + gstate_c.lightColor[t][l][1] = g; + gstate_c.lightColor[t][l][2] = b; } break; From 2ec8606fcb1f80569f7a73b940a8bf7fb5a291f7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 17:13:00 +0100 Subject: [PATCH 065/276] Flip Y axis for xinput --- Windows/XinputDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 86fc0dab64..6f7687f49b 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -41,7 +41,7 @@ int XinputDevice::UpdateState() { if ( dwResult == ERROR_SUCCESS ) { this->ApplyDiff(state); Stick left = NormalizedDeadzoneFilter(state); - __CtrlSetAnalog(left.x, left.y); + __CtrlSetAnalog(left.x, -left.y); this->prevState = state; this->check_delay = 0; return 0; From 88578cc525f6d05d0aa60c578cb0bf683261f4e7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 22 Dec 2012 00:49:53 +0800 Subject: [PATCH 066/276] Quick add checkitem for option fast memory --- Windows/WndMainWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index a80e17345c..246c048244 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -479,6 +479,10 @@ namespace MainWindow g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; UpdateMenus(); break; + case ID_OPTIONS_FASTMEMORY: + g_Config.bFastMemory = !g_Config.bFastMemory; + UpdateMenus(); + break; ////////////////////////////////////////////////////////////////////////// From 4eeab8338951b7407ec5943fe4d62f7d0b4b7c5e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 17:50:22 +0100 Subject: [PATCH 067/276] Add IndexGenerator.cpp/h which will later be used to combine small draw calls into large indexed draw calls, for better performance. --- CMakeLists.txt | 2 + GPU/CMakeLists.txt | 1 + GPU/GLES/IndexGenerator.cpp | 232 +++++++++++++++++++++++++++++ GPU/GLES/IndexGenerator.h | 57 +++++++ GPU/GLES/VertexShaderGenerator.cpp | 5 - GPU/GPU.vcxproj | 2 + GPU/GPU.vcxproj.filters | 6 + android/jni/Android.mk | 1 + 8 files changed, 301 insertions(+), 5 deletions(-) create mode 100644 GPU/GLES/IndexGenerator.cpp create mode 100644 GPU/GLES/IndexGenerator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 858bc710c4..adaf9dc6fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -786,6 +786,8 @@ add_library(GPU OBJECT GPU/GLES/FragmentShaderGenerator.h GPU/GLES/Framebuffer.cpp GPU/GLES/Framebuffer.h + GPU/GLES/IndexGenerator.cpp + GPU/GLES/IndexGenerator.h GPU/GLES/ShaderManager.cpp GPU/GLES/ShaderManager.h GPU/GLES/StateMapping.cpp diff --git a/GPU/CMakeLists.txt b/GPU/CMakeLists.txt index 803200ae6d..ad56972231 100644 --- a/GPU/CMakeLists.txt +++ b/GPU/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRCS GLES/DisplayListInterpreter.cpp GLES/FragmentShaderGenerator.cpp GLES/Framebuffer.cpp + GLES/IndexGenerator.cpp GLES/ShaderManager.cpp GLES/StateMapping.cpp GLES/TextureCache.cpp diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp new file mode 100644 index 0000000000..7a786488cf --- /dev/null +++ b/GPU/GLES/IndexGenerator.cpp @@ -0,0 +1,232 @@ +// 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 "IndexGenerator.h" + +// Points don't need indexing... +const u8 indexedPrimitiveType[7] = { + GE_PRIM_POINTS, + GE_PRIM_LINES, + GE_PRIM_LINES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, +}; + +void IndexGenerator::Reset() { + prim_ = -1; + inds_ = 0; +} + +bool IndexGenerator::PrimCompatible(int prim) { + if (prim_ == -1) + return true; + return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_]; +} + +void IndexGenerator::Start(u16 *inds, int baseIndex, int prim) +{ + this->inds_ = inds; + index_ = baseIndex; +} + +void IndexGenerator::AddList(int numVerts) +{ + //if we have no vertices return + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + i*3; + *inds_++ = index_ + i*3 + 1; + *inds_++ = index_ + i*3 + 2; + } + + // ignore overflow verts + index_ += numVerts; +} + +void IndexGenerator::AddStrip(int numVerts) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i+(wind?2:1); + *inds_++ = index_ + i+(wind?1:2); + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::AddFan(int numVerts) +{ + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_; + *inds_++ = index_ + i + 1; + *inds_++ = index_ + i + 2; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) +{ + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i*3]; + *inds_++ = index_ + offset + inds[i*3 + 1]; + *inds_++ = index_ + offset + inds[i*3 + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + (wind?2:1)]; + *inds_++ = index_ + offset + inds[i + (wind?1:2)]; + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) +{ + if (numVerts <= 0) return; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; + *inds_++ = index_ + offset + inds[i + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) +{ + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i*3]; + *inds_++ = index_ + offset + inds[i*3 + 1]; + *inds_++ = index_ + offset + inds[i*3 + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + (wind?2:1)]; + *inds_++ = index_ + offset + inds[i + (wind?1:2)]; + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) +{ + if (numVerts <= 0) return; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; + *inds_++ = index_ + offset + inds[i + 2]; + } + index_ += numVerts; +} + +//Lines +void IndexGenerator::AddLineList(int numVerts) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::AddLineStrip(int numVerts) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} \ No newline at end of file diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h new file mode 100644 index 0000000000..45d3a0bad3 --- /dev/null +++ b/GPU/GLES/IndexGenerator.h @@ -0,0 +1,57 @@ +// 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 + +#include "CommonTypes.h" +#include "../ge_constants.h" + +class IndexGenerator +{ +public: + void Reset(); + void Start(u16 *indexptr, int baseIndex, int prim); + bool PrimCompatible(int prim); + + // Triangles + void AddList(int numVerts); + void AddStrip(int numVerts); + void AddFan(int numVerts); + // Lines + void AddLineList(int numVerts); + void AddLineStrip(int numVerts); + + // Translates already indexed lists + void TranslateLineList(int numVerts, const u8 *inds, int offset); + void TranslateLineStrip(int numVerts, const u8 *inds, int offset); + void TranslateLineList(int numVerts, const u16 *inds, int offset); + void TranslateLineStrip(int numVerts, const u16 *inds, int offset); + + void TranslateList(int numVerts, const u8 *inds, int offset); + void TranslateStrip(int numVerts, const u8 *inds, int offset); + void TranslateFan(int numVerts, const u8 *inds, int offset); + void TranslateList(int numVerts, const u16 *inds, int offset); + void TranslateStrip(int numVerts, const u16 *inds, int offset); + void TranslateFan(int numVerts, const u16 *inds, int offset); + +private: + u16 *inds_; + int index_; + int prim_; +}; + diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 395021ce56..953b5c684d 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -15,10 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -// TODO: We should transition from doing the transform in software, as seen in TransformPipeline.cpp, -// into doing the transform in the vertex shader - except for Rectangles, there we really need to do -// the transforms ourselves. - #include #if defined(_WIN32) && defined(_DEBUG) #include @@ -42,7 +38,6 @@ static char buffer[16384]; #define WRITE p+=sprintf - bool CanUseHardwareTransform(int prim) { if (!g_Config.bHardwareTransform) diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 7b36bc7078..9b3228b826 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -120,6 +120,7 @@ + @@ -135,6 +136,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index aad3ad15c2..e5a783590f 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -57,6 +57,9 @@ GLES + + GLES + @@ -95,6 +98,9 @@ GLES + + GLES + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 13a44e02f1..84ddbce292 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -72,6 +72,7 @@ LOCAL_SRC_FILES := \ $(SRC)/GPU/GLES/Framebuffer.cpp \ $(SRC)/GPU/GLES/DisplayListInterpreter.cpp \ $(SRC)/GPU/GLES/TextureCache.cpp \ + $(SRC)/GPU/GLES/IndexGenerator.cpp \ $(SRC)/GPU/GLES/TransformPipeline.cpp \ $(SRC)/GPU/GLES/StateMapping.cpp \ $(SRC)/GPU/GLES/VertexDecoder.cpp \ From 2e9daa5f89ebdb3892d6793eedbfb9107c5771f2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 18:46:15 +0100 Subject: [PATCH 068/276] All drawing is now indexed lists, through IndexGenerator. --- GPU/GLES/IndexGenerator.cpp | 50 +++++++++++++ GPU/GLES/IndexGenerator.h | 8 +++ GPU/GLES/TransformPipeline.cpp | 126 ++++++++++++++++----------------- GPU/GLES/TransformPipeline.h | 2 +- GPU/GLES/VertexDecoder.cpp | 2 +- GPU/GLES/VertexDecoder.h | 1 + 6 files changed, 122 insertions(+), 67 deletions(-) diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index 7a786488cf..b08ab3cd5b 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -31,6 +31,7 @@ const u8 indexedPrimitiveType[7] = { void IndexGenerator::Reset() { prim_ = -1; inds_ = 0; + count_ = 0; } bool IndexGenerator::PrimCompatible(int prim) { @@ -41,8 +42,22 @@ bool IndexGenerator::PrimCompatible(int prim) { void IndexGenerator::Start(u16 *inds, int baseIndex, int prim) { + count_ = 0; this->inds_ = inds; index_ = baseIndex; + prim_ = indexedPrimitiveType[prim]; +} + +void IndexGenerator::AddPoints(int numVerts) +{ + //if we have no vertices return + for (int i = 0; i < numVerts; i++) + { + *inds_++ = index_ + i; + } + // ignore overflow verts + index_ += numVerts; + count_ += numVerts; } void IndexGenerator::AddList(int numVerts) @@ -58,6 +73,7 @@ void IndexGenerator::AddList(int numVerts) // ignore overflow verts index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::AddStrip(int numVerts) @@ -72,6 +88,7 @@ void IndexGenerator::AddStrip(int numVerts) wind = !wind; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::AddFan(int numVerts) @@ -84,6 +101,27 @@ void IndexGenerator::AddFan(int numVerts) *inds_++ = index_ + i + 2; } index_ += numVerts; + count_ += numTris * 3; +} + +void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) +{ + for (int i = 0; i < numVerts; i++) + { + *inds_++ = index_ + offset + inds[i]; + } + index_ += numVerts; + count_ += numVerts; +} + +void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) +{ + for (int i = 0; i < numVerts; i++) + { + *inds_++ = index_ + offset + inds[i]; + } + index_ += numVerts; + count_ += numVerts; } void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) @@ -96,6 +134,7 @@ void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) *inds_++ = index_ + offset + inds[i*3 + 2]; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) @@ -110,6 +149,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) wind = !wind; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) @@ -123,6 +163,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) *inds_++ = index_ + offset + inds[i + 2]; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) @@ -135,6 +176,7 @@ void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) *inds_++ = index_ + offset + inds[i*3 + 2]; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) @@ -149,6 +191,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) wind = !wind; } index_ += numVerts; + count_ += numTris * 3; } void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) @@ -162,6 +205,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) *inds_++ = index_ + offset + inds[i + 2]; } index_ += numVerts; + count_ += numTris * 3; } //Lines @@ -174,6 +218,7 @@ void IndexGenerator::AddLineList(int numVerts) *inds_++ = index_ + i*2+1; } index_ += numVerts; + count_ += numLines * 2; } void IndexGenerator::AddLineStrip(int numVerts) @@ -185,6 +230,7 @@ void IndexGenerator::AddLineStrip(int numVerts) *inds_++ = index_ + i + 1; } index_ += numVerts; + count_ += numLines * 2; } void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) @@ -196,6 +242,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) *inds_++ = index_ + i*2+1; } index_ += numVerts; + count_ += numLines * 2; } void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) @@ -207,6 +254,7 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset *inds_++ = index_ + i + 1; } index_ += numVerts; + count_ += numLines * 2; } void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) @@ -218,6 +266,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset *inds_++ = index_ + i*2+1; } index_ += numVerts; + count_ += numLines * 2; } void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) @@ -229,4 +278,5 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse *inds_++ = index_ + i + 1; } index_ += numVerts; + count_ += numLines * 2; } \ No newline at end of file diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index 45d3a0bad3..bb2a9bde00 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -28,6 +28,8 @@ public: void Start(u16 *indexptr, int baseIndex, int prim); bool PrimCompatible(int prim); + // Points (why index these? code simplicity) + void AddPoints(int numVerts); // Triangles void AddList(int numVerts); void AddStrip(int numVerts); @@ -36,6 +38,8 @@ public: void AddLineList(int numVerts); void AddLineStrip(int numVerts); + void TranslatePoints(int numVerts, const u8 *inds, int offset); + void TranslatePoints(int numVerts, const u16 *inds, int offset); // Translates already indexed lists void TranslateLineList(int numVerts, const u8 *inds, int offset); void TranslateLineStrip(int numVerts, const u8 *inds, int offset); @@ -49,9 +53,13 @@ public: void TranslateStrip(int numVerts, const u16 *inds, int offset); void TranslateFan(int numVerts, const u16 *inds, int offset); + int MaxIndex() { return index_; } + int VertexCount() { return count_; } + private: u16 *inds_; int index_; + int count_; int prim_; }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 91a8548749..913f2c23ca 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -30,6 +30,7 @@ #include "VertexDecoder.h" #include "ShaderManager.h" #include "DisplayListInterpreter.h" +#include "IndexGenerator.h" const GLuint glprim[8] = { GL_POINTS, @@ -42,7 +43,9 @@ const GLuint glprim[8] = { }; u8 decoded[65536 * 32]; -// uint16_t decIndex[65536]; // Unused +uint16_t decIndex[65536]; // Unused + +IndexGenerator indexGen; TransformedVertex transformed[65536]; TransformedVertex transformedExpanded[65536]; @@ -262,7 +265,7 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. -void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV) +void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV) { /* DEBUG_LOG(G3D, "View matrix:"); @@ -289,7 +292,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexTyp Lighter lighter; VertexReader reader(decoded, decVtxFormat); - for (int index = indexLowerBound; index <= indexUpperBound; index++) + for (int index = 0; index < maxIndex; index++) { reader.Goto(index); @@ -483,48 +486,19 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexTyp const TransformedVertex *drawBuffer = transformed; int numTrans = 0; - int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); - if (forceIndexType != -1) { - indexType = forceIndexType; - } bool drawIndexed = false; - GLuint glIndexType = 0; if (prim != GE_PRIM_RECTANGLES) { // We can simply draw the unexpanded buffer. numTrans = vertexCount; - switch (indexType) { - case GE_VTYPE_IDX_8BIT: - drawIndexed = true; - glIndexType = GL_UNSIGNED_BYTE; - break; - case GE_VTYPE_IDX_16BIT: - drawIndexed = true; - glIndexType = GL_UNSIGNED_SHORT; - break; - default: - drawIndexed = false; - break; - } + drawIndexed = true; } else { numTrans = 0; drawBuffer = transformedExpanded; TransformedVertex *trans = &transformedExpanded[0]; TransformedVertex saved; for (int i = 0; i < vertexCount; i++) { - int index; - if (indexType == GE_VTYPE_IDX_8BIT) - { - index = ((u8*)inds)[i]; - } - else if (indexType == GE_VTYPE_IDX_16BIT) - { - index = ((u16*)inds)[i]; - } - else - { - index = i; - } + int index = ((u16*)inds)[i]; TransformedVertex &transVtx = transformed[index]; if ((i & 1) == 0) @@ -591,7 +565,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexTyp if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 5 * 4); if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 9 * 4); if (drawIndexed) { - glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); + glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, (GLvoid *)inds); } else { glDrawArrays(glprim[prim], 0, numTrans); } @@ -603,6 +577,10 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexTyp void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { + // For the future + if (!indexGen.PrimCompatible(prim)) + Flush(prim); + int indexLowerBound, indexUpperBound; // First, decode the verts and apply morphing VertexDecoder dec; @@ -611,6 +589,51 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); + indexGen.Start(decIndex, 0, prim); + + int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); + if (forceIndexType != -1) indexType = forceIndexType; + switch (indexType) { + case GE_VTYPE_IDX_NONE: + switch (prim) { + case GE_PRIM_POINTS: indexGen.AddPoints(vertexCount); break; + case GE_PRIM_LINES: indexGen.AddLineList(vertexCount); break; + case GE_PRIM_LINE_STRIP: indexGen.AddLineStrip(vertexCount); break; + case GE_PRIM_TRIANGLES: indexGen.AddList(vertexCount); break; + case GE_PRIM_TRIANGLE_STRIP: indexGen.AddStrip(vertexCount); break; + case GE_PRIM_TRIANGLE_FAN: indexGen.AddFan(vertexCount); break; + case GE_PRIM_RECTANGLES: indexGen.AddLineList(vertexCount); break; // Same + } + break; + + case GE_VTYPE_IDX_8BIT: + switch (prim) { + case GE_PRIM_POINTS: indexGen.TranslatePoints(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_LINES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; + case GE_PRIM_LINE_STRIP: indexGen.TranslateLineStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u8 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u8 *)inds, -indexLowerBound); break; + case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same + } + break; + + case GE_VTYPE_IDX_16BIT: + switch (prim) { + case GE_PRIM_POINTS: indexGen.TranslatePoints(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_LINES: indexGen.TranslateLineList(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_LINE_STRIP: indexGen.TranslateLineStrip(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same + } + break; + } + + indexType = GE_VTYPE_IDX_16BIT; + // From here on out, the index type is ALWAYS 16-bit. Deal with it. + // And here we should return, having collected the morphed but untransformed vertices. // Note that DecodeVerts should convert strips into indexed lists etc, adding to our // current vertex buffer and index buffer. @@ -622,15 +645,12 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte PrintDecodedVertex(decoded[i], gstate.vertType); } #endif - bool useTexCoord = false; - // Check if anything needs updating if (gstate_c.textureChanged) { if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) { PSPSetTexture(); - useTexCoord = true; } gstate_c.textureChanged = false; } @@ -647,35 +667,11 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (CanUseHardwareTransform(prim)) { SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), decoded); - bool drawIndexed; - GLuint glIndexType; - int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); - if (forceIndexType != -1) { - indexType = forceIndexType; - } - int numTrans = vertexCount; - switch (indexType) { - case GE_VTYPE_IDX_8BIT: - drawIndexed = true; - glIndexType = GL_UNSIGNED_BYTE; - break; - case GE_VTYPE_IDX_16BIT: - drawIndexed = true; - glIndexType = GL_UNSIGNED_SHORT; - break; - default: - drawIndexed = false; - break; - } - // NOTICE_LOG(G3D,"DrawPrimitive: %i", numTrans); - if (drawIndexed) { - glDrawElements(glprim[prim], numTrans, glIndexType, (GLvoid *)inds); - } else { - glDrawArrays(glprim[prim], 0, numTrans); - } + glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { - SoftwareTransformAndDraw(prim, program, forceIndexType, vertexCount, inds, dec.GetDecVtxFmt(), indexLowerBound, indexUpperBound, customUV); + SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, indexType, dec.GetDecVtxFmt(), + indexGen.MaxIndex(), customUV); } } diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 5314e152f6..4c89dfcda3 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -65,4 +65,4 @@ struct Color4 } }; -void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); +// void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV); diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 8f7b7fb0b3..34bef88276 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -675,7 +675,7 @@ void VertexDecoder::DecodeVerts(u8 *decodedptr, const void *verts, const void *i *indexUpperBound = upperBound; // Decode the vertices within the found bounds, once each - decoded_ = decodedptr + lowerBound * decFmt.stride; + decoded_ = decodedptr; // + lowerBound * decFmt.stride; ptr_ = (const u8*)verts + lowerBound * size; for (int index = lowerBound; index <= upperBound; index++) { diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 6e6bc887ea..f664d303a3 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -86,6 +86,7 @@ public: void SetVertexType(u32 vtype); const DecVtxFormat &GetDecVtxFmt() { return decFmt; } + void DecodeVerts(u8 *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const; bool hasColor() const { return col != 0; } int VertexSize() const { return size; } From 3b114eb24ab0858d0f620ebc25e1244144917bff Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 19:16:17 +0100 Subject: [PATCH 069/276] More work on indexed draws. Not combining yet. --- Core/HLE/sceDisplay.cpp | 2 + GPU/GLES/DisplayListInterpreter.cpp | 2 + GPU/GLES/DisplayListInterpreter.h | 5 +- GPU/GLES/IndexGenerator.cpp | 72 +++++++++++++++++++++++++---- GPU/GLES/IndexGenerator.h | 14 +++++- GPU/GLES/TransformPipeline.cpp | 52 ++++++++++++--------- GPU/GPUState.h | 1 + 7 files changed, 115 insertions(+), 33 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index a417ea9cdc..be4a7cf43a 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -182,6 +182,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) sprintf(stats, "Frames: %i\n" "Draw calls: %i\n" + "Draw flushes: %i\n" "Vertices Transformed: %i\n" "Textures active: %i\n" "Vertex shaders loaded: %i\n" @@ -189,6 +190,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) "Combined shaders loaded: %i\n", gpuStats.numFrames, gpuStats.numDrawCalls, + gpuStats.numFlushes, gpuStats.numVertsTransformed, gpuStats.numTextures, gpuStats.numVertexShaders, diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d516cfe9e4..54ec9715c0 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -54,6 +54,7 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) renderHeightFactor_ = (float)renderHeight / 272.0f; shaderManager_ = &shaderManager; TextureCache_Init(); + InitTransform(); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { ERROR_LOG(G3D, "gstate has drifted out of sync!"); @@ -113,6 +114,7 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) void GLES_GPU::CopyDisplayToOutput() { + Flush(); if (!g_Config.bBufferedRendering) return; diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 690088e98e..439157c9b9 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -22,11 +22,11 @@ #include "../GPUInterface.h" #include "Framebuffer.h" +#include "VertexDecoder.h" #include "gfx_es2/fbo.h" class ShaderManager; class LinkedShader; -struct DecVtxFormat; class GLES_GPU : public GPUInterface { @@ -52,10 +52,11 @@ public: private: // TransformPipeline.cpp + void InitTransform(); void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); //void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); void ApplyDrawState(); - void Flush(int prim); + void Flush(); void UpdateViewportAndProjection(); void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index b08ab3cd5b..d28d92d663 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -25,13 +25,14 @@ const u8 indexedPrimitiveType[7] = { GE_PRIM_TRIANGLES, GE_PRIM_TRIANGLES, GE_PRIM_TRIANGLES, - GE_PRIM_TRIANGLES, + GE_PRIM_RECTANGLES, }; void IndexGenerator::Reset() { prim_ = -1; - inds_ = 0; count_ = 0; + index_ = 0; + this->inds_ = indsBase_; } bool IndexGenerator::PrimCompatible(int prim) { @@ -40,12 +41,10 @@ bool IndexGenerator::PrimCompatible(int prim) { return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_]; } -void IndexGenerator::Start(u16 *inds, int baseIndex, int prim) +void IndexGenerator::Setup(u16 *inds) { - count_ = 0; - this->inds_ = inds; - index_ = baseIndex; - prim_ = indexedPrimitiveType[prim]; + this->indsBase_ = inds; + Reset(); } void IndexGenerator::AddPoints(int numVerts) @@ -58,6 +57,7 @@ void IndexGenerator::AddPoints(int numVerts) // ignore overflow verts index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::AddList(int numVerts) @@ -74,6 +74,7 @@ void IndexGenerator::AddList(int numVerts) // ignore overflow verts index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::AddStrip(int numVerts) @@ -89,6 +90,7 @@ void IndexGenerator::AddStrip(int numVerts) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::AddFan(int numVerts) @@ -102,6 +104,7 @@ void IndexGenerator::AddFan(int numVerts) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) @@ -112,6 +115,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) @@ -122,6 +126,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numVerts; + prim_ = GE_PRIM_POINTS; } void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) @@ -135,6 +140,7 @@ void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) @@ -150,6 +156,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) @@ -164,6 +171,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) @@ -177,6 +185,7 @@ void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) @@ -192,6 +201,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) @@ -206,6 +216,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) } index_ += numVerts; count_ += numTris * 3; + prim_ = GE_PRIM_TRIANGLES; } //Lines @@ -219,6 +230,7 @@ void IndexGenerator::AddLineList(int numVerts) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::AddLineStrip(int numVerts) @@ -231,6 +243,20 @@ void IndexGenerator::AddLineStrip(int numVerts) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; +} + +void IndexGenerator::AddRectangles(int numVerts) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; } void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) @@ -243,6 +269,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) @@ -255,6 +282,7 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) @@ -267,6 +295,7 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset } index_ += numVerts; count_ += numLines * 2; + prim_ = GE_PRIM_LINES; } void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) @@ -279,4 +308,31 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse } index_ += numVerts; count_ += numLines * 2; -} \ No newline at end of file + prim_ = GE_PRIM_LINES; +} + +void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offset) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; +} + +void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offset) +{ + int numRects = numVerts / 2; + for (int i = 0; i < numRects; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; + count_ += numRects * 2; + prim_ = GE_PRIM_RECTANGLES; +} diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index bb2a9bde00..af6da67ae4 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -24,9 +24,10 @@ class IndexGenerator { public: + void Setup(u16 *indexptr); void Reset(); - void Start(u16 *indexptr, int baseIndex, int prim); bool PrimCompatible(int prim); + int Prim() const { return prim_; } // Points (why index these? code simplicity) void AddPoints(int numVerts); @@ -37,15 +38,21 @@ public: // Lines void AddLineList(int numVerts); void AddLineStrip(int numVerts); + // Rectangles + void AddRectangles(int numVerts); void TranslatePoints(int numVerts, const u8 *inds, int offset); void TranslatePoints(int numVerts, const u16 *inds, int offset); // Translates already indexed lists void TranslateLineList(int numVerts, const u8 *inds, int offset); - void TranslateLineStrip(int numVerts, const u8 *inds, int offset); void TranslateLineList(int numVerts, const u16 *inds, int offset); + void TranslateLineStrip(int numVerts, const u8 *inds, int offset); void TranslateLineStrip(int numVerts, const u16 *inds, int offset); + void TranslateRectangles(int numVerts, const u8 *inds, int offset); + void TranslateRectangles(int numVerts, const u16 *inds, int offset); + + void TranslateList(int numVerts, const u8 *inds, int offset); void TranslateStrip(int numVerts, const u8 *inds, int offset); void TranslateFan(int numVerts, const u8 *inds, int offset); @@ -56,7 +63,10 @@ public: int MaxIndex() { return index_; } int VertexCount() { return count_; } + bool Empty() { return index_ == 0; } + private: + u16 *indsBase_; u16 *inds_; int index_; int count_; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 913f2c23ca..88d08908cb 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -43,7 +43,10 @@ const GLuint glprim[8] = { }; u8 decoded[65536 * 32]; +VertexDecoder dec; uint16_t decIndex[65536]; // Unused +int numVerts; +int numInds; IndexGenerator indexGen; @@ -265,7 +268,7 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. -void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV) +void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { /* DEBUG_LOG(G3D, "View matrix:"); @@ -418,10 +421,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, } } - if (customUV) { - uv[0] = customUV[index * 2 + 0]*gstate_c.uScale + gstate_c.uOff; - uv[1] = customUV[index * 2 + 1]*gstate_c.vScale + gstate_c.vOff; - } else if (reader.hasUV()) { + if (reader.hasUV()) { float ruv[2]; reader.ReadUV(ruv); // Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights. @@ -575,22 +575,27 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } +void GLES_GPU::InitTransform() { + indexGen.Setup(decIndex); +} + void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { // For the future if (!indexGen.PrimCompatible(prim)) - Flush(prim); + Flush(); + + gpuStats.numDrawCalls++; + gpuStats.numVertsTransformed += vertexCount; int indexLowerBound, indexUpperBound; // First, decode the verts and apply morphing - VertexDecoder dec; dec.SetVertexType(gstate.vertType); dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); - indexGen.Start(decIndex, 0, prim); - int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); if (forceIndexType != -1) indexType = forceIndexType; switch (indexType) { @@ -602,7 +607,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.AddList(vertexCount); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.AddStrip(vertexCount); break; case GE_PRIM_TRIANGLE_FAN: indexGen.AddFan(vertexCount); break; - case GE_PRIM_RECTANGLES: indexGen.AddLineList(vertexCount); break; // Same + case GE_PRIM_RECTANGLES: indexGen.AddRectangles(vertexCount); break; // Same } break; @@ -614,7 +619,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u8 *)inds, -indexLowerBound); break; - case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same + case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u8 *)inds, -indexLowerBound); break; // Same } break; @@ -626,12 +631,18 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u16 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_STRIP: indexGen.TranslateStrip(vertexCount, (const u16 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLE_FAN: indexGen.TranslateFan(vertexCount, (const u16 *)inds, -indexLowerBound); break; - case GE_PRIM_RECTANGLES: indexGen.TranslateLineList(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same + case GE_PRIM_RECTANGLES: indexGen.TranslateRectangles(vertexCount, (const u16 *)inds, -indexLowerBound); break; // Same } break; } - indexType = GE_VTYPE_IDX_16BIT; + Flush(); +} + +void GLES_GPU::Flush() +{ + if (indexGen.Empty()) + return; // From here on out, the index type is ALWAYS 16-bit. Deal with it. // And here we should return, having collected the morphed but untransformed vertices. @@ -654,12 +665,13 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } gstate_c.textureChanged = false; } - gpuStats.numDrawCalls++; - gpuStats.numVertsTransformed += vertexCount; + gpuStats.numFlushes++; // TODO: This should not be done on every drawcall, we should collect vertex data // until critical state changes. That's when we draw (flush). + int prim = indexGen.Prim(); + ApplyDrawState(); UpdateViewportAndProjection(); @@ -670,11 +682,9 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { - SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, indexType, dec.GetDecVtxFmt(), - indexGen.MaxIndex(), customUV); + SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), + indexGen.MaxIndex()); } -} -void GLES_GPU::Flush(int prim) { - // TODO -} + indexGen.Reset(); +} \ No newline at end of file diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 66cb21d90b..e031f6bc71 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -263,6 +263,7 @@ struct GPUStatistics // Per frame statistics int numDrawCalls; + int numFlushes; int numVertsTransformed; int numTextureSwitches; int numShaderSwitches; From 33debd755babfcaf44ae24e3d568f78ac2f17653 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 11:58:32 -0800 Subject: [PATCH 070/276] Correct sceKernelSetSysClockAlarm timing. Also make refer status work for the tests to be usable. --- Core/CoreTiming.h | 4 +++ Core/HLE/sceKernelAlarm.cpp | 58 +++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index f771d7e484..f8883d9b35 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -58,6 +58,10 @@ inline int usToCycles(int us) { return (int)(CPU_HZ / 1000000 * us); } +inline u64 usToCycles(u64 us) { + return (u64)(CPU_HZ / 1000000ULL * us); +} + inline u64 cyclesToUs(u64 cycles) { return cycles / (CPU_HZ / 1000000); } diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index ee6657e670..4110ef2499 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -21,6 +21,8 @@ #include "HLE.h" #include "../../Core/CoreTiming.h" +const int NATIVEALARM_SIZE = 20; + struct NativeAlarm { SceSize size; @@ -38,7 +40,7 @@ struct Alarm : public KernelObject NativeAlarm alm; }; -void __KernelScheduleAlarm(Alarm *alarm, int ticks); +void __KernelScheduleAlarm(Alarm *alarm, u64 ticks); class AlarmIntrHandler : public SubIntrHandler { @@ -60,9 +62,8 @@ public: virtual void handleResult(int result) { // A non-zero result means to reschedule. - // TODO: Do sysclock alarms return a different value unit? if (result > 0) - __KernelScheduleAlarm(alarm, usToCycles(result)); + __KernelScheduleAlarm(alarm, (u64) usToCycles(result)); else if (result < 0) WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); } @@ -92,9 +93,9 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); } -void __KernelScheduleAlarm(Alarm *alarm, int ticks) +void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) { - alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.schedule = (CoreTiming::GetTicks() + ticks) / (u64) CoreTiming::GetClockFrequencyMHz(); CoreTiming::ScheduleEvent((int) ticks, alarmTimer, alarm->GetUID()); } @@ -106,8 +107,7 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) Alarm *alarm = new Alarm; SceUID uid = kernelObjects.Create(alarm); - alarm->alm.size = sizeof(NativeAlarm); - alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.size = NATIVEALARM_SIZE; alarm->alm.handlerPtr = handlerPtr; alarm->alm.commonPtr = commonPtr; @@ -115,29 +115,28 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) if (error != 0) return error; - __KernelScheduleAlarm(alarm, (int) ticks); + __KernelScheduleAlarm(alarm, ticks); return uid; } SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { DEBUG_LOG(HLE, "sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); - return __KernelSetAlarm(usToCycles((int) micro), handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles((u64) micro), handlerPtr, commonPtr); } -SceUID sceKernelSetSysClockAlarm(u32 ticksPtr, u32 handlerPtr, u32 commonPtr) +SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr) { - u64 ticks; + u64 micro; - if (Memory::IsValidAddress(ticksPtr)) - ticks = Memory::Read_U64(ticksPtr); + if (Memory::IsValidAddress(microPtr)) + micro = Memory::Read_U64(microPtr); // TODO: What to do when invalid? else return -1; - ERROR_LOG(HLE, "UNTESTED sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); - // TODO: Is this precise or is this relative? - return __KernelSetAlarm(ticks, handlerPtr, commonPtr); + DEBUG_LOG(HLE, "sceKernelSetSysClockAlarm(%lld, %08x, %08x)", micro, handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles(micro), handlerPtr, commonPtr); } int sceKernelCancelAlarm(SceUID uid) @@ -152,6 +151,29 @@ int sceKernelCancelAlarm(SceUID uid) int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) { - ERROR_LOG(HLE, "UNIMPL sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); - return -1; + u32 error; + Alarm *alarm = kernelObjects.Get(uid, error); + if (!alarm) + { + ERROR_LOG(HLE, "sceKernelReferAlarmStatus(%08x, %08x): invalid alarm", uid, infoPtr); + return error; + } + + if (!Memory::IsValidAddress(infoPtr)) + return -1; + + u32 size = Memory::Read_U32(infoPtr); + + // Alarms actually respect size and write (kinda) what it can hold. + // Intentionally 1 not 4. + if (size >= 1) + Memory::Write_U32(alarm->alm.size, infoPtr); + if (size >= 12) + Memory::Write_U64(alarm->alm.schedule, infoPtr + 4); + if (size >= 16) + Memory::Write_U32(alarm->alm.handlerPtr, infoPtr + 12); + if (size >= 20) + Memory::Write_U32(alarm->alm.commonPtr, infoPtr + 16); + + return 0; } \ No newline at end of file From 522b16bb89ce4fbed21a07cfea04d539fe1a99fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 12:04:02 -0800 Subject: [PATCH 071/276] Fix error handling for setting alarms. --- Core/HLE/sceKernelAlarm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 4110ef2499..a51feaf8df 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -104,6 +104,9 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) if (!alarmInitComplete) __KernelAlarmInit(); + if (!Memory::IsValidAddress(handlerPtr)) + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + Alarm *alarm = new Alarm; SceUID uid = kernelObjects.Create(alarm); @@ -131,7 +134,6 @@ SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr) if (Memory::IsValidAddress(microPtr)) micro = Memory::Read_U64(microPtr); - // TODO: What to do when invalid? else return -1; From dbec955a99fea3286bfb1f455e201324e7879f7d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 12:28:28 -0800 Subject: [PATCH 072/276] Properly delete alarms after they run. Also fix refer, based on tests. --- Core/HLE/sceKernelAlarm.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index a51feaf8df..cfd5b48155 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -64,8 +64,15 @@ public: // A non-zero result means to reschedule. if (result > 0) __KernelScheduleAlarm(alarm, (u64) usToCycles(result)); - else if (result < 0) - WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); + else + { + if (result < 0) + WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); + + // Delete the alarm if it's not rescheduled. + __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, alarm->GetUID()); + kernelObjects.Destroy(alarm->GetUID()); + } } Alarm *alarm; @@ -167,14 +174,13 @@ int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) u32 size = Memory::Read_U32(infoPtr); // Alarms actually respect size and write (kinda) what it can hold. - // Intentionally 1 not 4. - if (size >= 1) + if (size > 0) Memory::Write_U32(alarm->alm.size, infoPtr); - if (size >= 12) + if (size > 4) Memory::Write_U64(alarm->alm.schedule, infoPtr + 4); - if (size >= 16) + if (size > 12) Memory::Write_U32(alarm->alm.handlerPtr, infoPtr + 12); - if (size >= 20) + if (size > 16) Memory::Write_U32(alarm->alm.commonPtr, infoPtr + 16); return 0; From 6adb29030f54c21797509ee8d286ea6534240d77 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 12:38:12 -0800 Subject: [PATCH 073/276] Update tests. --- Core/HLE/sceKernelAlarm.cpp | 2 ++ pspautotests | 2 +- test.py | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index cfd5b48155..984c558e04 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -168,6 +168,8 @@ int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) return error; } + DEBUG_LOG(HLE, "sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); + if (!Memory::IsValidAddress(infoPtr)) return -1; diff --git a/pspautotests b/pspautotests index 6bd9d261e6..30f1f0698e 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 6bd9d261e6014d371b917e50d2e18d5fc986a8c3 +Subproject commit 30f1f0698e2ed2f45f4dd1bd199c81cdc379561e diff --git a/test.py b/test.py index 14f3746193..f352ccf50f 100755 --- a/test.py +++ b/test.py @@ -59,6 +59,9 @@ tests_good = [ "string/string", "gpu/callbacks/ge_callbacks", "threads/alarm/alarm", + "threads/alarm/cancel/cancel", + "threads/alarm/refer/refer", + "threads/alarm/set/set", "threads/events/events", "threads/events/cancel/cancel", "threads/events/clear/clear", From d663e28bdea7ac4dfdb09269f133ba4c9b635ff0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 21:49:09 +0100 Subject: [PATCH 074/276] More work and optimization. Still not quite there. --- Core/Dialog/PSPSaveDialog.cpp | 1 + Core/HLE/sceDisplay.cpp | 7 +- Core/HLE/sceGe.cpp | 4 +- GPU/GLES/DisplayListInterpreter.cpp | 188 +++++++++++++++++++++++++++- GPU/GLES/IndexGenerator.h | 4 +- GPU/GLES/ShaderManager.cpp | 15 ++- GPU/GLES/ShaderManager.h | 1 + GPU/GLES/TextureCache.cpp | 38 +++--- GPU/GLES/TransformPipeline.cpp | 18 ++- GPU/GLES/VertexShaderGenerator.cpp | 23 +--- GPU/GPUState.h | 5 + native | 2 +- 12 files changed, 250 insertions(+), 56 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 3185a43a0b..5a1ff4ea53 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -33,6 +33,7 @@ PSPSaveDialog::~PSPSaveDialog() { u32 PSPSaveDialog::Init(int paramAddr) { + return 0; // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index be4a7cf43a..dba162c325 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -185,6 +185,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) "Draw flushes: %i\n" "Vertices Transformed: %i\n" "Textures active: %i\n" + "Textures decoded: %i\n" "Vertex shaders loaded: %i\n" "Fragment shaders loaded: %i\n" "Combined shaders loaded: %i\n", @@ -193,15 +194,15 @@ void hleEnterVblank(u64 userdata, int cyclesLate) gpuStats.numFlushes, gpuStats.numVertsTransformed, gpuStats.numTextures, + gpuStats.numTexturesDecoded, gpuStats.numVertexShaders, gpuStats.numFragmentShaders, gpuStats.numShaders ); - float zoom = 0.7f / g_Config.iWindowZoom; + float zoom = 0.7f; /// g_Config.iWindowZoom; PPGeBegin(); - PPGeDrawText(stats, 2, 2, 0, zoom, 0x90000000); - PPGeDrawText(stats, 0, 0, 0, zoom); + PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFc0c0c0); PPGeEnd(); gpuStats.resetFrame(); diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index dd41e6e1db..3752622f7f 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -225,12 +225,12 @@ const HLEFunction sceGe_user[] = {0xE0D68148,&WrapV_UU, "sceGeListUpdateStallAddr"}, {0x03444EB4,&WrapI_UU, "sceGeListSync"}, {0xB287BD61,&WrapU_U, "sceGeDrawSync"}, - {0xB448EC0D,&WrapV_U, "sceGeBreak"}, + {0xB448EC0D,&WrapV_U, "sceGeBreak"}, {0x4C06E472,sceGeContinue, "sceGeContinue"}, {0xA4FC06A4,&WrapU_U, "sceGeSetCallback"}, {0x05DB22CE,&WrapV_U, "sceGeUnsetCallback"}, {0x1F6752AD,&WrapU_V, "sceGeEdramGetSize"}, - {0xB77905EA,&WrapU_I,"sceGeEdramSetAddrTranslation"}, + {0xB77905EA,&WrapU_I,"sceGeEdramSetAddrTranslation"}, {0xDC93CFEF,0,"sceGeGetCmd"}, {0x57C8945B,&sceGeGetMtx,"sceGeGetMtx"}, {0x438A385A,&WrapU_U,"sceGeSaveContext"}, diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 54ec9715c0..4071efe200 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -43,6 +43,121 @@ ShaderManager shaderManager; extern u32 curTextureWidth; extern u32 curTextureHeight; +bool flushBeforeCommand[256] = {0}; +const bool flushBeforeCommandList[] = { + GE_CMD_BEZIER, + GE_CMD_SPLINE, + GE_CMD_SIGNAL, + GE_CMD_FINISH, + GE_CMD_END, + GE_CMD_BJUMP, + GE_CMD_VERTEXTYPE, + GE_CMD_OFFSETADDR, + GE_CMD_REGION1, + GE_CMD_REGION2, + GE_CMD_CULLFACEENABLE, + GE_CMD_TEXTUREMAPENABLE, + GE_CMD_LIGHTINGENABLE, + GE_CMD_FOGENABLE, + GE_CMD_TEXSCALEU, + GE_CMD_TEXSCALEV, + GE_CMD_TEXOFFSETU, + GE_CMD_TEXOFFSETV, + GE_CMD_SCISSOR1, + GE_CMD_SCISSOR2, + GE_CMD_MINZ, + GE_CMD_MAXZ, + GE_CMD_FRAMEBUFPTR, + GE_CMD_FRAMEBUFWIDTH, + GE_CMD_FRAMEBUFPIXFORMAT, + GE_CMD_TEXADDR0, + GE_CMD_CLUTADDR, + GE_CMD_LOADCLUT, + GE_CMD_TEXMAPMODE, + GE_CMD_TEXSHADELS, + GE_CMD_CLUTFORMAT, + GE_CMD_TRANSFERSTART, + GE_CMD_TEXSIZE0, + GE_CMD_TEXSIZE1, + GE_CMD_TEXSIZE2, + GE_CMD_TEXSIZE3, + GE_CMD_TEXSIZE4, + GE_CMD_TEXSIZE5, + GE_CMD_TEXSIZE6, + GE_CMD_TEXSIZE7, + GE_CMD_ZBUFPTR, + GE_CMD_ZBUFWIDTH, + GE_CMD_AMBIENTCOLOR, + GE_CMD_AMBIENTALPHA, + GE_CMD_MATERIALAMBIENT, + GE_CMD_MATERIALDIFFUSE, + GE_CMD_MATERIALEMISSIVE, + GE_CMD_MATERIALSPECULAR, + GE_CMD_MATERIALALPHA, + GE_CMD_MATERIALSPECULARCOEF, + GE_CMD_LIGHTTYPE0, + GE_CMD_LIGHTTYPE1, + GE_CMD_LIGHTTYPE2, + GE_CMD_LIGHTTYPE3, + GE_CMD_LX0, + GE_CMD_LX1, + GE_CMD_LX2, + GE_CMD_LX3, + GE_CMD_LDX0, + GE_CMD_LDX1, + GE_CMD_LDX2, + GE_CMD_LDX3, + GE_CMD_LKA0, + GE_CMD_LAC0, + GE_CMD_LDC0, + GE_CMD_LSC0, + GE_CMD_VIEWPORTX1, + GE_CMD_VIEWPORTY1, + GE_CMD_VIEWPORTX2, + GE_CMD_VIEWPORTY2, + GE_CMD_VIEWPORTZ1, + GE_CMD_VIEWPORTZ2, + GE_CMD_LIGHTENABLE0, + GE_CMD_LIGHTENABLE1, + GE_CMD_LIGHTENABLE2, + GE_CMD_LIGHTENABLE3, + GE_CMD_CULL, + GE_CMD_LMODE, + GE_CMD_PATCHDIVISION, + GE_CMD_MATERIALUPDATE, + GE_CMD_CLEARMODE, + GE_CMD_ALPHABLENDENABLE, + GE_CMD_BLENDMODE, + GE_CMD_BLENDFIXEDA, + GE_CMD_BLENDFIXEDB, + GE_CMD_ALPHATESTENABLE, + GE_CMD_ALPHATEST, + GE_CMD_TEXFUNC, + GE_CMD_TEXFILTER, + GE_CMD_TEXENVCOLOR, + GE_CMD_TEXMODE, + GE_CMD_TEXFORMAT, + GE_CMD_TEXFLUSH, + GE_CMD_TEXWRAP, + GE_CMD_ZTESTENABLE, + GE_CMD_STENCILTESTENABLE, + GE_CMD_ZTEST, + GE_CMD_MORPHWEIGHT0, + GE_CMD_MORPHWEIGHT1, + GE_CMD_MORPHWEIGHT2, + GE_CMD_MORPHWEIGHT3, + GE_CMD_MORPHWEIGHT4, + GE_CMD_MORPHWEIGHT5, + GE_CMD_MORPHWEIGHT6, + GE_CMD_MORPHWEIGHT7, + GE_CMD_WORLDMATRIXNUMBER, + GE_CMD_VIEWMATRIXNUMBER, + GE_CMD_PROJMATRIXNUMBER, + GE_CMD_PROJMATRIXDATA, + GE_CMD_TGENMATRIXNUMBER, + GE_CMD_BONEMATRIXNUMBER, +}; + GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) : interruptsEnabled_(true), renderWidth_(renderWidth), @@ -59,6 +174,10 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { ERROR_LOG(G3D, "gstate has drifted out of sync!"); } + + for (int i = 0; i < ARRAY_SIZE(flushBeforeCommandList); i++) { + flushBeforeCommand[flushBeforeCommandList[i]] = true; + } } GLES_GPU::~GLES_GPU() @@ -104,6 +223,7 @@ void GLES_GPU::BeginFrame() void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) { if (framebuf & 0x04000000) { + DEBUG_LOG(G3D, "Switch display framebuffer %08x", framebuf); displayFramebufPtr_ = framebuf; displayStride_ = stride; displayFormat_ = format; @@ -168,6 +288,7 @@ GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() void GLES_GPU::SetRenderFrameBuffer() { + Flush(); if (!g_Config.bBufferedRendering) return; // Get parameters @@ -300,7 +421,7 @@ void GLES_GPU::UpdateStall(int listid, u32 newstall) void GLES_GPU::DrawSync(int mode) { - + Flush(); } void GLES_GPU::Continue() @@ -432,6 +553,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: { + Flush(); int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; DrawBezier(bz_ucount, bz_vcount); @@ -441,6 +563,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_SPLINE: { + Flush(); int sp_ucount = data & 0xFF; int sp_vcount = (data >> 8) & 0xFF; int sp_utype = (data >> 16) & 0x3; @@ -489,6 +612,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_FINISH: + Flush(); DEBUG_LOG(G3D,"DL CMD FINISH"); // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) @@ -544,6 +668,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_BJUMP: + Flush(); // bounding box jump. Let's just not jump, for now. DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); break; @@ -558,6 +683,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_VERTEXTYPE: + Flush(); DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); if (diff & GE_VTYPE_THROUGH) { // Throughmode changed, let's make the proj matrix dirty. @@ -593,21 +719,25 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_CULLFACEENABLE: + Flush(); DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); break; case GE_CMD_TEXTUREMAPENABLE: + Flush(); gstate_c.textureChanged = true; DEBUG_LOG(G3D, "DL Texture map enable: %i", data); break; case GE_CMD_LIGHTINGENABLE: + Flush(); DEBUG_LOG(G3D, "DL Lighting enable: %i", data); data += 1; //We don't use OpenGL lighting break; case GE_CMD_FOGENABLE: + Flush(); DEBUG_LOG(G3D, "DL Fog Enable: %i", data); break; @@ -624,24 +754,28 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXSCALEU: + Flush(); gstate_c.uScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: + Flush(); gstate_c.vScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: + Flush(); gstate_c.uOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: + Flush(); gstate_c.vOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); @@ -649,6 +783,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_SCISSOR1: { + Flush(); int x1 = data & 0x3ff; int y1 = data >> 10; DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); @@ -656,6 +791,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_SCISSOR2: { + Flush(); int x2 = data & 0x3ff; int y2 = data >> 10; DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); @@ -674,6 +810,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FRAMEBUFPTR: { + Flush(); u32 ptr = op & 0xFFE000; DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); } @@ -681,6 +818,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FRAMEBUFWIDTH: { + Flush(); u32 w = data & 0xFFFFFF; DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); } @@ -690,6 +828,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXADDR0: + Flush(); gstate_c.textureChanged = true; case GE_CMD_TEXADDR1: case GE_CMD_TEXADDR2: @@ -738,10 +877,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXMAPMODE: + Flush(); DEBUG_LOG(G3D,"Tex map mode: %06x", data); break; case GE_CMD_TEXSHADELS: + Flush(); DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); break; @@ -805,6 +946,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK { + Flush(); // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. DoBlockTransfer(); @@ -812,6 +954,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXSIZE0: + Flush(); gstate_c.textureChanged = true; gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); @@ -828,6 +971,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ZBUFPTR: { + Flush(); u32 ptr = op & 0xFFE000; DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); } @@ -841,44 +985,52 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_AMBIENTCOLOR: + Flush(); DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); break; case GE_CMD_AMBIENTALPHA: + Flush(); DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); break; case GE_CMD_MATERIALAMBIENT: + Flush(); DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: + Flush(); DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: + Flush(); DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: + Flush(); DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: + Flush(); DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: + Flush(); DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); if (diff) shaderManager.DirtyUniform(DIRTY_MATSPECULAR); @@ -896,6 +1048,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: { + Flush(); int n = cmd - GE_CMD_LX0; int l = n / 3; int c = n % 3; @@ -912,6 +1065,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: { + Flush(); int n = cmd - GE_CMD_LDX0; int l = n / 3; int c = n % 3; @@ -928,6 +1082,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: { + Flush(); int n = cmd - GE_CMD_LKA0; int l = n / 3; int c = n % 3; @@ -944,6 +1099,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: { + Flush(); float r = (float)(data & 0xff)/255.0f; float g = (float)((data>>8) & 0xff)/255.0f; float b = (float)(data>>16)/255.0f; @@ -962,13 +1118,16 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_VIEWPORTY1: case GE_CMD_VIEWPORTX2: case GE_CMD_VIEWPORTY2: + Flush(); DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); break; case GE_CMD_VIEWPORTZ1: + Flush(); gstate_c.zScale = getFloat24(data) / 65535.f; DEBUG_LOG(G3D,"DL Z scale: %f", gstate_c.zScale); break; case GE_CMD_VIEWPORTZ2: + Flush(); gstate_c.zOff = getFloat24(data) / 65535.f; DEBUG_LOG(G3D,"DL Z pos: %f", gstate_c.zOff); break; @@ -976,13 +1135,16 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LIGHTENABLE1: case GE_CMD_LIGHTENABLE2: case GE_CMD_LIGHTENABLE3: + Flush(); DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); break; case GE_CMD_CULL: + Flush(); DEBUG_LOG(G3D,"DL cull: %06x", data); break; case GE_CMD_LMODE: + Flush(); DEBUG_LOG(G3D,"DL Shade mode: %06x", data); break; @@ -993,6 +1155,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_MATERIALUPDATE: + Flush(); DEBUG_LOG(G3D,"DL Material Update: %d", data); break; @@ -1001,6 +1164,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // CLEARING ////////////////////////////////////////////////////////////////// case GE_CMD_CLEARMODE: + Flush(); // If it becomes a performance problem, check diff&1 if (data & 1) EnterClearMode(data); @@ -1014,33 +1178,40 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // ALPHA BLENDING ////////////////////////////////////////////////////////////////// case GE_CMD_ALPHABLENDENABLE: + Flush(); DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); break; case GE_CMD_BLENDMODE: + Flush(); DEBUG_LOG(G3D,"DL Blend mode: %06x", data); break; case GE_CMD_BLENDFIXEDA: + Flush(); DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); break; case GE_CMD_BLENDFIXEDB: + Flush(); DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); break; case GE_CMD_ALPHATESTENABLE: + Flush(); DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); // This is done in the shader. break; case GE_CMD_ALPHATEST: + Flush(); DEBUG_LOG(G3D,"DL Alpha test settings"); shaderManager.DirtyUniform(DIRTY_ALPHACOLORREF); break; case GE_CMD_TEXFUNC: { + Flush(); DEBUG_LOG(G3D,"DL TexFunc %i", data&7); /* int m=GL_MODULATE; @@ -1068,26 +1239,32 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXFILTER: { + Flush(); int min = data & 7; int mag = (data >> 8) & 1; DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); } break; case GE_CMD_TEXENVCOLOR: + Flush(); DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_TEXENV); break; case GE_CMD_TEXMODE: + Flush(); DEBUG_LOG(G3D,"DL TexMode %08x", data); break; case GE_CMD_TEXFORMAT: + Flush(); DEBUG_LOG(G3D,"DL TexFormat %08x", data); break; case GE_CMD_TEXFLUSH: + Flush(); DEBUG_LOG(G3D,"DL TexFlush"); break; case GE_CMD_TEXWRAP: + Flush(); DEBUG_LOG(G3D,"DL TexWrap %08x", data); break; ////////////////////////////////////////////////////////////////// @@ -1095,10 +1272,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) ////////////////////////////////////////////////////////////////// case GE_CMD_ZTESTENABLE: + Flush(); DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); break; case GE_CMD_STENCILTESTENABLE: + Flush(); DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); break; @@ -1132,6 +1311,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_WORLDMATRIXNUMBER: + Flush(); DEBUG_LOG(G3D,"DL World # %i", data & 0xF); gstate.worldmtxnum &= 0xFF00000F; break; @@ -1148,6 +1328,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_VIEWMATRIXNUMBER: + Flush(); DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF); gstate.viewmtxnum &= 0xFF00000F; break; @@ -1164,6 +1345,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_PROJMATRIXNUMBER: + Flush(); DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF); gstate.projmtxnum &= 0xFF00000F; break; @@ -1179,6 +1361,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TGENMATRIXNUMBER: + Flush(); DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF); gstate.texmtxnum &= 0xFF00000F; break; @@ -1195,6 +1378,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_BONEMATRIXNUMBER: + Flush(); DEBUG_LOG(G3D,"DL BONE #%i", data); gstate.boneMatrixNumber &= 0xFF00007F; break; @@ -1237,6 +1421,8 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; + if (flushBeforeCommand[cmd]) + Flush(); u32 diff = op ^ gstate.cmdmem[cmd]; gstate.cmdmem[cmd] = op; diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index af6da67ae4..2b491c6789 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -41,7 +41,7 @@ public: // Rectangles void AddRectangles(int numVerts); - void TranslatePoints(int numVerts, const u8 *inds, int offset); + void TranslatePoints(int numVerts, const u8 *inds, int offset); void TranslatePoints(int numVerts, const u16 *inds, int offset); // Translates already indexed lists void TranslateLineList(int numVerts, const u8 *inds, int offset); @@ -65,6 +65,8 @@ public: bool Empty() { return index_ == 0; } + void SetIndex(int ind) { index_ = ind; } + private: u16 *indsBase_; u16 *inds_; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 819b2815b7..ec5b60e290 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -176,8 +176,10 @@ static void SetMatrix4x3(int uniform, const float *m4x3) { void LinkedShader::use() { glUseProgram(program); - glUniform1i(u_tex, 0); + updateUniforms(); +} +void LinkedShader::updateUniforms() { if (!dirtyUniforms) return; @@ -300,6 +302,7 @@ void ShaderManager::DirtyShader() // Forget the last shader ID lastFSID.clear(); lastVSID.clear(); + lastShader = 0; } @@ -318,8 +321,11 @@ LinkedShader *ShaderManager::ApplyShader(int prim) ComputeVertexShaderID(&VSID, prim); ComputeFragmentShaderID(&FSID); - // Bail quickly in the no-op case. TODO: why does it cause trouble? - // if (VSID == lastVSID && FSID == lastFSID) return lastShader; // Already all set. + // Just update uniforms if this is the same shader as last time. + if (lastShader != 0 && VSID == lastVSID && FSID == lastFSID) { + lastShader->updateUniforms(); + return lastShader; // Already all set. + } lastVSID = VSID; lastFSID = FSID; @@ -355,10 +361,9 @@ LinkedShader *ShaderManager::ApplyShader(int prim) linkedShaderCache[linkedID] = ls; } else { ls = iter->second; + ls->use(); } - ls->use(); - lastShader = ls; return ls; } diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index c7cf3d1040..275b479cdf 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -32,6 +32,7 @@ public: ~LinkedShader(); void use(); + void updateUniforms(); uint32_t program; u32 dirtyUniforms; diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 9ad2685657..a09c0d1da3 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -597,17 +597,16 @@ void convertColors(u8 *finalBuf, GLuint dstFmt, int numPixels) void PSPSetTexture() { + static int lastBoundTexture = -1; + u32 texaddr = (gstate.texaddr[0] & 0xFFFFF0) | ((gstate.texbufwidth[0]<<8) & 0xFF000000); texaddr &= 0xFFFFFFF; - if (!texaddr) return; - u8 level = 0; u32 format = gstate.texformat & 0xF; u32 clutformat = gstate.clutformat & 3; u32 clutaddr = GetClutAddr(clutformat == GE_CMODE_32BIT_ABGR8888 ? 4 : 2); - DEBUG_LOG(G3D,"Texture at %08x",texaddr); u8 *texptr = Memory::GetPointer(texaddr); u32 texhash = texptr ? *(u32*)texptr : 0; @@ -636,8 +635,11 @@ void PSPSetTexture() if (match) { //got one! entry.frameCounter = gpuStats.numFrames; - glBindTexture(GL_TEXTURE_2D, entry.texture); - UpdateSamplingParams(); + if (entry.texture != lastBoundTexture) { + glBindTexture(GL_TEXTURE_2D, entry.texture); + UpdateSamplingParams(); + lastBoundTexture = entry.texture; + } DEBUG_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); return; //Done! } else { @@ -653,7 +655,7 @@ void PSPSetTexture() //we have to decode it - TexCacheEntry entry; + TexCacheEntry entry = {0}; entry.addr = texaddr; entry.hash = texhash; @@ -671,9 +673,6 @@ void PSPSetTexture() entry.clutaddr = 0; } - glGenTextures(1, &entry.texture); - glBindTexture(GL_TEXTURE_2D, entry.texture); - int bufw = gstate.texbufwidth[0] & 0x3ff; entry.dim = gstate.texsize[0] & 0xF0F; @@ -681,8 +680,6 @@ void PSPSetTexture() int w = 1 << (gstate.texsize[0] & 0xf); int h = 1 << ((gstate.texsize[0]>>8) & 0xf); - INFO_LOG(G3D, "Creating texture %i from %08x: %i x %i (stride: %i). fmt: %i", entry.texture, entry.addr, w, h, bufw, entry.format); - gstate_c.curTextureWidth=w; gstate_c.curTextureHeight=h; GLenum dstFmt = 0; @@ -932,26 +929,27 @@ void PSPSetTexture() } } + gpuStats.numTexturesDecoded++; // Can restore these and remove the above fixup on some platforms. //glPixelStorei(GL_UNPACK_ROW_LENGTH, bufw); - glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign); + //glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign); //glPixelStorei(GL_PACK_ROW_LENGTH, bufw); - glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign); + //glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign); + INFO_LOG(G3D, "Creating texture %i from %08x: %i x %i (stride: %i). fmt: %i", entry.texture, entry.addr, w, h, bufw, entry.format); + + glGenTextures(1, &entry.texture); + glBindTexture(GL_TEXTURE_2D, entry.texture); + lastBoundTexture = entry.texture; GLuint components = dstFmt == GL_UNSIGNED_SHORT_5_6_5 ? GL_RGB : GL_RGBA; glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components, dstFmt, finalBuf); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glGenerateMipmap(GL_TEXTURE_2D); UpdateSamplingParams(); //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); + //glPixelStorei(GL_PACK_ALIGNMENT, 1); cache[cachekey] = entry; } diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 88d08908cb..03599d5ab3 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -44,9 +44,8 @@ const GLuint glprim[8] = { u8 decoded[65536 * 32]; VertexDecoder dec; -uint16_t decIndex[65536]; // Unused +uint16_t decIndex[65536]; int numVerts; -int numInds; IndexGenerator indexGen; @@ -577,6 +576,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void GLES_GPU::InitTransform() { indexGen.Setup(decIndex); + numVerts = 0; } void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) @@ -585,13 +585,18 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte if (!indexGen.PrimCompatible(prim)) Flush(); + if (!indexGen.Empty()) { + gpuStats.numJoins++; + } gpuStats.numDrawCalls++; gpuStats.numVertsTransformed += vertexCount; + indexGen.SetIndex(numVerts); int indexLowerBound, indexUpperBound; // First, decode the verts and apply morphing dec.SetVertexType(gstate.vertType); - dec.DecodeVerts(decoded, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + dec.DecodeVerts(decoded + numVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); + numVerts += indexUpperBound - indexLowerBound + 1; if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); @@ -613,7 +618,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte case GE_VTYPE_IDX_8BIT: switch (prim) { - case GE_PRIM_POINTS: indexGen.TranslatePoints(vertexCount, (const u16 *)inds, -indexLowerBound); break; + case GE_PRIM_POINTS: indexGen.TranslatePoints(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_LINES: indexGen.TranslateLineList(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_LINE_STRIP: indexGen.TranslateLineStrip(vertexCount, (const u8 *)inds, -indexLowerBound); break; case GE_PRIM_TRIANGLES: indexGen.TranslateList(vertexCount, (const u8 *)inds, -indexLowerBound); break; @@ -677,6 +682,8 @@ void GLES_GPU::Flush() LinkedShader *program = shaderManager_->ApplyShader(prim); + DEBUG_LOG(G3D, "Flush prim %i! %i verts in one go", prim, numVerts); + if (CanUseHardwareTransform(prim)) { SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), decoded); glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); @@ -687,4 +694,5 @@ void GLES_GPU::Flush() } indexGen.Reset(); -} \ No newline at end of file + numVerts = 0; +} diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 953b5c684d..0c41881839 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -88,19 +88,11 @@ void ComputeVertexShaderID(VertexShaderID *id, int prim) id->d[1] |= ((gstate.ltype[i] >> 8) & 3) << (i * 4 + 2); } id->d[1] |= (gstate.materialupdate & 7) << 16; + id->d[1] |= (gstate.lightingEnable & 1) << 19; + for (int i = 0; i < 4; i++) { + id->d[1] |= (gstate.lightEnable[i] & 1) << (20 + i); + } } - - // Bits that we will need: - // lightenable * 4 - // lighttype * 4 - // lightcomp * 4 - // uv gen: - // mapping type - // texshade light choices (ONLY IF uv mapping type is shade) -} - -void WriteLight(char *p, int l) { - // TODO } const char *boneWeightAttrDecl[8] = { @@ -131,7 +123,6 @@ enum DoLightComputation { LIGHT_FULL, }; - char *GenerateVertexShader(int prim) { char *p = buffer; @@ -316,7 +307,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " float dot%i = dot(normalize(toLight%i), worldnormal);\n", i, i); if (poweredDiffuse) { - WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n"); + WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i); } if (doLight[i] == LIGHT_DOTONLY) @@ -400,10 +391,6 @@ char *GenerateVertexShader(int prim) WRITE(p, " v_depth = gl_Position.z;\n"); WRITE(p, "}\n"); - // DEBUG_LOG(HLE, "\n%s", buffer); -#if defined(_WIN32) && defined(_DEBUG) - OutputDebugString(buffer); -#endif return buffer; } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index e031f6bc71..4e271b4278 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -255,18 +255,23 @@ struct GPUStatistics memset(this, 0, sizeof(*this)); } void resetFrame() { + numJoins = 0; numDrawCalls = 0; numVertsTransformed = 0; numTextureSwitches = 0; numShaderSwitches = 0; + numFlushes = 0; + numTexturesDecoded = 0; } // Per frame statistics + int numJoins; int numDrawCalls; int numFlushes; int numVertsTransformed; int numTextureSwitches; int numShaderSwitches; + int numTexturesDecoded; // Total statistics, updated by the GPU core in UpdateStats int numFrames; diff --git a/native b/native index 0de5e114f3..ff60f2341b 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 0de5e114f337859a03d0763c30beaf6e03af03c4 +Subproject commit ff60f2341b31d3a8764641c9bee5b824c1090b2a From 6b3ac02dae1bffbc482200d5e8b0510b88f7ae31 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 22:52:09 +0100 Subject: [PATCH 075/276] Now not flushing at every drawcall by mistake... --- GPU/GLES/DisplayListInterpreter.cpp | 83 ++++------------------------- GPU/GLES/IndexGenerator.cpp | 2 +- GPU/GLES/TextureCache.cpp | 2 +- GPU/GLES/TransformPipeline.cpp | 2 - 4 files changed, 13 insertions(+), 76 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 4071efe200..edffc0943d 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -43,13 +43,12 @@ ShaderManager shaderManager; extern u32 curTextureWidth; extern u32 curTextureHeight; -bool flushBeforeCommand[256] = {0}; -const bool flushBeforeCommandList[] = { +bool *flushBeforeCommand = 0; +const int flushBeforeCommandList[] = { GE_CMD_BEZIER, GE_CMD_SPLINE, GE_CMD_SIGNAL, GE_CMD_FINISH, - GE_CMD_END, GE_CMD_BJUMP, GE_CMD_VERTEXTYPE, GE_CMD_OFFSETADDR, @@ -63,8 +62,6 @@ const bool flushBeforeCommandList[] = { GE_CMD_TEXSCALEV, GE_CMD_TEXOFFSETU, GE_CMD_TEXOFFSETV, - GE_CMD_SCISSOR1, - GE_CMD_SCISSOR2, GE_CMD_MINZ, GE_CMD_MAXZ, GE_CMD_FRAMEBUFPTR, @@ -175,9 +172,12 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } + flushBeforeCommand = new bool[256]; + memset(flushBeforeCommand, 0, 256 * sizeof(bool)); for (int i = 0; i < ARRAY_SIZE(flushBeforeCommandList); i++) { flushBeforeCommand[flushBeforeCommandList[i]] = true; } + flushBeforeCommand[1] = false; } GLES_GPU::~GLES_GPU() @@ -288,7 +288,6 @@ GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() void GLES_GPU::SetRenderFrameBuffer() { - Flush(); if (!g_Config.bBufferedRendering) return; // Get parameters @@ -320,6 +319,7 @@ void GLES_GPU::SetRenderFrameBuffer() // None found? Create one. if (!vfb) { + Flush(); vfb = new VirtualFramebuffer; vfb->fb_address = fb_address; vfb->fb_stride = fb_stride; @@ -340,6 +340,7 @@ void GLES_GPU::SetRenderFrameBuffer() if (vfb != currentRenderVfb_) { + Flush(); // Use it as a render target. DEBUG_LOG(HLE, "Switching render target to FBO for %08x", vfb->fb_address); fbo_bind_as_render_target(vfb->fbo); @@ -553,7 +554,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. case GE_CMD_BEZIER: { - Flush(); int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; DrawBezier(bz_ucount, bz_vcount); @@ -563,7 +563,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_SPLINE: { - Flush(); int sp_ucount = data & 0xFF; int sp_vcount = (data >> 8) & 0xFF; int sp_utype = (data >> 16) & 0x3; @@ -612,7 +611,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_FINISH: - Flush(); DEBUG_LOG(G3D,"DL CMD FINISH"); // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) @@ -668,7 +666,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_BJUMP: - Flush(); // bounding box jump. Let's just not jump, for now. DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); break; @@ -683,7 +680,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_VERTEXTYPE: - Flush(); DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); if (diff & GE_VTYPE_THROUGH) { // Throughmode changed, let's make the proj matrix dirty. @@ -719,25 +715,21 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_CULLFACEENABLE: - Flush(); DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); break; case GE_CMD_TEXTUREMAPENABLE: - Flush(); gstate_c.textureChanged = true; DEBUG_LOG(G3D, "DL Texture map enable: %i", data); break; case GE_CMD_LIGHTINGENABLE: - Flush(); DEBUG_LOG(G3D, "DL Lighting enable: %i", data); data += 1; //We don't use OpenGL lighting break; case GE_CMD_FOGENABLE: - Flush(); DEBUG_LOG(G3D, "DL Fog Enable: %i", data); break; @@ -754,28 +746,24 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXSCALEU: - Flush(); gstate_c.uScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: - Flush(); gstate_c.vScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: - Flush(); gstate_c.uOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: - Flush(); gstate_c.vOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); @@ -783,7 +771,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_SCISSOR1: { - Flush(); int x1 = data & 0x3ff; int y1 = data >> 10; DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); @@ -791,7 +778,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_SCISSOR2: { - Flush(); int x2 = data & 0x3ff; int y2 = data >> 10; DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); @@ -810,7 +796,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FRAMEBUFPTR: { - Flush(); u32 ptr = op & 0xFFE000; DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); } @@ -818,7 +803,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FRAMEBUFWIDTH: { - Flush(); u32 w = data & 0xFFFFFF; DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); } @@ -828,7 +812,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXADDR0: - Flush(); gstate_c.textureChanged = true; case GE_CMD_TEXADDR1: case GE_CMD_TEXADDR2: @@ -853,7 +836,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_CLUTADDR: - //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); + DEBUG_LOG(G3D,"CLUT base addr: %06x", data); break; case GE_CMD_CLUTADDRUPPER: @@ -877,12 +860,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXMAPMODE: - Flush(); DEBUG_LOG(G3D,"Tex map mode: %06x", data); break; case GE_CMD_TEXSHADELS: - Flush(); DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); break; @@ -946,7 +927,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK { - Flush(); // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. DoBlockTransfer(); @@ -954,7 +934,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXSIZE0: - Flush(); gstate_c.textureChanged = true; gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); @@ -971,7 +950,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ZBUFPTR: { - Flush(); u32 ptr = op & 0xFFE000; DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); } @@ -985,52 +963,44 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_AMBIENTCOLOR: - Flush(); DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); break; case GE_CMD_AMBIENTALPHA: - Flush(); DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); break; case GE_CMD_MATERIALAMBIENT: - Flush(); DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: - Flush(); DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: - Flush(); DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: - Flush(); DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: - Flush(); DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: - Flush(); DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); if (diff) shaderManager.DirtyUniform(DIRTY_MATSPECULAR); @@ -1048,7 +1018,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: { - Flush(); int n = cmd - GE_CMD_LX0; int l = n / 3; int c = n % 3; @@ -1065,7 +1034,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: { - Flush(); int n = cmd - GE_CMD_LDX0; int l = n / 3; int c = n % 3; @@ -1082,7 +1050,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: { - Flush(); int n = cmd - GE_CMD_LKA0; int l = n / 3; int c = n % 3; @@ -1099,13 +1066,13 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: { - Flush(); float r = (float)(data & 0xff)/255.0f; float g = (float)((data>>8) & 0xff)/255.0f; float b = (float)(data>>16)/255.0f; int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; + DEBUG_LOG(G3D,"DL Light color %i", l); gstate_c.lightColor[t][l][0] = r; gstate_c.lightColor[t][l][1] = g; gstate_c.lightColor[t][l][2] = b; @@ -1118,16 +1085,13 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_VIEWPORTY1: case GE_CMD_VIEWPORTX2: case GE_CMD_VIEWPORTY2: - Flush(); DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); break; case GE_CMD_VIEWPORTZ1: - Flush(); gstate_c.zScale = getFloat24(data) / 65535.f; DEBUG_LOG(G3D,"DL Z scale: %f", gstate_c.zScale); break; case GE_CMD_VIEWPORTZ2: - Flush(); gstate_c.zOff = getFloat24(data) / 65535.f; DEBUG_LOG(G3D,"DL Z pos: %f", gstate_c.zOff); break; @@ -1135,16 +1099,13 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_LIGHTENABLE1: case GE_CMD_LIGHTENABLE2: case GE_CMD_LIGHTENABLE3: - Flush(); DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); break; case GE_CMD_CULL: - Flush(); DEBUG_LOG(G3D,"DL cull: %06x", data); break; case GE_CMD_LMODE: - Flush(); DEBUG_LOG(G3D,"DL Shade mode: %06x", data); break; @@ -1155,7 +1116,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_MATERIALUPDATE: - Flush(); DEBUG_LOG(G3D,"DL Material Update: %d", data); break; @@ -1164,7 +1124,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // CLEARING ////////////////////////////////////////////////////////////////// case GE_CMD_CLEARMODE: - Flush(); // If it becomes a performance problem, check diff&1 if (data & 1) EnterClearMode(data); @@ -1178,40 +1137,33 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // ALPHA BLENDING ////////////////////////////////////////////////////////////////// case GE_CMD_ALPHABLENDENABLE: - Flush(); DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); break; case GE_CMD_BLENDMODE: - Flush(); DEBUG_LOG(G3D,"DL Blend mode: %06x", data); break; case GE_CMD_BLENDFIXEDA: - Flush(); DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); break; case GE_CMD_BLENDFIXEDB: - Flush(); DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); break; case GE_CMD_ALPHATESTENABLE: - Flush(); DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); // This is done in the shader. break; case GE_CMD_ALPHATEST: - Flush(); DEBUG_LOG(G3D,"DL Alpha test settings"); shaderManager.DirtyUniform(DIRTY_ALPHACOLORREF); break; case GE_CMD_TEXFUNC: { - Flush(); DEBUG_LOG(G3D,"DL TexFunc %i", data&7); /* int m=GL_MODULATE; @@ -1239,32 +1191,26 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXFILTER: { - Flush(); int min = data & 7; int mag = (data >> 8) & 1; DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); } break; case GE_CMD_TEXENVCOLOR: - Flush(); DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); if (diff) shaderManager.DirtyUniform(DIRTY_TEXENV); break; case GE_CMD_TEXMODE: - Flush(); DEBUG_LOG(G3D,"DL TexMode %08x", data); break; case GE_CMD_TEXFORMAT: - Flush(); DEBUG_LOG(G3D,"DL TexFormat %08x", data); break; case GE_CMD_TEXFLUSH: - Flush(); DEBUG_LOG(G3D,"DL TexFlush"); break; case GE_CMD_TEXWRAP: - Flush(); DEBUG_LOG(G3D,"DL TexWrap %08x", data); break; ////////////////////////////////////////////////////////////////// @@ -1272,12 +1218,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) ////////////////////////////////////////////////////////////////// case GE_CMD_ZTESTENABLE: - Flush(); DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); break; case GE_CMD_STENCILTESTENABLE: - Flush(); DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); break; @@ -1311,7 +1255,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_WORLDMATRIXNUMBER: - Flush(); DEBUG_LOG(G3D,"DL World # %i", data & 0xF); gstate.worldmtxnum &= 0xFF00000F; break; @@ -1328,7 +1271,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_VIEWMATRIXNUMBER: - Flush(); DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF); gstate.viewmtxnum &= 0xFF00000F; break; @@ -1345,7 +1287,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_PROJMATRIXNUMBER: - Flush(); DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF); gstate.projmtxnum &= 0xFF00000F; break; @@ -1361,7 +1302,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TGENMATRIXNUMBER: - Flush(); DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF); gstate.texmtxnum &= 0xFF00000F; break; @@ -1378,7 +1318,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_BONEMATRIXNUMBER: - Flush(); DEBUG_LOG(G3D,"DL BONE #%i", data); gstate.boneMatrixNumber &= 0xFF00007F; break; @@ -1421,9 +1360,9 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; - if (flushBeforeCommand[cmd]) - Flush(); u32 diff = op ^ gstate.cmdmem[cmd]; + if (diff && flushBeforeCommand[cmd]) + Flush(); gstate.cmdmem[cmd] = op; ExecuteOp(op, diff); diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index d28d92d663..5c2cdf3cb9 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -38,7 +38,7 @@ void IndexGenerator::Reset() { bool IndexGenerator::PrimCompatible(int prim) { if (prim_ == -1) return true; - return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_]; + return indexedPrimitiveType[prim] == prim_; } void IndexGenerator::Setup(u16 *inds) diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index a09c0d1da3..08da1b008a 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -635,7 +635,7 @@ void PSPSetTexture() if (match) { //got one! entry.frameCounter = gpuStats.numFrames; - if (entry.texture != lastBoundTexture) { + if (true || entry.texture != lastBoundTexture) { glBindTexture(GL_TEXTURE_2D, entry.texture); UpdateSamplingParams(); lastBoundTexture = entry.texture; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 03599d5ab3..bece8c27e8 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -640,8 +640,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } break; } - - Flush(); } void GLES_GPU::Flush() From ea07c14c4c390f2744edc475f88c9a26892167c2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 17:50:22 +0100 Subject: [PATCH 076/276] Add IndexGenerator.cpp/h which will later be used to combine small draw calls into large indexed draw calls, for better performance. --- CMakeLists.txt | 2 + GPU/CMakeLists.txt | 1 + GPU/GLES/IndexGenerator.cpp | 232 +++++++++++++++++++++++++++++ GPU/GLES/IndexGenerator.h | 57 +++++++ GPU/GLES/VertexShaderGenerator.cpp | 5 - GPU/GPU.vcxproj | 2 + GPU/GPU.vcxproj.filters | 6 + android/jni/Android.mk | 1 + 8 files changed, 301 insertions(+), 5 deletions(-) create mode 100644 GPU/GLES/IndexGenerator.cpp create mode 100644 GPU/GLES/IndexGenerator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 858bc710c4..adaf9dc6fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -786,6 +786,8 @@ add_library(GPU OBJECT GPU/GLES/FragmentShaderGenerator.h GPU/GLES/Framebuffer.cpp GPU/GLES/Framebuffer.h + GPU/GLES/IndexGenerator.cpp + GPU/GLES/IndexGenerator.h GPU/GLES/ShaderManager.cpp GPU/GLES/ShaderManager.h GPU/GLES/StateMapping.cpp diff --git a/GPU/CMakeLists.txt b/GPU/CMakeLists.txt index 803200ae6d..ad56972231 100644 --- a/GPU/CMakeLists.txt +++ b/GPU/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRCS GLES/DisplayListInterpreter.cpp GLES/FragmentShaderGenerator.cpp GLES/Framebuffer.cpp + GLES/IndexGenerator.cpp GLES/ShaderManager.cpp GLES/StateMapping.cpp GLES/TextureCache.cpp diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp new file mode 100644 index 0000000000..7a786488cf --- /dev/null +++ b/GPU/GLES/IndexGenerator.cpp @@ -0,0 +1,232 @@ +// 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 "IndexGenerator.h" + +// Points don't need indexing... +const u8 indexedPrimitiveType[7] = { + GE_PRIM_POINTS, + GE_PRIM_LINES, + GE_PRIM_LINES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, + GE_PRIM_TRIANGLES, +}; + +void IndexGenerator::Reset() { + prim_ = -1; + inds_ = 0; +} + +bool IndexGenerator::PrimCompatible(int prim) { + if (prim_ == -1) + return true; + return indexedPrimitiveType[prim] == indexedPrimitiveType[prim_]; +} + +void IndexGenerator::Start(u16 *inds, int baseIndex, int prim) +{ + this->inds_ = inds; + index_ = baseIndex; +} + +void IndexGenerator::AddList(int numVerts) +{ + //if we have no vertices return + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + i*3; + *inds_++ = index_ + i*3 + 1; + *inds_++ = index_ + i*3 + 2; + } + + // ignore overflow verts + index_ += numVerts; +} + +void IndexGenerator::AddStrip(int numVerts) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i+(wind?2:1); + *inds_++ = index_ + i+(wind?1:2); + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::AddFan(int numVerts) +{ + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_; + *inds_++ = index_ + i + 1; + *inds_++ = index_ + i + 2; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) +{ + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i*3]; + *inds_++ = index_ + offset + inds[i*3 + 1]; + *inds_++ = index_ + offset + inds[i*3 + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + (wind?2:1)]; + *inds_++ = index_ + offset + inds[i + (wind?1:2)]; + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) +{ + if (numVerts <= 0) return; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; + *inds_++ = index_ + offset + inds[i + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) +{ + int numTris = numVerts / 3; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i*3]; + *inds_++ = index_ + offset + inds[i*3 + 1]; + *inds_++ = index_ + offset + inds[i*3 + 2]; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) +{ + bool wind = false; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + (wind?2:1)]; + *inds_++ = index_ + offset + inds[i + (wind?1:2)]; + wind = !wind; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) +{ + if (numVerts <= 0) return; + int numTris = numVerts - 2; + for (int i = 0; i < numTris; i++) + { + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; + *inds_++ = index_ + offset + inds[i + 2]; + } + index_ += numVerts; +} + +//Lines +void IndexGenerator::AddLineList(int numVerts) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::AddLineStrip(int numVerts) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) +{ + int numLines = numVerts / 2; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i*2; + *inds_++ = index_ + i*2+1; + } + index_ += numVerts; +} + +void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) +{ + int numLines = numVerts - 1; + for (int i = 0; i < numLines; i++) + { + *inds_++ = index_ + i; + *inds_++ = index_ + i + 1; + } + index_ += numVerts; +} \ No newline at end of file diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h new file mode 100644 index 0000000000..45d3a0bad3 --- /dev/null +++ b/GPU/GLES/IndexGenerator.h @@ -0,0 +1,57 @@ +// 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 + +#include "CommonTypes.h" +#include "../ge_constants.h" + +class IndexGenerator +{ +public: + void Reset(); + void Start(u16 *indexptr, int baseIndex, int prim); + bool PrimCompatible(int prim); + + // Triangles + void AddList(int numVerts); + void AddStrip(int numVerts); + void AddFan(int numVerts); + // Lines + void AddLineList(int numVerts); + void AddLineStrip(int numVerts); + + // Translates already indexed lists + void TranslateLineList(int numVerts, const u8 *inds, int offset); + void TranslateLineStrip(int numVerts, const u8 *inds, int offset); + void TranslateLineList(int numVerts, const u16 *inds, int offset); + void TranslateLineStrip(int numVerts, const u16 *inds, int offset); + + void TranslateList(int numVerts, const u8 *inds, int offset); + void TranslateStrip(int numVerts, const u8 *inds, int offset); + void TranslateFan(int numVerts, const u8 *inds, int offset); + void TranslateList(int numVerts, const u16 *inds, int offset); + void TranslateStrip(int numVerts, const u16 *inds, int offset); + void TranslateFan(int numVerts, const u16 *inds, int offset); + +private: + u16 *inds_; + int index_; + int prim_; +}; + diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 395021ce56..953b5c684d 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -15,10 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -// TODO: We should transition from doing the transform in software, as seen in TransformPipeline.cpp, -// into doing the transform in the vertex shader - except for Rectangles, there we really need to do -// the transforms ourselves. - #include #if defined(_WIN32) && defined(_DEBUG) #include @@ -42,7 +38,6 @@ static char buffer[16384]; #define WRITE p+=sprintf - bool CanUseHardwareTransform(int prim) { if (!g_Config.bHardwareTransform) diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 7b36bc7078..9b3228b826 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -120,6 +120,7 @@ + @@ -135,6 +136,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index aad3ad15c2..e5a783590f 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -57,6 +57,9 @@ GLES + + GLES + @@ -95,6 +98,9 @@ GLES + + GLES + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 13a44e02f1..84ddbce292 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -72,6 +72,7 @@ LOCAL_SRC_FILES := \ $(SRC)/GPU/GLES/Framebuffer.cpp \ $(SRC)/GPU/GLES/DisplayListInterpreter.cpp \ $(SRC)/GPU/GLES/TextureCache.cpp \ + $(SRC)/GPU/GLES/IndexGenerator.cpp \ $(SRC)/GPU/GLES/TransformPipeline.cpp \ $(SRC)/GPU/GLES/StateMapping.cpp \ $(SRC)/GPU/GLES/VertexDecoder.cpp \ From 61f7986d12b038866ac1b0ae7d751e08e3ba445e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 22:53:50 +0100 Subject: [PATCH 077/276] update submodules --- native | 2 +- pspautotests | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native b/native index 0de5e114f3..ff60f2341b 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 0de5e114f337859a03d0763c30beaf6e03af03c4 +Subproject commit ff60f2341b31d3a8764641c9bee5b824c1090b2a diff --git a/pspautotests b/pspautotests index 30f1f0698e..54acddd544 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 30f1f0698e2ed2f45f4dd1bd199c81cdc379561e +Subproject commit 54acddd54469a88aadbaf0e69088aad504b5e1e4 From c33eafd430c60540d82366ff367a6940b95740de Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Fri, 21 Dec 2012 23:02:35 +0100 Subject: [PATCH 078/276] Warning fixes --- Core/Dialog/PSPSaveDialog.cpp | 4 ++-- Core/HLE/__sceAudio.cpp | 2 +- Core/HLE/sceAudio.cpp | 2 +- Core/HLE/sceKernelInterrupt.cpp | 5 +++-- Core/HLE/sceKernelThread.cpp | 2 +- Core/HLE/sceRtc.cpp | 14 +++++++------- GPU/GLES/DisplayListInterpreter.cpp | 6 +++--- GPU/GLES/VertexShaderGenerator.cpp | 2 +- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 3185a43a0b..8136491f4a 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -230,7 +230,7 @@ void PSPSaveDialog::DisplaySaveDataInfo1() else { char txt[1024]; - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %d KB\n%s\n%s" + sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %lld KB\n%s\n%s" , param.GetFileInfo(currentSelectedSave).title , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 @@ -254,7 +254,7 @@ void PSPSaveDialog::DisplaySaveDataInfo2() else { char txt[1024]; - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d\n%d KB" + sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d\n%lld KB" , param.GetFileInfo(currentSelectedSave).saveTitle , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index db1cc7332a..fc474706f0 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -186,7 +186,7 @@ void __AudioUpdate() } else { // This happens quite a lot. There's still something slightly off // about the amount of audio we produce. - DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), outAudioQueue.capacity()); + DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); } } diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index fcb869687c..563824421c 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -186,7 +186,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun { WARN_LOG(HLE, "WARNING: Reserving already reserved channel. Error?"); } - DEBUG_LOG(HLE, "%i = sceAudioChReserve(%i, %i, %i)", channel, sampleCount, format); + DEBUG_LOG(HLE, "sceAudioChReserve(channel = %d, sampleCount = %d, format = %d)", channel, sampleCount, format); chans[channel].sampleCount = sampleCount; chans[channel].reserved = true; diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index a8eaa41e3c..0c7b71296f 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -295,7 +295,7 @@ void __TriggerInterrupt(int type, PSPInterrupt intno, int subintr) if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) { intrHandlers[intno].queueUp(subintr); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, (u32)pendingInterrupts.size()); __TriggerRunInterrupts(type); } } @@ -305,7 +305,8 @@ void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int ar if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) { intrHandlers[intno].queueUpWithArg(subintr, arg); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, + (u32)pendingInterrupts.size()); __TriggerRunInterrupts(type); } } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 6523d8ba3a..446fe4a871 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -981,7 +981,7 @@ int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stack __KernelCreateThread(id, curModule, threadName, entry, prio, stacksize, attr); INFO_LOG(HLE, "%i = sceKernelCreateThread(name=\"%s\", entry=%08x, prio=%x, stacksize=%i)", id, threadName, entry, prio, stacksize); if (optionAddr != 0) - WARN_LOG(HLE, "sceKernelCreateThread: unsupported options parameter.", threadName); + WARN_LOG(HLE, "sceKernelCreateThread(name=\"%s\"): unsupported options parameter %08x", threadName, optionAddr); return id; } diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 38447046fa..40df086d01 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -435,7 +435,7 @@ int sceRtcSetTime_t(u32 datePtr, u32 time) int sceRtcSetTime64_t(u32 datePtr, u64 time) { - ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%d,%lld)", datePtr, time); if (Memory::IsValidAddress(datePtr)) { ScePspDateTime pt; @@ -453,7 +453,7 @@ int sceRtcSetTime64_t(u32 datePtr, u64 time) int sceRtcGetTime_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%d,%d)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -472,7 +472,7 @@ int sceRtcGetTime_t(u32 datePtr, u32 timePtr) int sceRtcGetTime64_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%d,%d)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -568,7 +568,7 @@ int sceRtcTickAddTicks(u32 destTickPtr, u32 srcTickPtr, u64 numTicks) Memory::Write_U64(srcTick, destTickPtr); } - DEBUG_LOG(HLE, "sceRtcTickAddTicks(%d,%d,%d)", destTickPtr, srcTickPtr, numTicks); + DEBUG_LOG(HLE, "sceRtcTickAddTicks(%x,%x,%llu)", destTickPtr, srcTickPtr, numTicks); return 0; } @@ -582,7 +582,7 @@ int sceRtcTickAddMicroseconds(u32 destTickPtr,u32 srcTickPtr, u64 numMS) Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddMicroseconds(%d,%d,%d)", destTickPtr, srcTickPtr, numMS); + ERROR_LOG(HLE, "HACK sceRtcTickAddMicroseconds(%x,%x,%llu)", destTickPtr, srcTickPtr, numMS); return 0; } @@ -595,7 +595,7 @@ int sceRtcTickAddSeconds(u32 destTickPtr, u32 srcTickPtr, u64 numSecs) srcTick += numSecs * 1000000UL; Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddSeconds(%d,%d,%d)", destTickPtr, srcTickPtr, numSecs); + ERROR_LOG(HLE, "HACK sceRtcTickAddSeconds(%x,%x,%llu)", destTickPtr, srcTickPtr, numSecs); return 0; } @@ -608,7 +608,7 @@ int sceRtcTickAddMinutes(u32 destTickPtr, u32 srcTickPtr, u64 numMins) srcTick += numMins*60000000UL; Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddMinutes(%d,%d,%d)", destTickPtr, srcTickPtr, numMins); + ERROR_LOG(HLE, "HACK sceRtcTickAddMinutes(%x,%x,%llu)", destTickPtr, srcTickPtr, numMins); return 0; } diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d516cfe9e4..40dc5b5ffa 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -44,11 +44,11 @@ extern u32 curTextureWidth; extern u32 curTextureHeight; GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) - : interruptsEnabled_(true), +: interruptsEnabled_(true), + displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1), - displayFramebufPtr_(0) + dlIdGenerator(1) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 395021ce56..e4b7153c52 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -321,7 +321,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " float dot%i = dot(normalize(toLight%i), worldnormal);\n", i, i); if (poweredDiffuse) { - WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n"); + WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i, i); } if (doLight[i] == LIGHT_DOTONLY) From 6a9a183dd364493c55c9fd1d13ac8ac254af8b3a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 14:10:57 -0800 Subject: [PATCH 079/276] Use sceKernelDcache*() to invalidate the texcache. Also in the block transfer code. --- Core/HLE/sceKernel.cpp | 5 +++++ GPU/GLES/DisplayListInterpreter.cpp | 12 +++++++++++- GPU/GLES/DisplayListInterpreter.h | 1 + GPU/GLES/TextureCache.cpp | 20 ++++++++++++++++++++ GPU/GLES/TextureCache.h | 1 + GPU/GPUInterface.h | 4 ++++ GPU/Null/NullGpu.cpp | 5 +++++ GPU/Null/NullGpu.h | 1 + 8 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index c99b4b6a2a..e9ea4db1e8 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -25,6 +25,8 @@ #include "../PSPLoaders.h" #include "../../Core/CoreTiming.h" #include "../../Core/System.h" +#include "../../GPU/GPUInterface.h" +#include "../../GPU/GPUState.h" #include "__sceAudio.h" @@ -187,6 +189,7 @@ void sceKernelGetGPI() // textures, and in the future display lists, in some cases though. void sceKernelDcacheInvalidateRange(u32 addr, int size) { + gpu->InvalidateCache(addr, size); } void sceKernelDcacheWritebackAll() { @@ -196,9 +199,11 @@ void sceKernelDcacheWritebackRange(u32 addr, int size) } void sceKernelDcacheWritebackInvalidateRange(u32 addr, int size) { + gpu->InvalidateCache(addr, size); } void sceKernelDcacheWritebackInvalidateAll() { + gpu->InvalidateCache(0, -1); } KernelObjectPool kernelObjects; diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d516cfe9e4..ba049038dc 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -1259,7 +1259,7 @@ void GLES_GPU::DoBlockTransfer() { // TODO: This is used a lot to copy data around between render targets and textures, // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so invalidate it and reload it immediately. + // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. // // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so // either copy between rt and texture or reassign the texture to point to the render target @@ -1293,4 +1293,14 @@ void GLES_GPU::DoBlockTransfer() } // TODO: Notify all overlapping textures that it's time to die/reload. + + TextureCache_Invalidate(srcBasePtr + srcY * srcStride + srcX, height * srcStride + width * bpp); +} + +void GLES_GPU::InvalidateCache(u32 addr, int size) +{ + if (size > 0) + TextureCache_Invalidate(addr, size); + else + TextureCache_Clear(true); } diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 690088e98e..7ea8261ce1 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -49,6 +49,7 @@ public: virtual void CopyDisplayToOutput(); virtual void BeginFrame(); virtual void UpdateStats(); + virtual void InvalidateCache(u32 addr, int size); private: // TransformPipeline.cpp diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 9ad2685657..05a9206f25 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -106,6 +106,26 @@ void TextureCache_Decimate() } } +void TextureCache_Invalidate(u32 addr, int size) +{ + u32 addr_end = addr + size; + + for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) + { + // Clear if either the addr or clutaddr is in the range. + bool invalidate = iter->second.addr >= addr && iter->second.addr < addr_end; + invalidate |= iter->second.clutaddr >= addr && iter->second.clutaddr < addr_end; + + if (invalidate) + { + glDeleteTextures(1, &iter->second.texture); + cache.erase(iter++); + } + else + ++iter; + } +} + int TextureCache_NumLoadedTextures() { return cache.size(); diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 2579aa677e..c895c569c7 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -25,4 +25,5 @@ void TextureCache_Init(); void TextureCache_Shutdown(); void TextureCache_Clear(bool delete_them); void TextureCache_Decimate(); // Run this once per frame to get rid of old textures. +void TextureCache_Invalidate(u32 addr, int size); int TextureCache_NumLoadedTextures(); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index f3fb0dad5e..be31b0c026 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -45,6 +45,10 @@ public: // Tells the GPU to update the gpuStats structure. virtual void UpdateStats() = 0; + // Invalidate any cached content sourced from the specified range. + // If size = -1, invalidate everything. + virtual void InvalidateCache(u32 addr, int size) = 0; + // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; }; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index c327266a02..3dd5228a02 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -838,3 +838,8 @@ void NullGPU::UpdateStats() gpuStats.numShaders = 0; gpuStats.numTextures = 0; } + +void NullGPU::InvalidateCache(u32 addr, int size) +{ + // Nothing to invalidate. +} diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 4acbf6895c..eacee19084 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -40,6 +40,7 @@ public: virtual void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) {} virtual void CopyDisplayToOutput() {} virtual void UpdateStats(); + virtual void InvalidateCache(u32 addr, int size); private: bool ProcessDLQueue(); From 18fe1d4b19af03bbeffa598484e2b70e50c2d999 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 14:21:23 -0800 Subject: [PATCH 080/276] Darn, invalidate the dest not the src. --- GPU/GLES/DisplayListInterpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index ba049038dc..1c90df2bac 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -1294,7 +1294,7 @@ void GLES_GPU::DoBlockTransfer() // TODO: Notify all overlapping textures that it's time to die/reload. - TextureCache_Invalidate(srcBasePtr + srcY * srcStride + srcX, height * srcStride + width * bpp); + TextureCache_Invalidate(dstBasePtr + dstY * dstStride + dstX, height * dstStride + width * bpp); } void GLES_GPU::InvalidateCache(u32 addr, int size) From 0769eb4b64890e555da6b27a6cbb8c9dac1e504d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 23:40:11 +0100 Subject: [PATCH 081/276] Set gstate_c.textureChanged in a few more places. --- GPU/GLES/DisplayListInterpreter.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 8bedf33010..1852a07892 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -197,6 +197,7 @@ void GLES_GPU::SetRenderFrameBuffer() // None found? Create one. if (!vfb) { + gstate_c.textureChanged = true; vfb = new VirtualFramebuffer; vfb->fb_address = fb_address; vfb->fb_stride = fb_stride; @@ -219,6 +220,7 @@ void GLES_GPU::SetRenderFrameBuffer() { // Use it as a render target. DEBUG_LOG(HLE, "Switching render target to FBO for %08x", vfb->fb_address); + gstate_c.textureChanged = true; fbo_bind_as_render_target(vfb->fbo); glViewport(0, 0, renderWidth_, renderHeight_); currentRenderVfb_ = vfb; @@ -688,7 +690,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXADDR0: - gstate_c.textureChanged = true; case GE_CMD_TEXADDR1: case GE_CMD_TEXADDR2: case GE_CMD_TEXADDR3: @@ -696,11 +697,11 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXADDR5: case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); break; case GE_CMD_TEXBUFWIDTH0: - gstate_c.textureChanged = true; case GE_CMD_TEXBUFWIDTH1: case GE_CMD_TEXBUFWIDTH2: case GE_CMD_TEXBUFWIDTH3: @@ -708,18 +709,22 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXBUFWIDTH5: case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); break; case GE_CMD_CLUTADDR: + gstate_c.textureChanged = true; //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); break; case GE_CMD_CLUTADDRUPPER: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); break; case GE_CMD_LOADCLUT: + gstate_c.textureChanged = true; // This could be used to "dirty" textures with clut. { u32 clutAddr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); @@ -745,6 +750,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_CLUTFORMAT: { + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Clut format: %06x", data); } break; @@ -810,7 +816,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXSIZE0: - gstate_c.textureChanged = true; gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); //fall thru - ignoring the mipmap sizes for now @@ -822,6 +827,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: DEBUG_LOG(G3D,"DL Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); + gstate_c.textureChanged = true; break; case GE_CMD_ZBUFPTR: From e42af096c8c804bd132a9d1aa56b9df2615b52c7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 23:43:48 +0100 Subject: [PATCH 082/276] Merge --- Core/Dialog/PSPSaveDialog.cpp | 4 ++-- Core/HLE/__sceAudio.cpp | 2 +- Core/HLE/sceAudio.cpp | 2 +- Core/HLE/sceKernel.cpp | 5 +++++ Core/HLE/sceKernelInterrupt.cpp | 5 +++-- Core/HLE/sceKernelThread.cpp | 2 +- Core/HLE/sceRtc.cpp | 14 ++++++------- GPU/GLES/DisplayListInterpreter.cpp | 32 +++++++++++++++++++++-------- GPU/GLES/DisplayListInterpreter.h | 1 + GPU/GLES/TextureCache.cpp | 20 ++++++++++++++++++ GPU/GLES/TextureCache.h | 1 + GPU/GLES/VertexShaderGenerator.cpp | 2 +- GPU/GPUInterface.h | 4 ++++ GPU/Null/NullGpu.cpp | 5 +++++ GPU/Null/NullGpu.h | 1 + 15 files changed, 77 insertions(+), 23 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 5a1ff4ea53..a404870fc4 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -231,7 +231,7 @@ void PSPSaveDialog::DisplaySaveDataInfo1() else { char txt[1024]; - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %d KB\n%s\n%s" + sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %lld KB\n%s\n%s" , param.GetFileInfo(currentSelectedSave).title , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 @@ -255,7 +255,7 @@ void PSPSaveDialog::DisplaySaveDataInfo2() else { char txt[1024]; - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d\n%d KB" + sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d\n%lld KB" , param.GetFileInfo(currentSelectedSave).saveTitle , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index db1cc7332a..fc474706f0 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -186,7 +186,7 @@ void __AudioUpdate() } else { // This happens quite a lot. There's still something slightly off // about the amount of audio we produce. - DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), outAudioQueue.capacity()); + DEBUG_LOG(HLE, "Audio outbuffer overrun! room = %i / %i", outAudioQueue.room(), (u32)outAudioQueue.capacity()); } } diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index fcb869687c..563824421c 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -186,7 +186,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun { WARN_LOG(HLE, "WARNING: Reserving already reserved channel. Error?"); } - DEBUG_LOG(HLE, "%i = sceAudioChReserve(%i, %i, %i)", channel, sampleCount, format); + DEBUG_LOG(HLE, "sceAudioChReserve(channel = %d, sampleCount = %d, format = %d)", channel, sampleCount, format); chans[channel].sampleCount = sampleCount; chans[channel].reserved = true; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index c99b4b6a2a..e9ea4db1e8 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -25,6 +25,8 @@ #include "../PSPLoaders.h" #include "../../Core/CoreTiming.h" #include "../../Core/System.h" +#include "../../GPU/GPUInterface.h" +#include "../../GPU/GPUState.h" #include "__sceAudio.h" @@ -187,6 +189,7 @@ void sceKernelGetGPI() // textures, and in the future display lists, in some cases though. void sceKernelDcacheInvalidateRange(u32 addr, int size) { + gpu->InvalidateCache(addr, size); } void sceKernelDcacheWritebackAll() { @@ -196,9 +199,11 @@ void sceKernelDcacheWritebackRange(u32 addr, int size) } void sceKernelDcacheWritebackInvalidateRange(u32 addr, int size) { + gpu->InvalidateCache(addr, size); } void sceKernelDcacheWritebackInvalidateAll() { + gpu->InvalidateCache(0, -1); } KernelObjectPool kernelObjects; diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index a8eaa41e3c..0c7b71296f 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -295,7 +295,7 @@ void __TriggerInterrupt(int type, PSPInterrupt intno, int subintr) if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) { intrHandlers[intno].queueUp(subintr); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, (u32)pendingInterrupts.size()); __TriggerRunInterrupts(type); } } @@ -305,7 +305,8 @@ void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int ar if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0) { intrHandlers[intno].queueUpWithArg(subintr, arg); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, + (u32)pendingInterrupts.size()); __TriggerRunInterrupts(type); } } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 6523d8ba3a..446fe4a871 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -981,7 +981,7 @@ int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stack __KernelCreateThread(id, curModule, threadName, entry, prio, stacksize, attr); INFO_LOG(HLE, "%i = sceKernelCreateThread(name=\"%s\", entry=%08x, prio=%x, stacksize=%i)", id, threadName, entry, prio, stacksize); if (optionAddr != 0) - WARN_LOG(HLE, "sceKernelCreateThread: unsupported options parameter.", threadName); + WARN_LOG(HLE, "sceKernelCreateThread(name=\"%s\"): unsupported options parameter %08x", threadName, optionAddr); return id; } diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 38447046fa..40df086d01 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -435,7 +435,7 @@ int sceRtcSetTime_t(u32 datePtr, u32 time) int sceRtcSetTime64_t(u32 datePtr, u64 time) { - ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%d,%lld)", datePtr, time); if (Memory::IsValidAddress(datePtr)) { ScePspDateTime pt; @@ -453,7 +453,7 @@ int sceRtcSetTime64_t(u32 datePtr, u64 time) int sceRtcGetTime_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%d,%d)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -472,7 +472,7 @@ int sceRtcGetTime_t(u32 datePtr, u32 timePtr) int sceRtcGetTime64_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%d,%d)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -568,7 +568,7 @@ int sceRtcTickAddTicks(u32 destTickPtr, u32 srcTickPtr, u64 numTicks) Memory::Write_U64(srcTick, destTickPtr); } - DEBUG_LOG(HLE, "sceRtcTickAddTicks(%d,%d,%d)", destTickPtr, srcTickPtr, numTicks); + DEBUG_LOG(HLE, "sceRtcTickAddTicks(%x,%x,%llu)", destTickPtr, srcTickPtr, numTicks); return 0; } @@ -582,7 +582,7 @@ int sceRtcTickAddMicroseconds(u32 destTickPtr,u32 srcTickPtr, u64 numMS) Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddMicroseconds(%d,%d,%d)", destTickPtr, srcTickPtr, numMS); + ERROR_LOG(HLE, "HACK sceRtcTickAddMicroseconds(%x,%x,%llu)", destTickPtr, srcTickPtr, numMS); return 0; } @@ -595,7 +595,7 @@ int sceRtcTickAddSeconds(u32 destTickPtr, u32 srcTickPtr, u64 numSecs) srcTick += numSecs * 1000000UL; Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddSeconds(%d,%d,%d)", destTickPtr, srcTickPtr, numSecs); + ERROR_LOG(HLE, "HACK sceRtcTickAddSeconds(%x,%x,%llu)", destTickPtr, srcTickPtr, numSecs); return 0; } @@ -608,7 +608,7 @@ int sceRtcTickAddMinutes(u32 destTickPtr, u32 srcTickPtr, u64 numMins) srcTick += numMins*60000000UL; Memory::Write_U64(srcTick, destTickPtr); } - ERROR_LOG(HLE, "HACK sceRtcTickAddMinutes(%d,%d,%d)", destTickPtr, srcTickPtr, numMins); + ERROR_LOG(HLE, "HACK sceRtcTickAddMinutes(%x,%x,%llu)", destTickPtr, srcTickPtr, numMins); return 0; } diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index edffc0943d..845d380db5 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -156,11 +156,11 @@ const int flushBeforeCommandList[] = { }; GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) - : interruptsEnabled_(true), +: interruptsEnabled_(true), + displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1), - displayFramebufPtr_(0) + dlIdGenerator(1) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; @@ -320,6 +320,7 @@ void GLES_GPU::SetRenderFrameBuffer() // None found? Create one. if (!vfb) { Flush(); + gstate_c.textureChanged = true; vfb = new VirtualFramebuffer; vfb->fb_address = fb_address; vfb->fb_stride = fb_stride; @@ -343,6 +344,7 @@ void GLES_GPU::SetRenderFrameBuffer() Flush(); // Use it as a render target. DEBUG_LOG(HLE, "Switching render target to FBO for %08x", vfb->fb_address); + gstate_c.textureChanged = true; fbo_bind_as_render_target(vfb->fbo); glViewport(0, 0, renderWidth_, renderHeight_); currentRenderVfb_ = vfb; @@ -812,7 +814,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_TEXADDR0: - gstate_c.textureChanged = true; case GE_CMD_TEXADDR1: case GE_CMD_TEXADDR2: case GE_CMD_TEXADDR3: @@ -820,11 +821,11 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXADDR5: case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); break; case GE_CMD_TEXBUFWIDTH0: - gstate_c.textureChanged = true; case GE_CMD_TEXBUFWIDTH1: case GE_CMD_TEXBUFWIDTH2: case GE_CMD_TEXBUFWIDTH3: @@ -832,18 +833,22 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXBUFWIDTH5: case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); break; case GE_CMD_CLUTADDR: - DEBUG_LOG(G3D,"CLUT base addr: %06x", data); + //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); + gstate_c.textureChanged = true; break; case GE_CMD_CLUTADDRUPPER: + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); break; case GE_CMD_LOADCLUT: + gstate_c.textureChanged = true; // This could be used to "dirty" textures with clut. { u32 clutAddr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); @@ -869,6 +874,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_CLUTFORMAT: { + gstate_c.textureChanged = true; DEBUG_LOG(G3D,"DL Clut format: %06x", data); } break; @@ -934,7 +940,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) } case GE_CMD_TEXSIZE0: - gstate_c.textureChanged = true; gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); //fall thru - ignoring the mipmap sizes for now @@ -946,6 +951,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: DEBUG_LOG(G3D,"DL Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); + gstate_c.textureChanged = true; break; case GE_CMD_ZBUFPTR: @@ -1386,7 +1392,7 @@ void GLES_GPU::DoBlockTransfer() { // TODO: This is used a lot to copy data around between render targets and textures, // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so invalidate it and reload it immediately. + // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. // // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so // either copy between rt and texture or reassign the texture to point to the render target @@ -1420,4 +1426,14 @@ void GLES_GPU::DoBlockTransfer() } // TODO: Notify all overlapping textures that it's time to die/reload. + + TextureCache_Invalidate(dstBasePtr + dstY * dstStride + dstX, height * dstStride + width * bpp); +} + +void GLES_GPU::InvalidateCache(u32 addr, int size) +{ + if (size > 0) + TextureCache_Invalidate(addr, size); + else + TextureCache_Clear(true); } diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 439157c9b9..425bc999a3 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -49,6 +49,7 @@ public: virtual void CopyDisplayToOutput(); virtual void BeginFrame(); virtual void UpdateStats(); + virtual void InvalidateCache(u32 addr, int size); private: // TransformPipeline.cpp diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 08da1b008a..ad8e708a1b 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -106,6 +106,26 @@ void TextureCache_Decimate() } } +void TextureCache_Invalidate(u32 addr, int size) +{ + u32 addr_end = addr + size; + + for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) + { + // Clear if either the addr or clutaddr is in the range. + bool invalidate = iter->second.addr >= addr && iter->second.addr < addr_end; + invalidate |= iter->second.clutaddr >= addr && iter->second.clutaddr < addr_end; + + if (invalidate) + { + glDeleteTextures(1, &iter->second.texture); + cache.erase(iter++); + } + else + ++iter; + } +} + int TextureCache_NumLoadedTextures() { return cache.size(); diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 2579aa677e..c895c569c7 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -25,4 +25,5 @@ void TextureCache_Init(); void TextureCache_Shutdown(); void TextureCache_Clear(bool delete_them); void TextureCache_Decimate(); // Run this once per frame to get rid of old textures. +void TextureCache_Invalidate(u32 addr, int size); int TextureCache_NumLoadedTextures(); diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 0c41881839..8cd6cafa6a 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -307,7 +307,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " float dot%i = dot(normalize(toLight%i), worldnormal);\n", i, i); if (poweredDiffuse) { - WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i); + WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i, i); } if (doLight[i] == LIGHT_DOTONLY) diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index f3fb0dad5e..be31b0c026 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -45,6 +45,10 @@ public: // Tells the GPU to update the gpuStats structure. virtual void UpdateStats() = 0; + // Invalidate any cached content sourced from the specified range. + // If size = -1, invalidate everything. + virtual void InvalidateCache(u32 addr, int size) = 0; + // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; }; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index c327266a02..3dd5228a02 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -838,3 +838,8 @@ void NullGPU::UpdateStats() gpuStats.numShaders = 0; gpuStats.numTextures = 0; } + +void NullGPU::InvalidateCache(u32 addr, int size) +{ + // Nothing to invalidate. +} diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 4acbf6895c..eacee19084 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -40,6 +40,7 @@ public: virtual void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) {} virtual void CopyDisplayToOutput() {} virtual void UpdateStats(); + virtual void InvalidateCache(u32 addr, int size); private: bool ProcessDLQueue(); From 252845ecb6ba1445e77a5ddabe581dbf46adba89 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 21 Dec 2012 23:54:38 +0100 Subject: [PATCH 083/276] Bugfix, remove hack --- Core/Dialog/PSPSaveDialog.cpp | 1 - Core/HLE/sceGe.cpp | 3 ++- GPU/GPUInterface.h | 2 ++ GPU/GPUState.cpp | 1 + GPU/Null/NullGpu.h | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index a404870fc4..8136491f4a 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -33,7 +33,6 @@ PSPSaveDialog::~PSPSaveDialog() { u32 PSPSaveDialog::Init(int paramAddr) { - return 0; // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 3752622f7f..8cbff40b80 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -166,7 +166,7 @@ void sceGeUnsetCallback(u32 cbID) { u32 sceGeSaveContext(u32 ctxAddr) { DEBUG_LOG(HLE, "sceGeSaveContext(%08x)", ctxAddr); - + gpu->Flush(); if (sizeof(gstate) > 512 * 4) { ERROR_LOG(HLE, "AARGH! sizeof(gstate) has grown too large!"); @@ -187,6 +187,7 @@ u32 sceGeSaveContext(u32 ctxAddr) u32 sceGeRestoreContext(u32 ctxAddr) { DEBUG_LOG(HLE, "sceGeRestoreContext(%08x)", ctxAddr); + gpu->Flush(); if (sizeof(gstate) > 512 * 4) { diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index be31b0c026..09773f7cf2 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -51,4 +51,6 @@ public: // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; + + virtual void Flush() = 0; }; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index ff4e868b27..2f60deb5d6 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -78,6 +78,7 @@ void ReapplyGfxState() { if (!gpu) return; + gpu->Flush(); // ShaderManager_DirtyShader(); // The commands are embedded in the command memory so we can just reexecute the words. Convenient. // To be safe we pass 0xFFFFFFF as the diff. diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index eacee19084..93e9de9488 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -41,6 +41,7 @@ public: virtual void CopyDisplayToOutput() {} virtual void UpdateStats(); virtual void InvalidateCache(u32 addr, int size); + virtual void Flush() {} private: bool ProcessDLQueue(); From baa640ea023d4ee8aa3de30532b4021c7310513e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Dec 2012 00:24:04 +0100 Subject: [PATCH 084/276] Two more commands that get to trigger flush --- GPU/GLES/DisplayListInterpreter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 845d380db5..7540b62041 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -120,6 +120,7 @@ const int flushBeforeCommandList[] = { GE_CMD_LIGHTENABLE3, GE_CMD_CULL, GE_CMD_LMODE, + GE_CMD_REVERSENORMAL, GE_CMD_PATCHDIVISION, GE_CMD_MATERIALUPDATE, GE_CMD_CLEARMODE, @@ -138,6 +139,7 @@ const int flushBeforeCommandList[] = { GE_CMD_TEXWRAP, GE_CMD_ZTESTENABLE, GE_CMD_STENCILTESTENABLE, + GE_CMD_STENCILOP, GE_CMD_ZTEST, GE_CMD_MORPHWEIGHT0, GE_CMD_MORPHWEIGHT1, From 8c267b0105e44705caaf775c38990696cde965be Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Dec 2012 00:38:17 +0100 Subject: [PATCH 085/276] Didn't mean to remove these calls --- GPU/GLES/TextureCache.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index ad8e708a1b..1b867a46d4 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -952,9 +952,9 @@ void PSPSetTexture() gpuStats.numTexturesDecoded++; // Can restore these and remove the above fixup on some platforms. //glPixelStorei(GL_UNPACK_ROW_LENGTH, bufw); - //glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign); + glPixelStorei(GL_UNPACK_ALIGNMENT, texByteAlign); //glPixelStorei(GL_PACK_ROW_LENGTH, bufw); - //glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign); + glPixelStorei(GL_PACK_ALIGNMENT, texByteAlign); INFO_LOG(G3D, "Creating texture %i from %08x: %i x %i (stride: %i). fmt: %i", entry.texture, entry.addr, w, h, bufw, entry.format); @@ -967,9 +967,9 @@ void PSPSetTexture() UpdateSamplingParams(); //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //glPixelStorei(GL_PACK_ROW_LENGTH, 0); - //glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); cache[cachekey] = entry; } From 8964ebcfd94bdc9f871b1c6f441d4083e94a64e0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 15:23:01 -0800 Subject: [PATCH 086/276] Don't chop the float in vscmp, don't branch. --- Core/MIPS/MIPSIntVFPU.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index eddba0a942..a3e3b2d902 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1495,10 +1495,8 @@ namespace MIPSInt ApplySwizzleT(t, sz); int n = GetNumVectorElements(sz); for (int i = 0; i < n ; i++) { - int a=s[i] - t[i]; - if (a > 0) d[i]=1; - else if (a < 0) d[i]=-1; - else d[i]=0; + float a = s[i] - t[i]; + d[i] = (0.0 < a) - (a < 0.0); } ApplyPrefixD(d, sz); WriteVector(d, sz, vd); From aabbbe9be46d630066b6203e0c2129a2a10f86c4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Dec 2012 00:57:42 +0100 Subject: [PATCH 087/276] IndexGenerator: fix triangle fans --- GPU/GLES/IndexGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index 5c2cdf3cb9..7f1da114c1 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -165,7 +165,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) int numTris = numVerts - 2; for (int i = 0; i < numTris; i++) { - *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[0]; *inds_++ = index_ + offset + inds[i + 1]; *inds_++ = index_ + offset + inds[i + 2]; } @@ -210,7 +210,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) int numTris = numVerts - 2; for (int i = 0; i < numTris; i++) { - *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[0]; *inds_++ = index_ + offset + inds[i + 1]; *inds_++ = index_ + offset + inds[i + 2]; } From 217bdc275e34b61f7ef36d807a0c4e717a28f86f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 15:41:09 -0800 Subject: [PATCH 088/276] Fix some type-conversion warnings. --- Core/Dialog/SavedataParam.cpp | 4 ++-- Core/HLE/sceFont.cpp | 28 ++++++++++++++-------------- Core/HLE/sceKernelMsgPipe.cpp | 8 ++++---- Core/HLE/sceRtc.cpp | 2 +- Core/HW/SasAudio.cpp | 2 +- Core/MIPS/MIPSIntVFPU.cpp | 2 +- Windows/WndMainWindow.cpp | 8 ++++---- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index e510f28026..078fc7d0c3 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -413,7 +413,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) memcpy(saveDataList[realCount].saveDetail,savedetail.c_str(),savedetail.size()); saveDataList[realCount].saveDetail[savedetail.size()] = 0; } - delete sfoParam; + delete [] sfoParam; } DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); @@ -504,7 +504,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) memcpy(saveDataList[0].saveDetail,savedetail.c_str(),savedetail.size()); saveDataList[0].saveDetail[savedetail.size()] = 0; } - delete sfoParam; + delete [] sfoParam; } DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index 664a6699d5..d2caefb3ad 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -235,32 +235,32 @@ int sceFontGetFontInfo(u32 fontHandle, u32 fontInfoPtr) memset (&fi, 0, sizeof(fi)); if (Memory::IsValidAddress(fontInfoPtr)) { - fi.BPP =4; + fi.BPP = 4; fi.charMapLength = 255; // fi.fontStyle =1; fi.maxGlyphAdvanceXF = 2.0; - fi.maxGlyphAdvanceXI =2; + fi.maxGlyphAdvanceXI = 2; fi.maxGlyphAdvanceYF = 2.0; fi.maxGlyphAdvanceYI = 32 << 6; - fi.maxGlyphAscenderF =32 << 6; + fi.maxGlyphAscenderF = 32 << 6; fi.maxGlyphAscenderI = 32 << 6; - fi.maxGlyphBaseYF= 0.0; - fi.maxGlyphBaseYI=0.0; - fi.maxGlyphDescenderF =0; - fi.maxGlyphDescenderI =0; + fi.maxGlyphBaseYF = 0.0; + fi.maxGlyphBaseYI = 0; + fi.maxGlyphDescenderF = 0; + fi.maxGlyphDescenderI = 0; fi.maxGlyphHeight = 32; - fi.maxGlyphHeightF= 32; + fi.maxGlyphHeightF = 32; fi.maxGlyphHeightI = 32; - fi.maxGlyphLeftXF= 0; + fi.maxGlyphLeftXF = 0; fi.maxGlyphLeftXI = 0; - fi.maxGlyphTopYF =0; + fi.maxGlyphTopYF = 0; fi.maxGlyphTopYI = 0; - fi.maxGlyphWidth =32; + fi.maxGlyphWidth = 32; fi.maxGlyphWidthF = 32; - fi.maxGlyphWidthI= 32; + fi.maxGlyphWidthI = 32; fi.minGlyphCenterXF = 16; - fi.minGlyphCenterXI= 16; - fi.shadowMapLength=0; + fi.minGlyphCenterXI = 16; + fi.shadowMapLength = 0; Memory::WriteStruct(fontInfoPtr, &fi); } diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index ca8fa76a73..1521d5f188 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -98,7 +98,7 @@ struct MsgPipe : public KernelObject if (sendWaitingThreads.empty()) return; MsgPipeWaitingThread *thread = &sendWaitingThreads.front(); - if (nmp.freeSize >= thread->bufSize) + if ((u32) nmp.freeSize >= thread->bufSize) { // Put all the data to the buffer memcpy(buffer + (nmp.bufSize - nmp.freeSize), Memory::GetPointer(thread->bufAddr), thread->bufSize); @@ -126,7 +126,7 @@ struct MsgPipe : public KernelObject if (receiveWaitingThreads.empty()) return; MsgPipeWaitingThread *thread = &receiveWaitingThreads.front(); - if (nmp.bufSize - nmp.freeSize >= thread->bufSize) + if ((u32) nmp.bufSize - (u32) nmp.freeSize >= thread->bufSize) { // Get the needed data from the buffer Memory::Memcpy(thread->bufAddr, buffer, thread->bufSize); @@ -271,7 +271,7 @@ void __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode } else { - if (sendSize <= m->nmp.freeSize) + if (sendSize <= (u32) m->nmp.freeSize) { memcpy(m->buffer + (m->nmp.bufSize - m->nmp.freeSize), Memory::GetPointer(sendBufAddr), sendSize); m->nmp.freeSize -= sendSize; @@ -445,7 +445,7 @@ void __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSize, int else { // Enough data in the buffer: copy just the needed amount of data - if (receiveSize <= m->nmp.bufSize - m->nmp.freeSize) + if (receiveSize <= (u32) m->nmp.bufSize - (u32) m->nmp.freeSize) { Memory::Memcpy(receiveBufAddr, m->buffer, receiveSize); m->nmp.freeSize += receiveSize; diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 40df086d01..33f28ecb58 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -459,7 +459,7 @@ int sceRtcGetTime_t(u32 datePtr, u32 timePtr) ScePspDateTime pt; Memory::ReadStruct(datePtr, &pt); pt.year-=1969; - u64 result = __RtcPspTimeToTicks(pt)/1000000ULL; + u32 result = (u32) (__RtcPspTimeToTicks(pt)/1000000ULL); Memory::Write_U32(result, timePtr); } else diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index b4ad23d2ef..d8025e7196 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -215,7 +215,7 @@ 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; - u32 numSamples = lastSample - curSample; + int numSamples = lastSample - curSample; if (numSamples > grainSize * 4) { ERROR_LOG(SAS, "numSamples too large, clamping: %i vs %i", numSamples, grainSize * 4); numSamples = grainSize * 4; diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index a3e3b2d902..f24dd2cc4e 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1496,7 +1496,7 @@ namespace MIPSInt int n = GetNumVectorElements(sz); for (int i = 0; i < n ; i++) { float a = s[i] - t[i]; - d[i] = (0.0 < a) - (a < 0.0); + d[i] = (float) ((0.0 < a) - (a < 0.0)); } ApplyPrefixD(d, sz); WriteVector(d, sz, vd); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index ec3868b027..90152ccf2b 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -114,13 +114,13 @@ namespace MainWindow void SetZoom(float zoom) { if (zoom < 5) - g_Config.iWindowZoom = zoom; + g_Config.iWindowZoom = (int) zoom; RECT rc, rcOuter; - GetWindowRectAtZoom(zoom, rc, rcOuter); + GetWindowRectAtZoom((int) 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; + PSP_CoreParameter().pixelWidth = (int) (480 * zoom); + PSP_CoreParameter().pixelHeight = (int) (272 * zoom); GL_Resized(); } From ec753a35755e3b101dd46ab75b1fed5414f9ae9c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 16:07:42 -0800 Subject: [PATCH 089/276] Fix some ignored error / shadowing warnings. --- Core/Debugger/Breakpoints.cpp | 2 +- Core/Debugger/SymbolMap.cpp | 14 +++++++------- Core/FileSystems/DirectoryFileSystem.cpp | 4 ++-- Core/FileSystems/ISOFileSystem.cpp | 10 +++++++--- Core/HLE/sceKernel.cpp | 2 +- Core/HLE/sceKernelModule.cpp | 10 +++++----- Core/MIPS/MIPSAnalyst.cpp | 8 ++++---- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index f682b96727..c426dfb7d7 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -40,7 +40,7 @@ void MemCheck::Action(u32 iValue, u32 addr, bool write, int size, u32 pc) if (bLog) { char temp[256]; - printf(temp,"CHK %08x %s%i at %08x (%s), PC=%08x (%s)",iValue,write?"Write":"Read",size*8,addr,symbolMap.GetDescription(addr),pc,symbolMap.GetDescription(pc)); + sprintf(temp,"CHK %08x %s%i at %08x (%s), PC=%08x (%s)",iValue,write?"Write":"Read",size*8,addr,symbolMap.GetDescription(addr),pc,symbolMap.GetDescription(pc)); ERROR_LOG(MEMMAP,"%s",temp); } if (bBreak) diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index b4f454b32f..c2481ec71d 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -144,10 +144,9 @@ bool SymbolMap::LoadSymbolMap(const char *filename) { char line[512],temp[256]; fgets(line,511,f); - if (strlen(line)<4) + if (strlen(line) < 4 || sscanf(line, "%s", temp) != 1) continue; - sscanf(line,"%s",temp); if (strcmp(temp,"UNUSED")==0) continue; if (strcmp(temp,".text")==0) {started=true;continue;}; if (strcmp(temp,".init")==0) {started=true;continue;}; @@ -233,7 +232,7 @@ int SymbolMap::GetSymbolNum(unsigned int address, SymbolType symmask) } -char temp[256]; +char descriptionTemp[256]; char *SymbolMap::GetDescription(unsigned int address) { @@ -244,8 +243,8 @@ char *SymbolMap::GetDescription(unsigned int address) return entries[fun].name; else { - sprintf(temp, "(%08x)", address); - return temp; + sprintf(descriptionTemp, "(%08x)", address); + return descriptionTemp; } //} //else @@ -438,11 +437,12 @@ void SymbolMap::UseFuncSignaturesFile(const char *filename, u32 maxAddress) //#1: Read the signature file and put them in a fast data structure FILE *f = fopen(filename, "r"); int count; - fscanf(f,"%08x\n",&count); - u32 inst,size,hash; + if (fscanf(f, "%08x\n", &count) != 1) + count = 0; char name[256]; for (int a=0; asecond.hFile, (LPVOID)pointer, (DWORD)size, (LPDWORD)&bytesRead, 0); #else - bytesRead = fread(pointer, 1, size, iter->second.hFile); + bytesRead = fread(pointer, 1, size, iter->second.hFile); #endif return bytesRead; } diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 2964d8e684..3578c6246c 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -29,11 +29,13 @@ static bool parseLBN(std::string filename, u32 *sectorStart, u32 *readSize) { if (filename.substr(0, 8) != "/sce_lbn") return false; - std::string yo = filename; + std::string prev = filename; filename.erase(0, 10); - sscanf(filename.c_str(), "%08x", sectorStart); + if (sscanf(filename.c_str(), "%08x", sectorStart) != 1) + WARN_LOG(FILESYS, "Invalid LBN reference: %s", prev.c_str()); filename.erase(0, filename.find("_size") + 7); - sscanf(filename.c_str(), "%08x", readSize); + if (sscanf(filename.c_str(), "%08x", readSize) != 1) + WARN_LOG(FILESYS, "Incomplete LBN reference: %s", prev.c_str()); return true; } @@ -393,6 +395,8 @@ size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) } else { + _dbg_assert_msg_(HLE, e.file != 0, "Expecting non-raw fd to have a tree entry."); + //clamp read length if ((s64)e.seekPos > e.file->size - (s64)size) { diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index e9ea4db1e8..adcc652b84 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -270,12 +270,12 @@ void KernelObjectPool::List() if (pool[i]) { pool[i]->GetQuickInfo(buffer,256); + INFO_LOG(HLE, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer); } else { strcpy(buffer,"WTF? Zero Pointer"); } - INFO_LOG(HLE, "KO %i: %s \"%s\": %s", i + handleOffset, pool[i]->GetTypeName(), pool[i]->GetName(), buffer); } } } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 3624d5f523..4303eca9e2 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -448,13 +448,13 @@ bool __KernelLoadPBP(const char *filename, std::string *error_string) in.seekg(offsets[5]); //in.read((char*)&id,4); { - u8 *temp = new u8[1024*1024*8]; - in.read((char*)temp, 1024*1024*8); - Module *module = __KernelLoadELFFromPtr(temp, PSP_GetDefaultLoadAddress(), error_string); + u8 *elftemp = new u8[1024*1024*8]; + in.read((char*)elftemp, 1024*1024*8); + Module *module = __KernelLoadELFFromPtr(elftemp, PSP_GetDefaultLoadAddress(), error_string); if (!module) return false; mipsr4k.pc = module->nm.entry_addr; - delete [] temp; + delete [] elftemp; } in.close(); return true; @@ -612,7 +612,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags) // TODO: Use position to decide whether to load high or low if (PARAM(2)) { - SceKernelLMOption *lmoption = (SceKernelLMOption *)Memory::GetPointer(PARAM(2)); + lmoption = (SceKernelLMOption *)Memory::GetPointer(PARAM(2)); } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index a97b168d8b..b05f70ed8d 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -301,13 +301,13 @@ namespace MIPSAnalyst { if (addr >= furthestBranch) { - u32 target = GetSureBranchTarget(addr); - if (target != INVALIDTARGET && target < addr) + u32 sureTarget = GetSureBranchTarget(addr); + if (sureTarget != INVALIDTARGET && sureTarget < addr) { end = true; } - target = GetJumpTarget(addr); - if (target != INVALIDTARGET && target < addr && ((op&0xFC000000)==0x08000000)) + sureTarget = GetJumpTarget(addr); + if (sureTarget != INVALIDTARGET && sureTarget < addr && ((op&0xFC000000)==0x08000000)) { end = true; } From 66e942c545ab2c679913b597352c0ec394dc9424 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 16:25:05 -0800 Subject: [PATCH 090/276] Fix some "might be null" warnings. --- Core/HLE/sceDisplay.cpp | 9 +++++++-- Core/HLE/sceIo.cpp | 2 +- Core/HLE/sceKernelThread.cpp | 10 +++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index dba162c325..1a36d9130a 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -298,8 +298,13 @@ u32 sceDisplaySetFramebuf() if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { // Write immediately to the current framebuffer parameters - framebuf = fbstate; - gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); + if (topaddr != 0) + { + framebuf = fbstate; + gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); + } + else + WARN_LOG(HLE, "%s: PSP_DISPLAY_SETBUF_IMMEDIATE without topaddr?", __FUNCTION__); } else if (topaddr != 0) { diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index c485ecc999..ce3fbe3915 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -192,7 +192,7 @@ void __IoInit() { } void __IoShutdown() { - + pspFileSystem.UnmountAll(); } u32 sceIoAssign(const char *aliasname, const char *physname, const char *devname, u32 flag) { diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 446fe4a871..113868f9eb 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -845,7 +845,7 @@ void __KernelReSchedule(bool doCallbacks, const char *reason) thread->isProcessingCallbacks = doCallbacks; } __KernelReSchedule(reason); - if (doCallbacks && thread == currentThread) { + if (doCallbacks && thread != NULL && thread == currentThread) { if (thread->isRunning()) { thread->isProcessingCallbacks = false; } @@ -1833,8 +1833,12 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo } if (!called) { - DEBUG_LOG(HLE, "Making mipscall pending on thread"); - thread->pendingMipsCalls.push_back(callId); + if (thread) { + DEBUG_LOG(HLE, "Making mipscall pending on thread"); + thread->pendingMipsCalls.push_back(callId); + } else { + WARN_LOG(HLE, "Ignoring mispcall on NULL/deleted thread"); + } } } From 17750c7c804925f50f4a5df523ce9a6bde75c9ae Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 16:28:55 -0800 Subject: [PATCH 091/276] Need this for the debug build. --- Core/FileSystems/ISOFileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 3578c6246c..a7e7bf01f6 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -16,7 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Globals.h" -#include "Log.h" +#include "Common.h" #include "ISOFileSystem.h" #include #include From 15793fe532f2317de76105c74e2a359326646011 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 16:57:44 -0800 Subject: [PATCH 092/276] More minor static analysis warning fixes. --- Common/ConsoleListener.cpp | 4 +- Common/MemArena.cpp | 2 +- Core/HLE/HLE.cpp | 2 +- GPU/GLES/DisplayListInterpreter.cpp | 2 +- GPU/GLES/VertexDecoder.cpp | 2 +- Windows/EmuThread.cpp | 3 +- Windows/WndMainWindow.cpp | 73 ++++++++++++++--------------- 7 files changed, 43 insertions(+), 45 deletions(-) diff --git a/Common/ConsoleListener.cpp b/Common/ConsoleListener.cpp index 04729985d0..e590d46c15 100644 --- a/Common/ConsoleListener.cpp +++ b/Common/ConsoleListener.cpp @@ -318,9 +318,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) Text += 10; } SetConsoleTextAttribute(hConsole, Color); - size_t len = strlen(Text); - if (Text[len-1] == '\n' && Text[len-1] == '\r') - len--; + size_t len = strlen(Text); WriteConsole(hConsole, Text, (DWORD)len, &cCharsWritten, NULL); #else char ColorAttr[16] = ""; diff --git a/Common/MemArena.cpp b/Common/MemArena.cpp index 22acf02f73..35b5dee794 100644 --- a/Common/MemArena.cpp +++ b/Common/MemArena.cpp @@ -283,7 +283,7 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 int i; for (i = 0; i < num_views; i++) { - const MemoryView &view = views[i]; + const MemoryView &view = views[i]; SKIP(flags, view.flags); if (view.flags & MV_MIRROR_PREVIOUS) { position = last_position; diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 2126ce2024..2290737f36 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -211,7 +211,7 @@ void hleCheckCurrentCallbacks() void hleReSchedule(const char *reason) { _dbg_assert_msg_(HLE, reason != 0, "hleReSchedule: Expecting a valid reason."); - _dbg_assert_msg_(HLE, strlen(reason) < 256, "hleReSchedule: Not too long reason."); + _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "hleReSchedule: Not too long reason."); hleAfterSyscall |= HLE_AFTER_RESCHED; diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index c7317112b9..c0688db195 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -587,7 +587,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_CALL: { u32 retval = dcontext.pc + 4; - if (stackptr == ARRAY_SIZE(stack)) { + if (stackptr == ARRAY_SIZE(stack) - 1) { ERROR_LOG(G3D, "CALL: Stack full!"); } else { stack[stackptr++] = retval; diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index 34bef88276..3a3ffe650c 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -234,7 +234,7 @@ void VertexDecoder::Step_Color5551Morph() const col[0] += w * (cdata & 0x1f) / 31.f; col[1] += w * ((cdata>>5) & 0x1f) / 31.f; col[2] += w * ((cdata>>10) & 0x1f) / 31.f; - col[3] += w * (cdata>>15) ? 1.0f : 0.0f; + col[3] += w * ((cdata>>15) ? 1.0f : 0.0f); } u8 *c = decoded_ + decFmt.c0off; for (int i = 0; i < 4; i++) { diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 4815a26296..f6795df085 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -29,7 +29,8 @@ DWORD TheThread(LPVOID x); void EmuThread_Start(const char *filename) { // _dbg_clear_(); - _tcscpy(fileToStart, filename); + _tcsncpy(fileToStart, filename, sizeof(fileToStart) - 1); + fileToStart[sizeof(fileToStart) - 1] = 0; unsigned int i; emuThread = (HANDLE)_beginthreadex(0,0,(unsigned int (__stdcall *)(void *))TheThread,(LPVOID)0,0,&i); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 90152ccf2b..7e20d7c1cf 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -37,7 +37,7 @@ #endif BOOL g_bFullScreen = FALSE; -RECT rc = {0}; +RECT g_normalRC = {0}; namespace MainWindow { @@ -705,51 +705,50 @@ namespace MainWindow } void _ViewNormal(HWND hWnd) { - // put caption and border styles back - DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE); - DWORD dwNewStyle = dwOldStyle | WS_CAPTION | WS_THICKFRAME; - ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle); + // put caption and border styles back + DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE); + DWORD dwNewStyle = dwOldStyle | WS_CAPTION | WS_THICKFRAME; + ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle); - // put back the menu bar - ::SetMenu(hWnd, menu); + // put back the menu bar + ::SetMenu(hWnd, menu); - // resize to normal view - // NOTE: use SWP_FRAMECHANGED to force redraw non-client - const int x = rc.left; - const int y = rc.top; - const int cx = rc.right - rc.left; - const int cy = rc.bottom - rc.top; - ::SetWindowPos(hWnd, HWND_NOTOPMOST, x, y, cx, cy, SWP_FRAMECHANGED); + // resize to normal view + // NOTE: use SWP_FRAMECHANGED to force redraw non-client + const int x = g_normalRC.left; + const int y = g_normalRC.top; + const int cx = g_normalRC.right - g_normalRC.left; + const int cy = g_normalRC.bottom - g_normalRC.top; + ::SetWindowPos(hWnd, HWND_NOTOPMOST, x, y, cx, cy, SWP_FRAMECHANGED); - // reset full screen indicator - g_bFullScreen = FALSE; + // reset full screen indicator + g_bFullScreen = FALSE; } -void _ViewFullScreen(HWND hWnd) -{ - // keep in mind normal window rectangle - ::GetWindowRect(hWnd, &rc); + void _ViewFullScreen(HWND hWnd) + { + // keep in mind normal window rectangle + ::GetWindowRect(hWnd, &g_normalRC); - // remove caption and border styles - DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE); - DWORD dwNewStyle = dwOldStyle & ~(WS_CAPTION | WS_THICKFRAME); - ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle); + // remove caption and border styles + DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE); + DWORD dwNewStyle = dwOldStyle & ~(WS_CAPTION | WS_THICKFRAME); + ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle); - // remove the menu bar - ::SetMenu(hWnd, NULL); + // remove the menu bar + ::SetMenu(hWnd, NULL); - // resize to full screen view - // NOTE: use SWP_FRAMECHANGED to force redraw non-client - const int x = 0; - const int y = 0; - const int cx = ::GetSystemMetrics(SM_CXSCREEN); - const int cy = ::GetSystemMetrics(SM_CYSCREEN); - ::SetWindowPos(hWnd, HWND_TOPMOST, x, y, cx, cy, SWP_FRAMECHANGED); - - // set full screen indicator - g_bFullScreen = TRUE; -} + // resize to full screen view + // NOTE: use SWP_FRAMECHANGED to force redraw non-client + const int x = 0; + const int y = 0; + const int cx = ::GetSystemMetrics(SM_CXSCREEN); + const int cy = ::GetSystemMetrics(SM_CYSCREEN); + ::SetWindowPos(hWnd, HWND_TOPMOST, x, y, cx, cy, SWP_FRAMECHANGED); + // set full screen indicator + g_bFullScreen = TRUE; + } void SetPlaying(const char *text) { From 8188df4c8a8429ca0a8fe2a09c1983f78523afc0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 17:03:11 -0800 Subject: [PATCH 093/276] Oops, don't think this belongs here after all. --- Core/HLE/sceIo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index ce3fbe3915..941d3a63ef 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -192,7 +192,6 @@ void __IoInit() { } void __IoShutdown() { - pspFileSystem.UnmountAll(); } u32 sceIoAssign(const char *aliasname, const char *physname, const char *devname, u32 flag) { From a72fd769efa36a789a14050455085d25dcc340d3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 21 Dec 2012 20:13:30 -0800 Subject: [PATCH 094/276] Ignore the .lastcodeanalysissucceeded file. --- .gitignore | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 1f0cd120e6..5e6b96b51c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,46 @@ +# For MSVC +*.lastcodeanalysissucceeded *.pdb *.ilk *.obj *.pch -Logs *.log *.dll *.rar *.exe -*.ini *.map *.lib *.user *.sdf *.ncb -Debug -DebugFast -Release *.opensdf *.suo *.aps +*.exp +Debug +DebugFast +Release +Windows/x64 +Windows/ipch + +# For ppsspp.ini, etc. +*.ini + +Logs +Memstick + bin gen libs obj -*.exp +build*/ + .pspsh.hist -GameLogNotes.txt -Windows/x64 -Windows/ipch -Memstick -android/ui_atlas.zim __testoutput.txt __testerror.txt +__testfinish.txt +GameLogNotes.txt + +android/ui_atlas.zim ppge_atlas.zim.png local.properties -build*/ From 47e558d9ce915b202c9925ee19f6622e44430fc3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 01:45:47 -0800 Subject: [PATCH 095/276] Fix specular causing shader to fail to link. --- GPU/GLES/VertexShaderGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 8cd6cafa6a..41dd351bea 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -281,7 +281,7 @@ char *GenerateVertexShader(int prim) const char *ambient = (gstate.materialupdate & 1) ? "unlitColor" : "u_matambientalpha.rgb"; const char *diffuse = (gstate.materialupdate & 2) ? "unlitColor" : "u_matdiffuse"; - const char *specular = (gstate.materialupdate & 4) ? "unlitColor" : "u_matspecular"; + const char *specular = (gstate.materialupdate & 4) ? "unlitColor" : "u_matspecular.rgb"; if (gstate.lightingEnable & 1) { WRITE(p, " vec4 lightSum0 = vec4(0.0);\n"); From 782d15ad1f5af5da42a4648bebba8edab6fa44ed Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 01:50:55 -0800 Subject: [PATCH 096/276] Remove DL flush optimization causing wonky gfx. --- GPU/GLES/DisplayListInterpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index c0688db195..a693b9eb0b 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -1370,7 +1370,7 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff && flushBeforeCommand[cmd]) + if (flushBeforeCommand[cmd]) Flush(); gstate.cmdmem[cmd] = op; From 88f18b09e94506db6a0b859aa511b0a4b4047065 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 07:24:01 -0800 Subject: [PATCH 097/276] Revert incorrect warning fix. --- GPU/GLES/DisplayListInterpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index a693b9eb0b..ebffc37835 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -587,7 +587,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_CALL: { u32 retval = dcontext.pc + 4; - if (stackptr == ARRAY_SIZE(stack) - 1) { + if (stackptr == ARRAY_SIZE(stack)) { ERROR_LOG(G3D, "CALL: Stack full!"); } else { stack[stackptr++] = retval; From 2861a21658fe2780b62f2c19a69373a51116e212 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 5 Dec 2012 23:47:09 -0800 Subject: [PATCH 098/276] Fix a couple typos in headless. --- headless/Headless.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 7510f6527e..dabd2586e7 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -74,8 +74,8 @@ void printUsage(const char *progname, const char *reason) if (reason != NULL) fprintf(stderr, "Error: %s\n\n", reason); fprintf(stderr, "PPSSPP Headless\n"); - fprintf(stderr, "This is primarily meant for non-inactive test tool.\n\n"); - fprintf(stderr, "Usage: %s [options] file.elf\n\n", progname); + fprintf(stderr, "This is primarily meant as a non-interactive test tool.\n\n"); + fprintf(stderr, "Usage: %s file.elf [options]\n\n", progname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -m, --mount umd.cso mount iso on umd:\n"); fprintf(stderr, " -l, --log full log output, not just emulated printfs\n"); From 965592eda8b2a58ae014ea8b71295e74238cfd33 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 09:01:59 -0800 Subject: [PATCH 099/276] Fix sceIoRemove() on Windows infinite looping. --- Core/FileSystems/DirectoryFileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 50bbb11253..3302c266d2 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -92,7 +92,7 @@ bool DirectoryFileSystem::DeleteFile(const std::string &filename) { std::string fullName = GetLocalPath(filename); #ifdef _WIN32 - return DeleteFile(fullName.c_str()) == TRUE; + return ::DeleteFile(fullName.c_str()) == TRUE; #else return 0 == unlink(fullName.c_str()); #endif From d745bddc236afc29d57e4779d51ad43600fedabf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 09:21:23 -0800 Subject: [PATCH 100/276] Enable a few command line switches on Windows. --- Windows/WndMainWindow.cpp | 12 ++++++-- Windows/WndMainWindow.h | 3 ++ Windows/main.cpp | 64 +++++++++++++++++++++++++++++++-------- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 7e20d7c1cf..1309ebddb3 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -46,6 +46,7 @@ namespace MainWindow HWND hwndGameList; HMENU menu; BOOL skinMode = FALSE; + CoreState nextState = CORE_POWERDOWN; HINSTANCE hInst; @@ -244,7 +245,6 @@ namespace MainWindow switch (message) { case WM_CREATE: - PostMessage(hWnd, WM_COMMAND, ID_FILE_LOAD, 0); break; case WM_MOVE: @@ -467,7 +467,7 @@ namespace MainWindow memoryWindow[0]->Show(true); break; case ID_DEBUG_LOG: - LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden()); + LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden()); break; ////////////////////////////////////////////////////////////////////////// @@ -617,6 +617,9 @@ namespace MainWindow disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); + + if (nextState == CORE_RUNNING) + PostMessage(hwndMain, WM_COMMAND, ID_EMULATION_RUN, 0); break; default: @@ -762,6 +765,11 @@ namespace MainWindow } } + void SetNextState(CoreState state) + { + nextState = state; + } + HINSTANCE GetHInstance() { return hInst; diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index 0e01330bc4..7aaaaab423 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace MainWindow { @@ -14,6 +15,8 @@ namespace MainWindow HINSTANCE GetHInstance(); HWND GetDisplayHWND(); void SetPlaying(const char*text); + void BrowseAndBoot(); + void SetNextState(CoreState state); void _ViewFullScreen(HWND hWnd); void _ViewNormal(HWND hWnd); } diff --git a/Windows/main.cpp b/Windows/main.cpp index 1a859b1a89..0facb4845b 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -21,6 +21,7 @@ #include "file/zip_read.h" #include "../Core/Config.h" +#include "EmuThread.h" #include "LogManager.h" #include "ConsoleListener.h" @@ -50,23 +51,51 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin { Common::EnableCrashingOnCrashes(); - char *token = szCmdLine; - char fileToLoad[256] = ""; - - token = strtok(szCmdLine," "); + const char *fileToStart = NULL; + bool showLog = false; + bool autoRun = true; g_Config.Load(); VFSRegister("", new DirectoryAssetReader("assets/")); VFSRegister("", new DirectoryAssetReader("")); - while (token) + for (int i = 1; i < __argc; i++) { - if (strcmp(token,"-run")) - { - //run immediately - } + if (__targv[i][0] == '\0') + continue; - token = strtok(NULL," "); + if (__targv[i][0] == '-') + { + switch (__targv[i][1]) + { + case 'j': + g_Config.iCpuCore = CPU_JIT; + break; + case 'i': + g_Config.iCpuCore = CPU_INTERPRETER; + break; + case 'l': + showLog = true; + break; + case 's': + autoRun = false; + break; + } + } + else if (fileToStart == NULL) + { + fileToStart = __targv[i]; + if (!File::Exists(fileToStart)) + { + fprintf(stderr, "File not found: %s\n", fileToStart); + exit(1); + } + } + else + { + fprintf(stderr, "Can only boot one file"); + exit(1); + } } //Windows, API init stuff @@ -104,10 +133,21 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin #endif LogManager::GetInstance()->GetConsoleListener()->Open(hidden, 150, 120, "PPSSPP Debug Console"); LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); - if (strlen(fileToLoad)) + if (fileToStart != NULL) { - // TODO: load the thing + MainWindow::SetPlaying(fileToStart); + MainWindow::Update(); + MainWindow::UpdateMenus(); + + EmuThread_Start(fileToStart); } + else + MainWindow::BrowseAndBoot(); + + if (showLog) + PostMessage(hwndMain, WM_COMMAND, ID_DEBUG_LOG, 0); + if (autoRun) + MainWindow::SetNextState(CORE_RUNNING); //so.. we're at the message pump of the GUI thread MSG msg; From 7fb65a59977b157e9806206fadd0cc9db1d1ddca Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 09:49:29 -0800 Subject: [PATCH 101/276] Add a switch to Windows to save to a log file. --- Common/CommonPaths.h | 2 +- Common/LogManager.cpp | 25 +++++++++++++++++++++++-- Common/LogManager.h | 2 ++ Windows/main.cpp | 19 ++++++++++++++----- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Common/CommonPaths.h b/Common/CommonPaths.h index 0fdf5f887c..949c8d390b 100644 --- a/Common/CommonPaths.h +++ b/Common/CommonPaths.h @@ -100,7 +100,7 @@ #define LOGGER_CONFIG "Logger.ini" // Files in the directory returned by GetUserPath(D_LOGS_IDX) -#define MAIN_LOG "dolphin.log" +#define MAIN_LOG "ppsspp.log" // Sys files #define TOTALDB "totaldb.dsy" diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp index 0918cebf9d..64da7ff032 100644 --- a/Common/LogManager.cpp +++ b/Common/LogManager.cpp @@ -68,6 +68,8 @@ LogManager::LogManager() m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str()); m_consoleLog = new ConsoleListener(); m_debuggerLog = new DebuggerLogListener(); +#else + m_fileLog = NULL; #endif for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -88,8 +90,9 @@ LogManager::~LogManager() { for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { + if (m_fileLog != NULL) + m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); #if !defined(ANDROID) && !defined(IOS) && !defined(BLACKBERRY) - m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); #endif @@ -97,12 +100,30 @@ LogManager::~LogManager() for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) delete m_Log[i]; + if (m_fileLog != NULL) + delete m_fileLog; #if !defined(ANDROID) && !defined(IOS) && !defined(BLACKBERRY) - delete m_fileLog; delete m_consoleLog; #endif } +void LogManager::ChangeFileLog(const char *filename) +{ + if (m_fileLog != NULL) + { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); + delete m_fileLog; + } + + if (filename != NULL) + { + m_fileLog = new FileLogListener(filename); + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + m_Log[i]->AddListener(m_fileLog); + } +} + void LogManager::SaveConfig(IniFile::Section *section) { for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) diff --git a/Common/LogManager.h b/Common/LogManager.h index 9b6614e696..faef623276 100644 --- a/Common/LogManager.h +++ b/Common/LogManager.h @@ -179,6 +179,8 @@ public: static void Init(); static void Shutdown(); + void ChangeFileLog(const char *filename); + void SaveConfig(IniFile::Section *section); void LoadConfig(IniFile::Section *section); }; diff --git a/Windows/main.cpp b/Windows/main.cpp index 0facb4845b..c840312467 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -52,6 +52,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin Common::EnableCrashingOnCrashes(); const char *fileToStart = NULL; + const char *fileToLog = NULL; bool showLog = false; bool autoRun = true; @@ -59,14 +60,14 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin VFSRegister("", new DirectoryAssetReader("assets/")); VFSRegister("", new DirectoryAssetReader("")); - for (int i = 1; i < __argc; i++) + for (int i = 1; i < __argc; ++i) { - if (__targv[i][0] == '\0') + if (__argv[i][0] == '\0') continue; - if (__targv[i][0] == '-') + if (__argv[i][0] == '-') { - switch (__targv[i][1]) + switch (__argv[i][1]) { case 'j': g_Config.iCpuCore = CPU_JIT; @@ -80,11 +81,17 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin case 's': autoRun = false; break; + case '-': + if (!strcmp(__argv[i], "--log") && i < __argc - 1) + fileToLog = __argv[++i]; + if (!strncmp(__argv[i], "--log=", strlen("--log=")) && strlen(__argv[i]) > strlen("--log=")) + fileToLog = __argv[i] + strlen("--log="); + break; } } else if (fileToStart == NULL) { - fileToStart = __targv[i]; + fileToStart = __argv[i]; if (!File::Exists(fileToStart)) { fprintf(stderr, "File not found: %s\n", fileToStart); @@ -127,6 +134,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin MainWindow::UpdateMenus(); LogManager::Init(); + if (fileToLog != NULL) + LogManager::GetInstance()->ChangeFileLog(fileToLog); bool hidden = false; #ifndef _DEBUG hidden = true; From 7aa7640e879e28a36da8d4b8d550bf488d840fcd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 09:49:59 -0800 Subject: [PATCH 102/276] Add -f switch for parody with Headless. --- Windows/main.cpp | 3 +++ android/jni/NativeApp.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Windows/main.cpp b/Windows/main.cpp index c840312467..b4131d81d9 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -75,6 +75,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin case 'i': g_Config.iCpuCore = CPU_INTERPRETER; break; + case 'f': + g_Config.iCpuCore = CPU_FASTINTERPRETER; + break; case 'l': showLog = true; break; diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 8f6b959cc4..4b749797c1 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -185,6 +185,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co case 'j': g_Config.iCpuCore = CPU_JIT; break; + case 'f': + g_Config.iCpuCore = CPU_FASTINTERPRETER; + break; case 'i': g_Config.iCpuCore = CPU_INTERPRETER; break; From ecffa492f698b5163a8cdee84f77c54cdb4c15ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 09:54:07 -0800 Subject: [PATCH 103/276] Refactor Windows show log switch. --- Windows/main.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Windows/main.cpp b/Windows/main.cpp index b4131d81d9..d2f9b186ac 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -53,9 +53,13 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin const char *fileToStart = NULL; const char *fileToLog = NULL; - bool showLog = false; + bool hideLog = true; bool autoRun = true; +#ifdef _DEBUG + hideLog = false; +#endif + g_Config.Load(); VFSRegister("", new DirectoryAssetReader("assets/")); VFSRegister("", new DirectoryAssetReader("")); @@ -79,7 +83,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin g_Config.iCpuCore = CPU_FASTINTERPRETER; break; case 'l': - showLog = true; + hideLog = false; break; case 's': autoRun = false; @@ -139,11 +143,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin LogManager::Init(); if (fileToLog != NULL) LogManager::GetInstance()->ChangeFileLog(fileToLog); - bool hidden = false; -#ifndef _DEBUG - hidden = true; -#endif - LogManager::GetInstance()->GetConsoleListener()->Open(hidden, 150, 120, "PPSSPP Debug Console"); + LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console"); LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); if (fileToStart != NULL) { @@ -156,8 +156,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin else MainWindow::BrowseAndBoot(); - if (showLog) - PostMessage(hwndMain, WM_COMMAND, ID_DEBUG_LOG, 0); if (autoRun) MainWindow::SetNextState(CORE_RUNNING); From 745ba092c56700a1c43214a32597cb868843d41f Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sat, 22 Dec 2012 19:05:47 +0100 Subject: [PATCH 104/276] merge --- Core/Dialog/SavedataParam.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index ccfa3ff5a9..8f99e0d51f 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -265,7 +265,6 @@ bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) return true; } -<<<<<<< HEAD std::string SavedataParam::GetSpaceText(int size) { char text[50]; @@ -300,10 +299,7 @@ std::string SavedataParam::GetSpaceText(int size) // From my test, PSP only answer with data for save of size 1500 (sdk < 2) // Perhaps changed to use mode 22 id SDK >= 2 // For now we always return results -bool SavedataParam::GetSizes(SceUtilitySavedataParam* param) -======= bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) ->>>>>>> upstream/master { if (!param) { return false; @@ -341,11 +337,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) //return false; } } -<<<<<<< HEAD - if(Memory::IsValidAddress(param->utilityData)) // Calc space required for save -======= if (Memory::IsValidAddress(param->utilityData)) ->>>>>>> upstream/master { int total_size = 0; total_size += getSizeNormalized(1); // SFO; From 154d3aaf6a53d3085c249457046e4e102c1fba2e Mon Sep 17 00:00:00 2001 From: TMaul Date: Sat, 22 Dec 2012 12:25:03 +0000 Subject: [PATCH 105/276] Add sceAtracSetMOutHalfwayBuffer definitiion PLus clean up the font code a tiny bit --- Core/HLE/sceAtrac.cpp | 1 + Core/HLE/sceFont.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6b442be805..aacc12a8eb 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -234,6 +234,7 @@ const HLEFunction sceAtrac3plus[] = {0xeca32a99,0,"sceAtracIsSecondBufferNeeded"}, {0x0fae370e,sceAtracSetHalfwayBufferAndGetID,"sceAtracSetHalfwayBufferAndGetID"}, {0x2DD3E298,0,"sceAtrac3plus_2DD3E298"}, + {0x5CF9D852,0,"sceAtracSetMOutHalfwayBuffer"}, }; diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index d2caefb3ad..5c7f3595c4 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -331,7 +331,10 @@ int sceFontGetFontList(u32 fontLibHandle, u32 fontStylePtr, u32 numFonts) style.fontVRes = 20 / 64.f; style.fontStyle = 1; - Memory::WriteStruct(fontStylePtr, &style); + for (u32 i = 0; i < numFonts; i++) + { + Memory::WriteStruct(fontStylePtr+ (sizeof(style)), &style); + } return 0; } From 2b177e9b6d614587c5b1f64eb2df2efceb4eee68 Mon Sep 17 00:00:00 2001 From: TMaul Date: Sat, 22 Dec 2012 14:09:14 +0000 Subject: [PATCH 106/276] Start making the osk an osk --- Core/Dialog/PSPOskDialog.cpp | 29 ++++++++++++++++++----------- Core/Dialog/PSPOskDialog.h | 3 +++ Core/HLE/sceFont.cpp | 1 - 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 4312295612..640376c2ec 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -141,10 +141,8 @@ SceUtilityOskData oskData; std::string oskDesc; std::string oskIntext; std::string oskOuttext; - int oskParamsAddr; - PSPOskDialog::PSPOskDialog() : PSPDialog() { } @@ -152,7 +150,6 @@ PSPOskDialog::PSPOskDialog() : PSPDialog() { PSPOskDialog::~PSPOskDialog() { } - // Same as get string but read out 16bit void PSPOskDialog::HackyGetStringWide(std::string& _string, const u32 em_address) { @@ -201,6 +198,17 @@ int PSPOskDialog::Init(u32 oskPtr) return 0; } + +void PSPOskDialog::RenderKeyboard() +{ + //First render the characters + for (int i=0; i Date: Sat, 22 Dec 2012 15:11:20 +0000 Subject: [PATCH 107/276] Display 'keys' --- Core/Dialog/PSPOskDialog.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 640376c2ec..b61daddf59 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -143,6 +143,17 @@ std::string oskIntext; std::string oskOuttext; int oskParamsAddr; +#define NUMKEYROWS 4 +#define KEYSPERROW 11 +const char oskKeys[NUMKEYROWS][KEYSPERROW] = +{ + {'1','2','3','4','5','6','7','8','9','0',}, + {'Q','W','E','R','T','Y','U','I','O','P'}, + {'A','S','D','F','G','H','J','K','L'}, + {'Z','X','C','V','B','N','M',}, +}; + + PSPOskDialog::PSPOskDialog() : PSPDialog() { } @@ -201,12 +212,16 @@ int PSPOskDialog::Init(u32 oskPtr) void PSPOskDialog::RenderKeyboard() { - //First render the characters + PPGeDrawText(oskDesc.c_str(), 480/2, 20, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); for (int i=0; i Date: Sat, 22 Dec 2012 15:41:20 +0000 Subject: [PATCH 108/276] Increase font size and spacing --- Core/Dialog/PSPOskDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index b61daddf59..b246f0202d 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -220,7 +220,7 @@ void PSPOskDialog::RenderKeyboard() for (int row = 0; row < NUMKEYROWS; row++) { - PPGeDrawText(oskKeys[row], 20, 60 + (20 * row), NULL , 0.6f, 0xFFFFFFFF); + PPGeDrawText(oskKeys[row], 20, 60 + (25 * row), NULL , 0.6f, 0xFFFFFFFF); } } From 60e831bc8e4c6cba7919a5eb6a6738869a083679 Mon Sep 17 00:00:00 2001 From: TMaul Date: Sat, 22 Dec 2012 18:19:50 +0000 Subject: [PATCH 109/276] Make OSK work But it's kind of horriffic --- Core/Dialog/PSPOskDialog.cpp | 122 ++++++++++++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 10 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index b246f0202d..bdf15883f6 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -143,19 +143,26 @@ std::string oskIntext; std::string oskOuttext; int oskParamsAddr; +char inputChars[255]; // must be a better way of doing this... +int currentInputChar; +int selectedChar; + #define NUMKEYROWS 4 -#define KEYSPERROW 11 +#define KEYSPERROW 13 const char oskKeys[NUMKEYROWS][KEYSPERROW] = { - {'1','2','3','4','5','6','7','8','9','0',}, - {'Q','W','E','R','T','Y','U','I','O','P'}, - {'A','S','D','F','G','H','J','K','L'}, - {'Z','X','C','V','B','N','M',}, + {'1','2','3','4','5','6','7','8','9','0','-','+','\0'}, + {'Q','W','E','R','T','Y','U','I','O','P','[',']','\0'}, + {'A','S','D','F','G','H','J','K','L',';','@','~','\0'}, + {'Z','X','C','V','B','N','M',',','.','/','?','\\','\0'}, }; -PSPOskDialog::PSPOskDialog() : PSPDialog() { +PSPOskDialog::PSPOskDialog() : PSPDialog() { + selectedChar = 15; + currentInputChar = 0; + memset(inputChars, 0x00, sizeof(inputChars)); } PSPOskDialog::~PSPOskDialog() { @@ -212,21 +219,68 @@ int PSPOskDialog::Init(u32 oskPtr) void PSPOskDialog::RenderKeyboard() { + int selectedRow = selectedChar / (KEYSPERROW-1); + int selectedExtra = selectedChar % (KEYSPERROW-1); + char SelectedLine[KEYSPERROW]; + PPGeDrawText(oskDesc.c_str(), 480/2, 20, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); for (int i=0; i 44) + { + selectedChar = 0; + } + + + // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) + { + if (currentInputChar < oskData.outtextlimit) + { + inputChars[currentInputChar]= oskKeys[selectedRow][selectedExtra]; + currentInputChar++; + } + else + { + currentInputChar = oskData.outtextlimit; // just in case + } + } + else if (IsButtonPressed(CTRL_CIRCLE)) + { + inputChars[currentInputChar] = 0x00; + currentInputChar--; + } + else if (IsButtonPressed(CTRL_START)) { status = SCE_UTILITY_STATUS_FINISHED; } + + EndDraw(); } else if (status == SCE_UTILITY_STATUS_FINISHED) { status = SCE_UTILITY_STATUS_SHUTDOWN; } - // just fake the return values to be "000000" as this will work for most cases e.g. when restricted to entering just numbers for (int i=0; i Date: Sat, 22 Dec 2012 18:34:52 +0000 Subject: [PATCH 110/276] Clean up OSK instructions --- Core/Dialog/PSPOskDialog.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index bdf15883f6..85c66c07d2 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -290,8 +290,16 @@ void PSPOskDialog::Update() { StartDraw(); RenderKeyboard(); - PPGeDrawImage(I_CROSS, 200, 220, 20, 20, 0, 0xFFFFFFFF); - PPGeDrawText("Ignore", 230, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); + PPGeDrawImage(I_CROSS, 100, 220, 20, 20, 0, 0xFFFFFFFF); + PPGeDrawText("Select", 130, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); + + PPGeDrawImage(I_CIRCLE, 200, 220, 20, 20, 0, 0xFFFFFFFF); + PPGeDrawText("Delete", 230, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); + + PPGeDrawImage(I_BUTTON, 290, 220, 50, 20, 0, 0xFFFFFFFF); + PPGeDrawText("Start", 305, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); + PPGeDrawText("Finish", 350, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); + if (IsButtonPressed(CTRL_UP)) { From d5dd6881d702b3a8fed7688fcf7ac09bfb8bfaf5 Mon Sep 17 00:00:00 2001 From: TMaul Date: Sat, 22 Dec 2012 18:40:05 +0000 Subject: [PATCH 111/276] Fix returned value length --- Core/Dialog/PSPOskDialog.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 85c66c07d2..b7fa333741 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -281,7 +281,6 @@ void PSPOskDialog::Update() int selectedRow = selectedChar / (KEYSPERROW-1); int selectedExtra = selectedChar % (KEYSPERROW-1); - //__UtilityUpdate(); if (status == SCE_UTILITY_STATUS_INITIALIZE) { status = SCE_UTILITY_STATUS_RUNNING; @@ -327,9 +326,6 @@ void PSPOskDialog::Update() { selectedChar = 0; } - - - // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) { @@ -352,20 +348,19 @@ void PSPOskDialog::Update() { status = SCE_UTILITY_STATUS_FINISHED; } - - EndDraw(); } else if (status == SCE_UTILITY_STATUS_FINISHED) { status = SCE_UTILITY_STATUS_SHUTDOWN; } + for (int i=0; i Date: Sat, 22 Dec 2012 19:55:44 +0000 Subject: [PATCH 112/276] Clean up OSK code Remove some magic numbers and a few other things --- Core/Dialog/PSPOskDialog.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index b7fa333741..c5e8cb6380 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -149,6 +149,7 @@ int selectedChar; #define NUMKEYROWS 4 #define KEYSPERROW 13 +#define NUMBEROFVALIDCHARS 44 const char oskKeys[NUMKEYROWS][KEYSPERROW] = { {'1','2','3','4','5','6','7','8','9','0','-','+','\0'}, @@ -160,9 +161,7 @@ const char oskKeys[NUMKEYROWS][KEYSPERROW] = PSPOskDialog::PSPOskDialog() : PSPDialog() { - selectedChar = 15; - currentInputChar = 0; - memset(inputChars, 0x00, sizeof(inputChars)); + } PSPOskDialog::~PSPOskDialog() { @@ -196,7 +195,12 @@ int PSPOskDialog::Init(u32 oskPtr) memset(&oskParams, 0, sizeof(oskParams)); memset(&oskData, 0, sizeof(oskData)); + // TODO: should this be init'd to oskIntext? + memset(inputChars, 0x00, sizeof(inputChars)); oskParamsAddr = oskPtr; + selectedChar = 0; + currentInputChar = 0; + if (Memory::IsValidAddress(oskPtr)) { Memory::ReadStruct(oskPtr, &oskParams); @@ -212,7 +216,6 @@ int PSPOskDialog::Init(u32 oskPtr) return -1; } - return 0; } @@ -244,7 +247,6 @@ void PSPOskDialog::RenderKeyboard() } } } - for (int row = 0; row < NUMKEYROWS; row++) { if (selectedRow == row) @@ -256,9 +258,6 @@ void PSPOskDialog::RenderKeyboard() PPGeDrawText(oskKeys[row], 20, 70 + (25 * row), NULL , 0.6f, 0xFFFFFFFF); } } - - - for (int selectedItemCounter = 0; selectedItemCounter < KEYSPERROW; selectedItemCounter++ ) { if (selectedItemCounter!=selectedExtra) @@ -299,7 +298,6 @@ void PSPOskDialog::Update() PPGeDrawText("Start", 305, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); PPGeDrawText("Finish", 350, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); - if (IsButtonPressed(CTRL_UP)) { selectedChar += 10; @@ -319,13 +317,13 @@ void PSPOskDialog::Update() if (selectedChar < 0) { - selectedChar = 44; + selectedChar = NUMBEROFVALIDCHARS; } - - if (selectedChar > 44) + if (selectedChar > NUMBEROFVALIDCHARS) { selectedChar = 0; } + // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) { From 8586bb30b6309d51b6983541710233bc4828424c Mon Sep 17 00:00:00 2001 From: TMaul Date: Sat, 22 Dec 2012 19:58:47 +0000 Subject: [PATCH 113/276] Make some vars class members --- Core/Dialog/PSPOskDialog.cpp | 129 ---------------------------------- Core/Dialog/PSPOskDialog.h | 130 +++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 129 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index c5e8cb6380..55bbe101cc 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -19,134 +19,6 @@ #include "../Util/PPGeDraw.h" #include "../HLE/sceCtrl.h" - -/** - * Enumeration for input language - */ -enum SceUtilityOskInputLanguage -{ - PSP_UTILITY_OSK_LANGUAGE_DEFAULT = 0x00, - PSP_UTILITY_OSK_LANGUAGE_JAPANESE = 0x01, - PSP_UTILITY_OSK_LANGUAGE_ENGLISH = 0x02, - PSP_UTILITY_OSK_LANGUAGE_FRENCH = 0x03, - PSP_UTILITY_OSK_LANGUAGE_SPANISH = 0x04, - PSP_UTILITY_OSK_LANGUAGE_GERMAN = 0x05, - PSP_UTILITY_OSK_LANGUAGE_ITALIAN = 0x06, - PSP_UTILITY_OSK_LANGUAGE_DUTCH = 0x07, - PSP_UTILITY_OSK_LANGUAGE_PORTUGESE = 0x08, - PSP_UTILITY_OSK_LANGUAGE_RUSSIAN = 0x09, - PSP_UTILITY_OSK_LANGUAGE_KOREAN = 0x0a -}; - -/** - * Enumeration for OSK internal state - */ -enum SceUtilityOskState -{ - PSP_UTILITY_OSK_DIALOG_NONE = 0, /**< No OSK is currently active */ - PSP_UTILITY_OSK_DIALOG_INITING, /**< The OSK is currently being initialized */ - PSP_UTILITY_OSK_DIALOG_INITED, /**< The OSK is initialised */ - PSP_UTILITY_OSK_DIALOG_VISIBLE, /**< The OSK is visible and ready for use */ - PSP_UTILITY_OSK_DIALOG_QUIT, /**< The OSK has been cancelled and should be shut down */ - PSP_UTILITY_OSK_DIALOG_FINISHED /**< The OSK has successfully shut down */ -}; - -/** - * Enumeration for OSK field results - */ -enum SceUtilityOskResult -{ - PSP_UTILITY_OSK_RESULT_UNCHANGED = 0, - PSP_UTILITY_OSK_RESULT_CANCELLED, - PSP_UTILITY_OSK_RESULT_CHANGED -}; - -/** - * Enumeration for input types (these are limited by initial choice of language) - */ -enum SceUtilityOskInputType -{ - PSP_UTILITY_OSK_INPUTTYPE_ALL = 0x00000000, - PSP_UTILITY_OSK_INPUTTYPE_LATIN_DIGIT = 0x00000001, - PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL = 0x00000002, - PSP_UTILITY_OSK_INPUTTYPE_LATIN_LOWERCASE = 0x00000004, - PSP_UTILITY_OSK_INPUTTYPE_LATIN_UPPERCASE = 0x00000008, - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_DIGIT = 0x00000100, - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_SYMBOL = 0x00000200, - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_LOWERCASE = 0x00000400, - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_UPPERCASE = 0x00000800, - // http://en.wikipedia.org/wiki/Hiragana - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HIRAGANA = 0x00001000, - // http://en.wikipedia.org/wiki/Katakana - // Half-width Katakana - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HALF_KATAKANA = 0x00002000, - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_KATAKANA = 0x00004000, - // http://en.wikipedia.org/wiki/Kanji - PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_KANJI = 0x00008000, - PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_LOWERCASE = 0x00010000, - PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_UPPERCASE = 0x00020000, - PSP_UTILITY_OSK_INPUTTYPE_KOREAN = 0x00040000, - PSP_UTILITY_OSK_INPUTTYPE_URL = 0x00080000 -}; - -/** - * OSK Field data - */ -typedef struct _SceUtilityOskData -{ - /** Unknown. Pass 0. */ - int unk_00; - /** Unknown. Pass 0. */ - int unk_04; - /** One of ::SceUtilityOskInputLanguage */ - int language; - /** Unknown. Pass 0. */ - int unk_12; - /** One or more of ::SceUtilityOskInputType (types that are selectable by pressing SELECT) */ - int inputtype; - /** Number of lines */ - int lines; - /** Unknown. Pass 0. */ - int unk_24; - /** Description text */ - u32 descPtr; - /** Initial text */ - u32 intextPtr; - /** Length of output text */ - int outtextlength; - /** Pointer to the output text */ - u32 outtextPtr; - /** Result. One of ::SceUtilityOskResult */ - int result; - /** The max text that can be input */ - int outtextlimit; - -} SceUtilityOskData; - -/** - * OSK parameters - */ -typedef struct _SceUtilityOskParams -{ - pspUtilityDialogCommon base; - int datacount; /** Number of input fields */ - u32 SceUtilityOskDataPtr; /** Pointer to the start of the data for the input fields */ - int state; /** The local OSK state, one of ::SceUtilityOskState */ - int unk_60;/** Unknown. Pass 0 */ - -} SceUtilityOskParams; - -SceUtilityOskParams oskParams; -SceUtilityOskData oskData; -std::string oskDesc; -std::string oskIntext; -std::string oskOuttext; -int oskParamsAddr; - -char inputChars[255]; // must be a better way of doing this... -int currentInputChar; -int selectedChar; - #define NUMKEYROWS 4 #define KEYSPERROW 13 #define NUMBEROFVALIDCHARS 44 @@ -159,7 +31,6 @@ const char oskKeys[NUMKEYROWS][KEYSPERROW] = }; - PSPOskDialog::PSPOskDialog() : PSPDialog() { } diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h index c845474a37..3527bd1c38 100644 --- a/Core/Dialog/PSPOskDialog.h +++ b/Core/Dialog/PSPOskDialog.h @@ -19,6 +19,126 @@ #include "PSPDialog.h" #include "../Core/MemMap.h" + + + +/** +* Enumeration for input language +*/ +enum SceUtilityOskInputLanguage +{ + PSP_UTILITY_OSK_LANGUAGE_DEFAULT = 0x00, + PSP_UTILITY_OSK_LANGUAGE_JAPANESE = 0x01, + PSP_UTILITY_OSK_LANGUAGE_ENGLISH = 0x02, + PSP_UTILITY_OSK_LANGUAGE_FRENCH = 0x03, + PSP_UTILITY_OSK_LANGUAGE_SPANISH = 0x04, + PSP_UTILITY_OSK_LANGUAGE_GERMAN = 0x05, + PSP_UTILITY_OSK_LANGUAGE_ITALIAN = 0x06, + PSP_UTILITY_OSK_LANGUAGE_DUTCH = 0x07, + PSP_UTILITY_OSK_LANGUAGE_PORTUGESE = 0x08, + PSP_UTILITY_OSK_LANGUAGE_RUSSIAN = 0x09, + PSP_UTILITY_OSK_LANGUAGE_KOREAN = 0x0a +}; + +/** +* Enumeration for OSK internal state +*/ +enum SceUtilityOskState +{ + PSP_UTILITY_OSK_DIALOG_NONE = 0, /**< No OSK is currently active */ + PSP_UTILITY_OSK_DIALOG_INITING, /**< The OSK is currently being initialized */ + PSP_UTILITY_OSK_DIALOG_INITED, /**< The OSK is initialised */ + PSP_UTILITY_OSK_DIALOG_VISIBLE, /**< The OSK is visible and ready for use */ + PSP_UTILITY_OSK_DIALOG_QUIT, /**< The OSK has been cancelled and should be shut down */ + PSP_UTILITY_OSK_DIALOG_FINISHED /**< The OSK has successfully shut down */ +}; + +/** +* Enumeration for OSK field results +*/ +enum SceUtilityOskResult +{ + PSP_UTILITY_OSK_RESULT_UNCHANGED = 0, + PSP_UTILITY_OSK_RESULT_CANCELLED, + PSP_UTILITY_OSK_RESULT_CHANGED +}; + +/** +* Enumeration for input types (these are limited by initial choice of language) +*/ +enum SceUtilityOskInputType +{ + PSP_UTILITY_OSK_INPUTTYPE_ALL = 0x00000000, + PSP_UTILITY_OSK_INPUTTYPE_LATIN_DIGIT = 0x00000001, + PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL = 0x00000002, + PSP_UTILITY_OSK_INPUTTYPE_LATIN_LOWERCASE = 0x00000004, + PSP_UTILITY_OSK_INPUTTYPE_LATIN_UPPERCASE = 0x00000008, + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_DIGIT = 0x00000100, + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_SYMBOL = 0x00000200, + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_LOWERCASE = 0x00000400, + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_UPPERCASE = 0x00000800, + // http://en.wikipedia.org/wiki/Hiragana + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HIRAGANA = 0x00001000, + // http://en.wikipedia.org/wiki/Katakana + // Half-width Katakana + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HALF_KATAKANA = 0x00002000, + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_KATAKANA = 0x00004000, + // http://en.wikipedia.org/wiki/Kanji + PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_KANJI = 0x00008000, + PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_LOWERCASE = 0x00010000, + PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_UPPERCASE = 0x00020000, + PSP_UTILITY_OSK_INPUTTYPE_KOREAN = 0x00040000, + PSP_UTILITY_OSK_INPUTTYPE_URL = 0x00080000 +}; + +/** +* OSK Field data +*/ +typedef struct _SceUtilityOskData +{ + /** Unknown. Pass 0. */ + int unk_00; + /** Unknown. Pass 0. */ + int unk_04; + /** One of ::SceUtilityOskInputLanguage */ + int language; + /** Unknown. Pass 0. */ + int unk_12; + /** One or more of ::SceUtilityOskInputType (types that are selectable by pressing SELECT) */ + int inputtype; + /** Number of lines */ + int lines; + /** Unknown. Pass 0. */ + int unk_24; + /** Description text */ + u32 descPtr; + /** Initial text */ + u32 intextPtr; + /** Length of output text */ + int outtextlength; + /** Pointer to the output text */ + u32 outtextPtr; + /** Result. One of ::SceUtilityOskResult */ + int result; + /** The max text that can be input */ + int outtextlimit; + +} SceUtilityOskData; + +/** +* OSK parameters +*/ +typedef struct _SceUtilityOskParams +{ + pspUtilityDialogCommon base; + int datacount; /** Number of input fields */ + u32 SceUtilityOskDataPtr; /** Pointer to the start of the data for the input fields */ + int state; /** The local OSK state, one of ::SceUtilityOskState */ + int unk_60;/** Unknown. Pass 0 */ + +} SceUtilityOskParams; + + class PSPOskDialog: public PSPDialog { public: PSPOskDialog(); @@ -30,6 +150,16 @@ private: void HackyGetStringWide(std::string& _string, const u32 em_address); void RenderKeyboard(); + SceUtilityOskParams oskParams; + SceUtilityOskData oskData; + std::string oskDesc; + std::string oskIntext; + std::string oskOuttext; + int oskParamsAddr; + + char inputChars[255]; // must be a better way of doing this... + int currentInputChar; + int selectedChar; }; From 15018ca4a5645c493ecf8894743afb5e07fa42f9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 18:30:14 -0800 Subject: [PATCH 114/276] Stub out the sceCtrl idle cancel funcs. --- Core/HLE/sceCtrl.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 73e03def9d..c5881219f0 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -297,6 +297,7 @@ u32 sceCtrlSetSamplingMode(u32 mode) int sceCtrlGetSamplingMode(u32 modePtr) { u32 retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL; + DEBUG_LOG(HLE, "%d=sceCtrlGetSamplingMode(%i)", retVal); if (Memory::IsValidAddress(modePtr)) Memory::Write_U32(retVal, modePtr); @@ -304,10 +305,16 @@ int sceCtrlGetSamplingMode(u32 modePtr) return 0; } -void sceCtrlSetIdleCancelThreshold() +int sceCtrlSetIdleCancelThreshold(int idleReset, int idleBack) { - ERROR_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceCtrlSetIdleCancelThreshold(%d, %d)", idleReset, idleBack); + return 0; +} + +int sceCtrlGetIdleCancelThreshold(u32 idleResetPtr, u32 idleBackPtr) +{ + ERROR_LOG(HLE, "UNIMPL sceCtrlSetIdleCancelThreshold(%08x, %08x)", idleResetPtr, idleBackPtr); + return 0; } void sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) @@ -393,8 +400,8 @@ static const HLEFunction sceCtrl[] = {0xAF5960F3, 0, "sceCtrl_AF5960F3"}, {0xA68FD260, 0, "sceCtrlClearRapidFire"}, {0x6841BE1A, 0, "sceCtrlSetRapidFire"}, - {0xa7144800, WrapV_V, "sceCtrlSetIdleCancelThreshold"}, - {0x687660fa, 0, "sceCtrlGetIdleCancelThreshold"}, + {0xa7144800, WrapI_II, "sceCtrlSetIdleCancelThreshold"}, + {0x687660fa, WrapI_UU, "sceCtrlGetIdleCancelThreshold"}, }; void Register_sceCtrl() From 91e1cb74087f807c46dbc5b3a8c62ff7556a7260 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 18:41:49 -0800 Subject: [PATCH 115/276] Implement sceCtrl*IdleCancelThreshold(). --- Core/HLE/sceCtrl.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index c5881219f0..8c9c1f28bf 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -33,6 +33,7 @@ const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; const int PSP_CTRL_ERROR_INVALID_NUM_BUFFERS = 0x80000104; +const int PSP_CTRL_ERROR_INVALID_IDLE_PTR = 0x80000023; const int NUM_CTRL_BUFFERS = 64; @@ -72,6 +73,9 @@ static int ctrlBuf = 0; static int ctrlBufRead = 0; static CtrlLatch latch; +static int ctrlIdleReset = -1; +static int ctrlIdleBack = -1; + static std::vector waitingThreads; static std::recursive_mutex ctrlMutex; @@ -307,13 +311,30 @@ int sceCtrlGetSamplingMode(u32 modePtr) int sceCtrlSetIdleCancelThreshold(int idleReset, int idleBack) { - ERROR_LOG(HLE, "UNIMPL sceCtrlSetIdleCancelThreshold(%d, %d)", idleReset, idleBack); + DEBUG_LOG(HLE, "FAKE sceCtrlSetIdleCancelThreshold(%d, %d)", idleReset, idleBack); + + if (idleReset < -1 || idleBack < -1 || idleReset > 128 || idleBack > 128) + return SCE_KERNEL_ERROR_INVALID_VALUE; + + ctrlIdleReset = idleReset; + ctrlIdleBack = idleBack; return 0; } int sceCtrlGetIdleCancelThreshold(u32 idleResetPtr, u32 idleBackPtr) { - ERROR_LOG(HLE, "UNIMPL sceCtrlSetIdleCancelThreshold(%08x, %08x)", idleResetPtr, idleBackPtr); + DEBUG_LOG(HLE, "sceCtrlSetIdleCancelThreshold(%08x, %08x)", idleResetPtr, idleBackPtr); + + if (idleResetPtr && !Memory::IsValidAddress(idleResetPtr)) + return PSP_CTRL_ERROR_INVALID_IDLE_PTR; + if (idleBackPtr && !Memory::IsValidAddress(idleBackPtr)) + return PSP_CTRL_ERROR_INVALID_IDLE_PTR; + + if (idleResetPtr) + Memory::Write_U32(ctrlIdleReset, idleResetPtr); + if (idleBackPtr) + Memory::Write_U32(ctrlIdleBack, idleBackPtr); + return 0; } From 6ad3c2d4541838856c07135afcfb67ce2d2ab5b9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 19:37:18 -0800 Subject: [PATCH 116/276] Make sure ctrl resets properly on game close/open. --- Core/HLE/sceCtrl.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 8c9c1f28bf..ca6bf486a4 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -255,14 +255,11 @@ void __CtrlInit() for (int i = 0; i < NUM_CTRL_BUFFERS; i++) memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data)); -} -void sceCtrlInit() -{ - __CtrlInit(); + ctrlIdleReset = -1; + ctrlIdleBack = -1; - DEBUG_LOG(HLE,"sceCtrlInit"); - RETURN(0); + waitingThreads.clear(); } u32 sceCtrlSetSamplingCycle(u32 cycle) @@ -406,7 +403,7 @@ u32 sceCtrlReadLatch(u32 latchDataPtr) static const HLEFunction sceCtrl[] = { - {0x3E65A0EA, WrapV_V, "sceCtrlInit"}, //(int unknown), init with 0 + {0x3E65A0EA, 0, "sceCtrlInit"}, //(int unknown), init with 0 {0x1f4011e6, WrapU_U, "sceCtrlSetSamplingMode"}, //(int on); {0x6A2774F3, WrapU_U, "sceCtrlSetSamplingCycle"}, {0x02BAAD91, WrapI_U,"sceCtrlGetSamplingCycle"}, From 8839516c1ecf36c890ce844fbeb1569d0092722d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 20:31:22 -0800 Subject: [PATCH 117/276] Implement sceCtrlGetSamplingCycle(). --- Core/HLE/sceCtrl.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index ca6bf486a4..bfce13d43b 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -76,6 +76,8 @@ static CtrlLatch latch; static int ctrlIdleReset = -1; static int ctrlIdleBack = -1; +static u32 ctrlCycle = 0; + static std::vector waitingThreads; static std::recursive_mutex ctrlMutex; @@ -258,27 +260,40 @@ void __CtrlInit() ctrlIdleReset = -1; ctrlIdleBack = -1; + ctrlCycle = 0; waitingThreads.clear(); } u32 sceCtrlSetSamplingCycle(u32 cycle) { + WARN_LOG(HLE, "FAKE sceCtrlSetSamplingCycle(%u)", cycle); + + if ((cycle > 0 && cycle < 5555) || cycle > 20000) + { + WARN_LOG(HLE, "SCE_KERNEL_ERROR_INVALID_VALUE=sceCtrlSetSamplingCycle(%u)", cycle); + return SCE_KERNEL_ERROR_INVALID_VALUE; + } + + u32 prev = ctrlCycle; + ctrlCycle = cycle; + if (cycle == 0) { - // TODO: Change to vblank when we support something else. - DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%u)", cycle); + // TODO: Cancel the timer. } else { - ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%u)", cycle); + // TODO: Setup the timer. } - return 0; + return prev; } int sceCtrlGetSamplingCycle(u32 cyclePtr) { - ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%08x)", cyclePtr); + DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%08x)", cyclePtr); + if (Memory::IsValidAddress(cyclePtr)) + Memory::Write_U32(ctrlCycle, cyclePtr); return 0; } From bbd7710234c0b0a67541d576284813fa8eb27728 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 21:23:28 -0800 Subject: [PATCH 118/276] Implement sceCtrlGetSamplingCycle() freq changes. --- Core/HLE/sceCtrl.cpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index bfce13d43b..19de18d557 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -76,11 +76,13 @@ static CtrlLatch latch; static int ctrlIdleReset = -1; static int ctrlIdleBack = -1; -static u32 ctrlCycle = 0; +static int ctrlCycle = 0; static std::vector waitingThreads; static std::recursive_mutex ctrlMutex; +static int ctrlTimer = -1; + // STATE END ////////////////////////////////////////////////////////////////////////// @@ -208,9 +210,9 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) return done; } -void __CtrlVblank() +void __CtrlDoSample() { - // When in vblank sampling mode, this samples the ctrl data into the buffers and updates the latch. + // This samples the ctrl data into the buffers and updates the latch. __CtrlUpdateLatch(); // Wake up a single thread that was waiting for the buffer. @@ -232,6 +234,22 @@ retry: } } +void __CtrlVblank() +{ + // This always runs, so make sure we're in vblank mode. + if (ctrlCycle == 0) + __CtrlDoSample(); +} + +void __CtrlTimerUpdate(u64 userdata, int cyclesLate) +{ + // This only runs in timer mode (ctrlCycle > 0.) + _dbg_assert_msg_(HLE, ctrlCycle > 0, "Ctrl: sampling cycle should be > 0"); + + __CtrlDoSample(); + CoreTiming::ScheduleEvent(usToCycles(ctrlCycle), ctrlTimer, 0); +} + void __CtrlInit() { std::lock_guard guard(ctrlMutex); @@ -263,11 +281,13 @@ void __CtrlInit() ctrlCycle = 0; waitingThreads.clear(); + + ctrlTimer = CoreTiming::RegisterEvent("CtrlSampleTimer", __CtrlTimerUpdate); } u32 sceCtrlSetSamplingCycle(u32 cycle) { - WARN_LOG(HLE, "FAKE sceCtrlSetSamplingCycle(%u)", cycle); + DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%u)", cycle); if ((cycle > 0 && cycle < 5555) || cycle > 20000) { @@ -278,14 +298,11 @@ u32 sceCtrlSetSamplingCycle(u32 cycle) u32 prev = ctrlCycle; ctrlCycle = cycle; - if (cycle == 0) - { - // TODO: Cancel the timer. - } - else - { - // TODO: Setup the timer. - } + if (prev > 0) + CoreTiming::UnscheduleEvent(ctrlTimer, 0); + if (cycle > 0) + CoreTiming::ScheduleEvent(usToCycles(ctrlCycle), ctrlTimer, 0); + return prev; } From 13389437d30dde14026ca35634074624dd018f88 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 21:28:01 -0800 Subject: [PATCH 119/276] Update tests. --- pspautotests | 2 +- test.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pspautotests b/pspautotests index 54acddd544..9ea2847b5e 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 54acddd54469a88aadbaf0e69088aad504b5e1e4 +Subproject commit 9ea2847b5e793b9fae8ccd81f25cc8e4f6a81d7d diff --git a/test.py b/test.py index f352ccf50f..2e1248690b 100755 --- a/test.py +++ b/test.py @@ -49,7 +49,9 @@ tests_good = [ "cpu/fpu/fpu", "ctrl/ctrl", + "ctrl/idle/idle", "ctrl/sampling/sampling", + "ctrl/sampling2/sampling2", "display/display", "dmac/dmactest", "loader/bss/bss", From 4bc06562d63acc6128c8f6299fb734aa14b04120 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 22 Dec 2012 22:41:51 -0800 Subject: [PATCH 120/276] Move OSK inputChars to global, fixes release crash. Also, assorted potential crash fixes / etc. --- Core/Dialog/PSPOskDialog.cpp | 71 ++++++++++++++++++++++-------------- Core/Dialog/PSPOskDialog.h | 1 - 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 55bbe101cc..d0eba108d4 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -30,6 +30,8 @@ const char oskKeys[NUMKEYROWS][KEYSPERROW] = {'Z','X','C','V','B','N','M',',','.','/','?','\\','\0'}, }; +char inputChars[255]; // must be a better way of doing this... + PSPOskDialog::PSPOskDialog() : PSPDialog() { @@ -81,6 +83,13 @@ int PSPOskDialog::Init(u32 oskPtr) HackyGetStringWide(oskOuttext, oskData.outtextPtr); Memory::WriteStruct(oskParams.SceUtilityOskDataPtr, &oskData); Memory::WriteStruct(oskPtr, &oskParams); + + if (oskData.outtextlimit >= sizeof(inputChars)) + { + // TODO: Check actual behavior. + ERROR_LOG(HLE, "OskDialog requested %d characters, failing", oskData.outtextlimit); + return -1; + } } else { @@ -97,37 +106,36 @@ void PSPOskDialog::RenderKeyboard() int selectedExtra = selectedChar % (KEYSPERROW-1); char SelectedLine[KEYSPERROW]; + char temp[2]; + temp[1] = '\0'; + + int limit = oskData.outtextlimit; + // TODO: Test more thoroughly. Encountered a game where this was 0. + if (limit <= 0) + limit = 16; + PPGeDrawText(oskDesc.c_str(), 480/2, 20, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); - for (int i=0; i 0) + { + inputChars[currentInputChar] = 0x00; + currentInputChar--; + } } else if (IsButtonPressed(CTRL_START)) { @@ -224,7 +241,7 @@ void PSPOskDialog::Update() status = SCE_UTILITY_STATUS_SHUTDOWN; } - for (int i=0; i Date: Sat, 22 Dec 2012 22:57:56 -0800 Subject: [PATCH 121/276] Oops, forgot to add one here. --- Core/Dialog/PSPOskDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index d0eba108d4..e4cc8331cb 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -104,7 +104,7 @@ void PSPOskDialog::RenderKeyboard() { int selectedRow = selectedChar / (KEYSPERROW-1); int selectedExtra = selectedChar % (KEYSPERROW-1); - char SelectedLine[KEYSPERROW]; + char SelectedLine[KEYSPERROW + 1]; char temp[2]; temp[1] = '\0'; From f57e78c324d20a818bdf156bcc8308bc99afd9d5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 22 Dec 2012 19:12:12 +1000 Subject: [PATCH 122/276] Update Qt: IndexGenerator{.cpp,.h} --- Qt/Core.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Qt/Core.pro b/Qt/Core.pro index d5c1c384e9..95cefa9a4b 100755 --- a/Qt/Core.pro +++ b/Qt/Core.pro @@ -109,6 +109,7 @@ SOURCES += ../Core/MIPS/ARM/Asm.cpp \ #CoreARM ../GPU/GLES/DisplayListInterpreter.cpp \ ../GPU/GLES/FragmentShaderGenerator.cpp \ ../GPU/GLES/Framebuffer.cpp \ + ../GPU/GLES/IndexGenerator.cpp \ ../GPU/GLES/ShaderManager.cpp \ ../GPU/GLES/StateMapping.cpp \ ../GPU/GLES/TextureCache.cpp \ @@ -219,6 +220,7 @@ HEADERS += ../Core/MIPS/ARM/Asm.h \ ../GPU/GLES/DisplayListInterpreter.h \ ../GPU/GLES/FragmentShaderGenerator.h \ ../GPU/GLES/Framebuffer.h \ + ../GPU/GLES/IndexGenerator.h \ ../GPU/GLES/ShaderManager.h \ ../GPU/GLES/StateMapping.h \ ../GPU/GLES/TextureCache.h \ From f870b19cbbba12895d793f252adc2e7c1c5151eb Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 23 Dec 2012 17:46:44 +1000 Subject: [PATCH 123/276] Support x86 arch and Windows(untested), Linux platforms with Qt frontend --- Qt/Common.pro | 128 +++++++------ Qt/Core.pro | 476 ++++++++++++++++++++++++------------------------ Qt/Native.pro | 318 ++++++++++++++++---------------- Qt/PPSSPP.pro | 47 +++-- Qt/Settings.pri | 31 ++++ 5 files changed, 525 insertions(+), 475 deletions(-) create mode 100644 Qt/Settings.pri diff --git a/Qt/Common.pro b/Qt/Common.pro index 350da2f1ab..7817c8ab3e 100755 --- a/Qt/Common.pro +++ b/Qt/Common.pro @@ -4,65 +4,75 @@ TARGET = Common TEMPLATE = lib CONFIG += staticlib -blackberry: { - QMAKE_CC = ntoarmv7-gcc - QMAKE_CXX = ntoarmv7-g++ - DEFINES += "_QNX_SOURCE=1" "_C99=1" +include(Settings.pri) + +arm { + SOURCES += ../Common/ArmABI.cpp \ + ../Common/ArmEmitter.cpp \ + ../Common/ThunkARM.cpp + HEADERS += ../Common/ArmABI.h \ + ../Common/ArmEmitter.h +} +x86 { + SOURCES += ../Common/ABI.cpp \ + ../Common/CPUDetect.cpp \ + ../Common/MathUtil.cpp \ + ../Common/Thunk.cpp \ + ../Common/x64Analyzer.cpp \ + ../Common/x64Emitter.cpp + HEADERS += ../Common/ABI.h \ + ../Common/CPUDetect.h \ + ../Common/MathUtil.h \ + ../Common/Thunk.h \ + ../Common/x64Analyzer.h \ + ../Common/x64Emitter.h +} +win32 { + SOURCES += ../Common/stdafx.cpp + HEADERS += ../Common/stdafx.h } -SOURCES += ../Common/ArmABI.cpp \ - ../Common/ArmEmitter.cpp \ - ../Common/ThunkARM.cpp \ - ../Common/Action.cpp \ - ../Common/ColorUtil.cpp \ - ../Common/ConsoleListener.cpp \ - ../Common/Crypto/aes_cbc.cpp \ - ../Common/Crypto/aes_core.cpp \ - ../Common/Crypto/bn.cpp \ - ../Common/Crypto/ec.cpp \ - ../Common/Crypto/md5.cpp \ - ../Common/Crypto/sha1.cpp \ - ../Common/ExtendedTrace.cpp \ - ../Common/FPURoundModeGeneric.cpp \ - ../Common/FileSearch.cpp \ - ../Common/FileUtil.cpp \ - ../Common/Hash.cpp \ - ../Common/IniFile.cpp \ - ../Common/LogManager.cpp \ - ../Common/MemArena.cpp \ - ../Common/MemoryUtil.cpp \ - ../Common/Misc.cpp \ - ../Common/MathUtil.cpp \ - ../Common/MsgHandler.cpp \ - ../Common/StringUtil.cpp \ - ../Common/Thread.cpp \ - ../Common/Timer.cpp \ - ../Common/Version.cpp -HEADERS += ../Common/ArmABI.h \ - ../Common/ArmEmitter.h \ - ../Common/Action.h \ - ../Common/ColorUtil.h \ - ../Common/ConsoleListener.h \ - ../Common/Crypto/md5.h \ - ../Common/Crypto/sha1.h \ - ../Common/ExtendedTrace.h \ - ../Common/FileSearch.h \ - ../Common/FileUtil.h \ - ../Common/Hash.h \ - ../Common/IniFile.h \ - ../Common/LogManager.h \ - ../Common/MemArena.h \ - ../Common/MemoryUtil.h \ - ../Common/MathUtil.h \ - ../Common/MsgHandler.h \ - ../Common/StringUtil.h \ - ../Common/Thread.h \ - ../Common/Timer.h +SOURCES += ../Common/Action.cpp \ + ../Common/ColorUtil.cpp \ + ../Common/ConsoleListener.cpp \ + ../Common/Crypto/aes_cbc.cpp \ + ../Common/Crypto/aes_core.cpp \ + ../Common/Crypto/bn.cpp \ + ../Common/Crypto/ec.cpp \ + ../Common/Crypto/md5.cpp \ + ../Common/Crypto/sha1.cpp \ + ../Common/ExtendedTrace.cpp \ + ../Common/FPURoundModeGeneric.cpp \ + ../Common/FileSearch.cpp \ + ../Common/FileUtil.cpp \ + ../Common/Hash.cpp \ + ../Common/IniFile.cpp \ + ../Common/LogManager.cpp \ + ../Common/MemArena.cpp \ + ../Common/MemoryUtil.cpp \ + ../Common/Misc.cpp \ + ../Common/MathUtil.cpp \ + ../Common/MsgHandler.cpp \ + ../Common/StringUtil.cpp \ + ../Common/Thread.cpp \ + ../Common/Timer.cpp \ + ../Common/Version.cpp +HEADERS += ../Common/Action.h \ + ../Common/ColorUtil.h \ + ../Common/ConsoleListener.h \ + ../Common/Crypto/md5.h \ + ../Common/Crypto/sha1.h \ + ../Common/ExtendedTrace.h \ + ../Common/FileSearch.h \ + ../Common/FileUtil.h \ + ../Common/Hash.h \ + ../Common/IniFile.h \ + ../Common/LogManager.h \ + ../Common/MemArena.h \ + ../Common/MemoryUtil.h \ + ../Common/MathUtil.h \ + ../Common/MsgHandler.h \ + ../Common/StringUtil.h \ + ../Common/Thread.h \ + ../Common/Timer.h -QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter -DEFINES += ARM USING_GLES2 -blackberry: DEFINES += BLACKBERRY BLACKBERRY10 -symbian: { - QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment - DEFINES += SYMBIAN -} diff --git a/Qt/Core.pro b/Qt/Core.pro index 95cefa9a4b..2a14f42b01 100755 --- a/Qt/Core.pro +++ b/Qt/Core.pro @@ -4,242 +4,250 @@ TARGET = Core TEMPLATE = lib CONFIG += staticlib -blackberry: { - QMAKE_CC = ntoarmv7-gcc - QMAKE_CXX = ntoarmv7-g++ - DEFINES += "_QNX_SOURCE=1" "_C99=1" -} +include(Settings.pri) INCLUDEPATH += ../native ../Common ../ -SOURCES += ../Core/MIPS/ARM/Asm.cpp \ #CoreARM - ../Core/MIPS/ARM/CompALU.cpp \ - ../Core/MIPS/ARM/CompBranch.cpp \ - ../Core/MIPS/ARM/CompFPU.cpp \ - ../Core/MIPS/ARM/CompLoadStore.cpp \ - ../Core/MIPS/ARM/CompVFPU.cpp \ - ../Core/MIPS/ARM/Jit.cpp \ - ../Core/MIPS/ARM/JitCache.cpp \ - ../Core/MIPS/ARM/RegCache.cpp \ - ../Core/CPU.cpp \ # Core - ../Core/Config.cpp \ - ../Core/Core.cpp \ - ../Core/CoreTiming.cpp \ - ../Core/Debugger/Breakpoints.cpp \ - ../Core/Debugger/SymbolMap.cpp \ - ../Core/Dialog/PSPDialog.cpp \ - ../Core/Dialog/PSPMsgDialog.cpp \ - ../Core/Dialog/PSPOskDialog.cpp \ - ../Core/Dialog/PSPPlaceholderDialog.cpp \ - ../Core/Dialog/PSPSaveDialog.cpp \ - ../Core/Dialog/SavedataParam.cpp \ - ../Core/ELF/ElfReader.cpp \ - ../Core/ELF/PrxDecrypter.cpp \ - ../Core/ELF/ParamSFO.cpp \ - ../Core/FileSystems/BlockDevices.cpp \ - ../Core/FileSystems/DirectoryFileSystem.cpp \ - ../Core/FileSystems/ISOFileSystem.cpp \ - ../Core/FileSystems/MetaFileSystem.cpp \ - ../Core/HLE/HLE.cpp \ - ../Core/HLE/HLETables.cpp \ - ../Core/HLE/__sceAudio.cpp \ - ../Core/HLE/sceAtrac.cpp \ - ../Core/HLE/sceAudio.cpp \ - ../Core/HLE/sceCtrl.cpp \ - ../Core/HLE/sceDisplay.cpp \ - ../Core/HLE/sceDmac.cpp \ - ../Core/HLE/sceGe.cpp \ - ../Core/HLE/sceFont.cpp \ - ../Core/HLE/sceHprm.cpp \ - ../Core/HLE/sceHttp.cpp \ - ../Core/HLE/sceImpose.cpp \ - ../Core/HLE/sceIo.cpp \ - ../Core/HLE/sceKernel.cpp \ - ../Core/HLE/sceKernelAlarm.cpp \ - ../Core/HLE/sceKernelEventFlag.cpp \ - ../Core/HLE/sceKernelInterrupt.cpp \ - ../Core/HLE/sceKernelMbx.cpp \ - ../Core/HLE/sceKernelMemory.cpp \ - ../Core/HLE/sceKernelModule.cpp \ - ../Core/HLE/sceKernelMsgPipe.cpp \ - ../Core/HLE/sceKernelMutex.cpp \ - ../Core/HLE/sceKernelSemaphore.cpp \ - ../Core/HLE/sceKernelThread.cpp \ - ../Core/HLE/sceKernelThread.h \ - ../Core/HLE/sceKernelTime.cpp \ - ../Core/HLE/sceKernelVTimer.cpp \ - ../Core/HLE/sceMpeg.cpp \ - ../Core/HLE/sceNet.cpp \ - ../Core/HLE/sceOpenPSID.cpp \ - ../Core/HLE/sceParseHttp.cpp \ - ../Core/HLE/sceParseUri.cpp \ - ../Core/HLE/scePower.cpp \ - ../Core/HLE/scePsmf.cpp \ - ../Core/HLE/sceRtc.cpp \ - ../Core/HLE/sceSas.cpp \ - ../Core/HLE/sceSsl.cpp \ - ../Core/HLE/scesupPreAcc.cpp \ - ../Core/HLE/sceUmd.cpp \ - ../Core/HLE/sceUsb.cpp \ - ../Core/HLE/sceUtility.cpp \ - ../Core/HLE/sceVaudio.cpp \ - ../Core/HW/MemoryStick.cpp \ - ../Core/HW/SasAudio.cpp \ - ../Core/Host.cpp \ - ../Core/Loaders.cpp \ - ../Core/MIPS/JitCommon/JitCommon.cpp \ - ../Core/MIPS/MIPS.cpp \ - ../Core/MIPS/MIPSAnalyst.cpp \ - ../Core/MIPS/MIPSCodeUtils.cpp \ - ../Core/MIPS/MIPSDebugInterface.cpp \ - ../Core/MIPS/MIPSDis.cpp \ - ../Core/MIPS/MIPSDisVFPU.cpp \ - ../Core/MIPS/MIPSInt.cpp \ - ../Core/MIPS/MIPSIntVFPU.cpp \ - ../Core/MIPS/MIPSTables.cpp \ - ../Core/MIPS/MIPSVFPUUtils.cpp \ - ../Core/MemMap.cpp \ - ../Core/MemMapFunctions.cpp \ - ../Core/PSPLoaders.cpp \ - ../Core/PSPMixer.cpp \ - ../Core/System.cpp \ - ../Core/Util/BlockAllocator.cpp \ - ../Core/Util/PPGeDraw.cpp \ - ../Core/Util/ppge_atlas.cpp \ # GPU - ../GPU/GLES/DisplayListInterpreter.cpp \ - ../GPU/GLES/FragmentShaderGenerator.cpp \ - ../GPU/GLES/Framebuffer.cpp \ - ../GPU/GLES/IndexGenerator.cpp \ - ../GPU/GLES/ShaderManager.cpp \ - ../GPU/GLES/StateMapping.cpp \ - ../GPU/GLES/TextureCache.cpp \ - ../GPU/GLES/TransformPipeline.cpp \ - ../GPU/GLES/VertexDecoder.cpp \ - ../GPU/GLES/VertexShaderGenerator.cpp \ - ../GPU/GPUState.cpp \ - ../GPU/Math3D.cpp \ - ../GPU/Null/NullGpu.cpp \ # Kirk - ../ext/libkirk/AES.c \ - ../ext/libkirk/SHA1.c \ - ../ext/libkirk/bn.c \ - ../ext/libkirk/ec.c \ - ../ext/libkirk/kirk_engine.c +arm { + SOURCES += ../Core/MIPS/ARM/Asm.cpp \ #CoreARM + ../Core/MIPS/ARM/CompALU.cpp \ + ../Core/MIPS/ARM/CompBranch.cpp \ + ../Core/MIPS/ARM/CompFPU.cpp \ + ../Core/MIPS/ARM/CompLoadStore.cpp \ + ../Core/MIPS/ARM/CompVFPU.cpp \ + ../Core/MIPS/ARM/Jit.cpp \ + ../Core/MIPS/ARM/JitCache.cpp \ + ../Core/MIPS/ARM/RegCache.cpp -HEADERS += ../Core/MIPS/ARM/Asm.h \ - ../Core/MIPS/ARM/Jit.h \ - ../Core/MIPS/ARM/JitCache.h \ - ../Core/MIPS/ARM/RegCache.h \ - ../Core/CPU.h \ - ../Core/Config.h \ - ../Core/Core.h \ - ../Core/CoreParameter.h \ - ../Core/CoreTiming.h \ - ../Core/Debugger/Breakpoints.h \ - ../Core/Debugger/DebugInterface.h \ - ../Core/Debugger/SymbolMap.h \ - ../Core/Dialog/PSPDialog.h \ - ../Core/Dialog/PSPMsgDialog.h \ - ../Core/Dialog/PSPOskDialog.h \ - ../Core/Dialog/PSPPlaceholderDialog.h \ - ../Core/Dialog/PSPSaveDialog.h \ - ../Core/Dialog/SavedataParam.h \ - ../Core/ELF/ElfReader.h \ - ../Core/ELF/ElfTypes.h \ - ../Core/ELF/PrxDecrypter.h \ - ../Core/ELF/ParamSFO.h \ - ../Core/FileSystems/BlockDevices.h \ - ../Core/FileSystems/DirectoryFileSystem.h \ - ../Core/FileSystems/FileSystem.h \ - ../Core/FileSystems/ISOFileSystem.h \ - ../Core/FileSystems/MetaFileSystem.h \ - ../Core/HLE/FunctionWrappers.h \ - ../Core/HLE/HLE.h \ - ../Core/HLE/HLETables.h \ - ../Core/HLE/__sceAudio.h \ - ../Core/HLE/sceAtrac.h \ - ../Core/HLE/sceAudio.h \ - ../Core/HLE/sceCtrl.h \ - ../Core/HLE/sceDisplay.h \ - ../Core/HLE/sceDmac.h \ - ../Core/HLE/sceGe.h \ - ../Core/HLE/sceFont.h \ - ../Core/HLE/sceHprm.h \ - ../Core/HLE/sceHttp.h \ - ../Core/HLE/sceImpose.h \ - ../Core/HLE/sceIo.h \ - ../Core/HLE/sceKernel.h \ - ../Core/HLE/sceKernelAlarm.h \ - ../Core/HLE/sceKernelEventFlag.h \ - ../Core/HLE/sceKernelInterrupt.h \ - ../Core/HLE/sceKernelMbx.h \ - ../Core/HLE/sceKernelMemory.h \ - ../Core/HLE/sceKernelModule.h \ - ../Core/HLE/sceKernelMsgPipe.h \ - ../Core/HLE/sceKernelMutex.h \ - ../Core/HLE/sceKernelSemaphore.h \ - ../Core/HLE/sceMpeg.h \ - ../Core/HLE/sceNet.h \ - ../Core/HLE/sceOpenPSID.h \ - ../Core/HLE/sceParseHttp.h \ - ../Core/HLE/sceParseUri.h \ - ../Core/HLE/scePower.h \ - ../Core/HLE/scePsmf.h \ - ../Core/HLE/sceRtc.h \ - ../Core/HLE/sceSas.h \ - ../Core/HLE/sceSsl.h \ - ../Core/HLE/scesupPreAcc.h \ - ../Core/HLE/sceUmd.h \ - ../Core/HLE/sceUsb.h \ - ../Core/HLE/sceUtility.h \ - ../Core/HLE/sceVaudio.h \ - ../Core/HW/MemoryStick.h \ - ../Core/HW/SasAudio.h \ - ../Core/Host.h \ - ../Core/Loaders.h \ - ../Core/MIPS/JitCommon/JitCommon.h \ - ../Core/MIPS/MIPS.h \ - ../Core/MIPS/MIPSAnalyst.h \ - ../Core/HLE/sceKernelTime.h \ - ../Core/HLE/sceKernelVTimer.h \ - ../Core/MIPS/MIPSCodeUtils.h \ - ../Core/MIPS/MIPSDebugInterface.h \ - ../Core/MIPS/MIPSDis.h \ - ../Core/MIPS/MIPSDisVFPU.h \ - ../Core/MIPS/MIPSInt.h \ - ../Core/MIPS/MIPSIntVFPU.h \ - ../Core/MIPS/MIPSTables.h \ - ../Core/MIPS/MIPSVFPUUtils.h \ - ../Core/MemMap.h \ - ../Core/PSPLoaders.h \ - ../Core/PSPMixer.h \ - ../Core/System.h \ - ../Core/Util/BlockAllocator.h \ - ../Core/Util/PPGeDraw.h \ - ../Core/Util/Pool.h \ - ../Core/Util/ppge_atlas.h \ - ../GPU/GLES/DisplayListInterpreter.h \ - ../GPU/GLES/FragmentShaderGenerator.h \ - ../GPU/GLES/Framebuffer.h \ - ../GPU/GLES/IndexGenerator.h \ - ../GPU/GLES/ShaderManager.h \ - ../GPU/GLES/StateMapping.h \ - ../GPU/GLES/TextureCache.h \ - ../GPU/GLES/TransformPipeline.h \ - ../GPU/GLES/VertexDecoder.h \ - ../GPU/GLES/VertexShaderGenerator.h \ - ../GPU/GPUInterface.h \ - ../GPU/GPUState.h \ - ../GPU/Math3D.h \ - ../GPU/Null/NullGpu.h \ - ../GPU/ge_constants.h \ - ../ext/libkirk/AES.h \ - ../ext/libkirk/SHA1.h \ - ../ext/libkirk/kirk_engine.h - -QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter -DEFINES += ARM USING_GLES2 -blackberry: DEFINES += BLACKBERRY BLACKBERRY10 -symbian: { - QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment - DEFINES += SYMBIAN + HEADERS += ../Core/MIPS/ARM/Asm.h \ + ../Core/MIPS/ARM/Jit.h \ + ../Core/MIPS/ARM/JitCache.h \ + ../Core/MIPS/ARM/RegCache.h } +x86 { + SOURCES += ../Core/MIPS/x86/Asm.cpp \ + ../Core/MIPS/x86/CompALU.cpp \ + ../Core/MIPS/x86/CompBranch.cpp \ + ../Core/MIPS/x86/CompFPU.cpp \ + ../Core/MIPS/x86/CompLoadStore.cpp \ + ../Core/MIPS/x86/CompVFPU.cpp \ + ../Core/MIPS/x86/Jit.cpp \ + ../Core/MIPS/x86/JitCache.cpp \ + ../Core/MIPS/x86/RegCache.cpp + HEADERS += ../Core/MIPS/x86/Asm.h \ + ../Core/MIPS/x86/Jit.h \ + ../Core/MIPS/x86/JitCache.h \ + ../Core/MIPS/x86/RegCache.h +} + +SOURCES += ../Core/CPU.cpp \ # Core + ../Core/Config.cpp \ + ../Core/Core.cpp \ + ../Core/CoreTiming.cpp \ + ../Core/Debugger/Breakpoints.cpp \ + ../Core/Debugger/SymbolMap.cpp \ + ../Core/Dialog/PSPDialog.cpp \ + ../Core/Dialog/PSPMsgDialog.cpp \ + ../Core/Dialog/PSPOskDialog.cpp \ + ../Core/Dialog/PSPPlaceholderDialog.cpp \ + ../Core/Dialog/PSPSaveDialog.cpp \ + ../Core/Dialog/SavedataParam.cpp \ + ../Core/ELF/ElfReader.cpp \ + ../Core/ELF/PrxDecrypter.cpp \ + ../Core/ELF/ParamSFO.cpp \ + ../Core/FileSystems/BlockDevices.cpp \ + ../Core/FileSystems/DirectoryFileSystem.cpp \ + ../Core/FileSystems/ISOFileSystem.cpp \ + ../Core/FileSystems/MetaFileSystem.cpp \ + ../Core/HLE/HLE.cpp \ + ../Core/HLE/HLETables.cpp \ + ../Core/HLE/__sceAudio.cpp \ + ../Core/HLE/sceAtrac.cpp \ + ../Core/HLE/sceAudio.cpp \ + ../Core/HLE/sceCtrl.cpp \ + ../Core/HLE/sceDisplay.cpp \ + ../Core/HLE/sceDmac.cpp \ + ../Core/HLE/sceGe.cpp \ + ../Core/HLE/sceFont.cpp \ + ../Core/HLE/sceHprm.cpp \ + ../Core/HLE/sceHttp.cpp \ + ../Core/HLE/sceImpose.cpp \ + ../Core/HLE/sceIo.cpp \ + ../Core/HLE/sceKernel.cpp \ + ../Core/HLE/sceKernelAlarm.cpp \ + ../Core/HLE/sceKernelEventFlag.cpp \ + ../Core/HLE/sceKernelInterrupt.cpp \ + ../Core/HLE/sceKernelMbx.cpp \ + ../Core/HLE/sceKernelMemory.cpp \ + ../Core/HLE/sceKernelModule.cpp \ + ../Core/HLE/sceKernelMsgPipe.cpp \ + ../Core/HLE/sceKernelMutex.cpp \ + ../Core/HLE/sceKernelSemaphore.cpp \ + ../Core/HLE/sceKernelThread.cpp \ + ../Core/HLE/sceKernelThread.h \ + ../Core/HLE/sceKernelTime.cpp \ + ../Core/HLE/sceKernelVTimer.cpp \ + ../Core/HLE/sceMpeg.cpp \ + ../Core/HLE/sceNet.cpp \ + ../Core/HLE/sceOpenPSID.cpp \ + ../Core/HLE/sceParseHttp.cpp \ + ../Core/HLE/sceParseUri.cpp \ + ../Core/HLE/scePower.cpp \ + ../Core/HLE/scePsmf.cpp \ + ../Core/HLE/sceRtc.cpp \ + ../Core/HLE/sceSas.cpp \ + ../Core/HLE/sceSsl.cpp \ + ../Core/HLE/scesupPreAcc.cpp \ + ../Core/HLE/sceUmd.cpp \ + ../Core/HLE/sceUsb.cpp \ + ../Core/HLE/sceUtility.cpp \ + ../Core/HLE/sceVaudio.cpp \ + ../Core/HW/MemoryStick.cpp \ + ../Core/HW/SasAudio.cpp \ + ../Core/Host.cpp \ + ../Core/Loaders.cpp \ + ../Core/MIPS/JitCommon/JitCommon.cpp \ + ../Core/MIPS/MIPS.cpp \ + ../Core/MIPS/MIPSAnalyst.cpp \ + ../Core/MIPS/MIPSCodeUtils.cpp \ + ../Core/MIPS/MIPSDebugInterface.cpp \ + ../Core/MIPS/MIPSDis.cpp \ + ../Core/MIPS/MIPSDisVFPU.cpp \ + ../Core/MIPS/MIPSInt.cpp \ + ../Core/MIPS/MIPSIntVFPU.cpp \ + ../Core/MIPS/MIPSTables.cpp \ + ../Core/MIPS/MIPSVFPUUtils.cpp \ + ../Core/MemMap.cpp \ + ../Core/MemMapFunctions.cpp \ + ../Core/PSPLoaders.cpp \ + ../Core/PSPMixer.cpp \ + ../Core/System.cpp \ + ../Core/Util/BlockAllocator.cpp \ + ../Core/Util/PPGeDraw.cpp \ + ../Core/Util/ppge_atlas.cpp \ # GPU + ../GPU/GLES/DisplayListInterpreter.cpp \ + ../GPU/GLES/FragmentShaderGenerator.cpp \ + ../GPU/GLES/Framebuffer.cpp \ + ../GPU/GLES/IndexGenerator.cpp \ + ../GPU/GLES/ShaderManager.cpp \ + ../GPU/GLES/StateMapping.cpp \ + ../GPU/GLES/TextureCache.cpp \ + ../GPU/GLES/TransformPipeline.cpp \ + ../GPU/GLES/VertexDecoder.cpp \ + ../GPU/GLES/VertexShaderGenerator.cpp \ + ../GPU/GPUState.cpp \ + ../GPU/Math3D.cpp \ + ../GPU/Null/NullGpu.cpp \ # Kirk + ../ext/libkirk/AES.c \ + ../ext/libkirk/SHA1.c \ + ../ext/libkirk/bn.c \ + ../ext/libkirk/ec.c \ + ../ext/libkirk/kirk_engine.c + +HEADERS += ../Core/CPU.h \ + ../Core/Config.h \ + ../Core/Core.h \ + ../Core/CoreParameter.h \ + ../Core/CoreTiming.h \ + ../Core/Debugger/Breakpoints.h \ + ../Core/Debugger/DebugInterface.h \ + ../Core/Debugger/SymbolMap.h \ + ../Core/Dialog/PSPDialog.h \ + ../Core/Dialog/PSPMsgDialog.h \ + ../Core/Dialog/PSPOskDialog.h \ + ../Core/Dialog/PSPPlaceholderDialog.h \ + ../Core/Dialog/PSPSaveDialog.h \ + ../Core/Dialog/SavedataParam.h \ + ../Core/ELF/ElfReader.h \ + ../Core/ELF/ElfTypes.h \ + ../Core/ELF/PrxDecrypter.h \ + ../Core/ELF/ParamSFO.h \ + ../Core/FileSystems/BlockDevices.h \ + ../Core/FileSystems/DirectoryFileSystem.h \ + ../Core/FileSystems/FileSystem.h \ + ../Core/FileSystems/ISOFileSystem.h \ + ../Core/FileSystems/MetaFileSystem.h \ + ../Core/HLE/FunctionWrappers.h \ + ../Core/HLE/HLE.h \ + ../Core/HLE/HLETables.h \ + ../Core/HLE/__sceAudio.h \ + ../Core/HLE/sceAtrac.h \ + ../Core/HLE/sceAudio.h \ + ../Core/HLE/sceCtrl.h \ + ../Core/HLE/sceDisplay.h \ + ../Core/HLE/sceDmac.h \ + ../Core/HLE/sceGe.h \ + ../Core/HLE/sceFont.h \ + ../Core/HLE/sceHprm.h \ + ../Core/HLE/sceHttp.h \ + ../Core/HLE/sceImpose.h \ + ../Core/HLE/sceIo.h \ + ../Core/HLE/sceKernel.h \ + ../Core/HLE/sceKernelAlarm.h \ + ../Core/HLE/sceKernelEventFlag.h \ + ../Core/HLE/sceKernelInterrupt.h \ + ../Core/HLE/sceKernelMbx.h \ + ../Core/HLE/sceKernelMemory.h \ + ../Core/HLE/sceKernelModule.h \ + ../Core/HLE/sceKernelMsgPipe.h \ + ../Core/HLE/sceKernelMutex.h \ + ../Core/HLE/sceKernelSemaphore.h \ + ../Core/HLE/sceMpeg.h \ + ../Core/HLE/sceNet.h \ + ../Core/HLE/sceOpenPSID.h \ + ../Core/HLE/sceParseHttp.h \ + ../Core/HLE/sceParseUri.h \ + ../Core/HLE/scePower.h \ + ../Core/HLE/scePsmf.h \ + ../Core/HLE/sceRtc.h \ + ../Core/HLE/sceSas.h \ + ../Core/HLE/sceSsl.h \ + ../Core/HLE/scesupPreAcc.h \ + ../Core/HLE/sceUmd.h \ + ../Core/HLE/sceUsb.h \ + ../Core/HLE/sceUtility.h \ + ../Core/HLE/sceVaudio.h \ + ../Core/HW/MemoryStick.h \ + ../Core/HW/SasAudio.h \ + ../Core/Host.h \ + ../Core/Loaders.h \ + ../Core/MIPS/JitCommon/JitCommon.h \ + ../Core/MIPS/MIPS.h \ + ../Core/MIPS/MIPSAnalyst.h \ + ../Core/HLE/sceKernelTime.h \ + ../Core/HLE/sceKernelVTimer.h \ + ../Core/MIPS/MIPSCodeUtils.h \ + ../Core/MIPS/MIPSDebugInterface.h \ + ../Core/MIPS/MIPSDis.h \ + ../Core/MIPS/MIPSDisVFPU.h \ + ../Core/MIPS/MIPSInt.h \ + ../Core/MIPS/MIPSIntVFPU.h \ + ../Core/MIPS/MIPSTables.h \ + ../Core/MIPS/MIPSVFPUUtils.h \ + ../Core/MemMap.h \ + ../Core/PSPLoaders.h \ + ../Core/PSPMixer.h \ + ../Core/System.h \ + ../Core/Util/BlockAllocator.h \ + ../Core/Util/PPGeDraw.h \ + ../Core/Util/Pool.h \ + ../Core/Util/ppge_atlas.h \ + ../GPU/GLES/DisplayListInterpreter.h \ + ../GPU/GLES/FragmentShaderGenerator.h \ + ../GPU/GLES/Framebuffer.h \ + ../GPU/GLES/IndexGenerator.h \ + ../GPU/GLES/ShaderManager.h \ + ../GPU/GLES/StateMapping.h \ + ../GPU/GLES/TextureCache.h \ + ../GPU/GLES/TransformPipeline.h \ + ../GPU/GLES/VertexDecoder.h \ + ../GPU/GLES/VertexShaderGenerator.h \ + ../GPU/GPUInterface.h \ + ../GPU/GPUState.h \ + ../GPU/Math3D.h \ + ../GPU/Null/NullGpu.h \ + ../GPU/ge_constants.h \ + ../ext/libkirk/AES.h \ + ../ext/libkirk/SHA1.h \ + ../ext/libkirk/kirk_engine.h + diff --git a/Qt/Native.pro b/Qt/Native.pro index 1ad7bf8d4e..a5916b80cb 100755 --- a/Qt/Native.pro +++ b/Qt/Native.pro @@ -4,20 +4,30 @@ TARGET = Native TEMPLATE = lib CONFIG += staticlib -blackberry: { - QMAKE_CC = ntoarmv7-gcc - QMAKE_CXX = ntoarmv7-g++ - DEFINES += "_QNX_SOURCE=1" "_C99=1" +include(Settings.pri) + +!mobile_platform: { + SOURCES += ../native/ext/glew/glew.c + HEADERS += ../native/ext/glew/GL/glew.h \ + ../native/ext/glew/GL/glxew.h \ + ../native/ext/glew/GL/wglew.h + INCLUDEPATH += ../native/ext/glew +} + +# Backtrace +x86:!mobile_platform: { + SOURCES += ../native/base/backtrace.cpp + HEADERS += ../native/base/backtrace.h } # EtcPack SOURCES += ../native/ext/etcpack/etcdec.cpp \ - ../native/ext/etcpack/etcpack.cpp \ - ../native/ext/etcpack/image.cpp + ../native/ext/etcpack/etcpack.cpp \ + ../native/ext/etcpack/image.cpp HEADERS += ../native/ext/etcpack/etcdec.h \ - ../native/ext/etcpack/etcpack.h \ - ../native/ext/etcpack/image.h + ../native/ext/etcpack/etcpack.h \ + ../native/ext/etcpack/image.h INCLUDEPATH += ../native/ext/etcpack # Stb_image @@ -32,163 +42,155 @@ SOURCES += ../native/ext/stb_vorbis/stb_vorbis.c HEADERS += ../native/ext/stb_vorbis/stb_vorbis.h INCLUDEPATH += ../native/ext/stb_vorbis -!symbian: { # Zlib - -SOURCES += ../ext/zlib/adler32.c \ - ../ext/zlib/compress.c \ - ../ext/zlib/crc32.c \ - ../ext/zlib/deflate.c \ - ../ext/zlib/gzclose.c \ - ../ext/zlib/gzlib.c \ - ../ext/zlib/gzread.c \ - ../ext/zlib/gzwrite.c \ - ../ext/zlib/infback.c \ - ../ext/zlib/inffast.c \ - ../ext/zlib/inflate.c \ - ../ext/zlib/inflate.h \ - ../ext/zlib/inftrees.c \ - ../ext/zlib/trees.c \ - ../ext/zlib/uncompr.c \ - ../ext/zlib/zutil.c -HEADERS += ../ext/zlib/crc32.h \ - ../ext/zlib/deflate.h \ - ../ext/zlib/gzguts.h \ - ../ext/zlib/inffast.h \ - ../ext/zlib/inffixed.h \ - ../ext/zlib/inftrees.h \ - ../ext/zlib/trees.h \ - ../ext/zlib/zconf.h \ - ../ext/zlib/zlib.h \ - ../ext/zlib/zutil.h -INCLUDEPATH += ../ext/zlib +!symbian: { + SOURCES += ../ext/zlib/adler32.c \ + ../ext/zlib/compress.c \ + ../ext/zlib/crc32.c \ + ../ext/zlib/deflate.c \ + ../ext/zlib/gzclose.c \ + ../ext/zlib/gzlib.c \ + ../ext/zlib/gzread.c \ + ../ext/zlib/gzwrite.c \ + ../ext/zlib/infback.c \ + ../ext/zlib/inffast.c \ + ../ext/zlib/inflate.c \ + ../ext/zlib/inflate.h \ + ../ext/zlib/inftrees.c \ + ../ext/zlib/trees.c \ + ../ext/zlib/uncompr.c \ + ../ext/zlib/zutil.c + HEADERS += ../ext/zlib/crc32.h \ + ../ext/zlib/deflate.h \ + ../ext/zlib/gzguts.h \ + ../ext/zlib/inffast.h \ + ../ext/zlib/inffixed.h \ + ../ext/zlib/inftrees.h \ + ../ext/zlib/trees.h \ + ../ext/zlib/zconf.h \ + ../ext/zlib/zlib.h \ + ../ext/zlib/zutil.h + INCLUDEPATH += ../ext/zlib } # Native SOURCES += ../native/audio/mixer.cpp \ - ../native/audio/wav_read.cpp \ - ../native/base/buffer.cpp \ - ../native/base/colorutil.cpp \ - ../native/base/display.cpp \ - ../native/base/error_context.cpp \ - ../native/base/fastlist_test.cpp \ - ../native/base/stringutil.cpp \ - ../native/base/threadutil.cpp \ - ../native/base/timeutil.cpp \ - ../native/file/chunk_file.cpp \ - ../native/file/dialog.cpp \ - ../native/file/easy_file.cpp \ - ../native/file/fd_util.cpp \ - ../native/file/file_util.cpp \ - ../native/file/zip_read.cpp \ - ../native/gfx/gl_debug_log.cpp \ - ../native/gfx/gl_lost_manager.cpp \ - ../native/gfx/texture.cpp \ - ../native/gfx/texture_atlas.cpp \ - ../native/gfx/texture_gen.cpp \ - ../native/gfx_es2/draw_buffer.cpp \ - ../native/gfx_es2/fbo.cpp \ - ../native/gfx_es2/gl_state.cpp \ - ../native/gfx_es2/glsl_program.cpp \ - ../native/gfx_es2/vertex_format.cpp \ - ../native/image/png_load.cpp \ - ../native/image/zim_load.cpp \ - ../native/image/zim_save.cpp \ - ../native/input/gesture_detector.cpp \ - ../native/json/json_writer.cpp \ - ../native/math/curves.cpp \ - ../native/math/lin/aabb.cpp \ - ../native/math/lin/matrix4x4.cpp \ - ../native/math/lin/plane.cpp \ - ../native/math/lin/quat.cpp \ - ../native/math/lin/vec3.cpp \ - ../native/math/math_util.cpp \ - ../native/midi/midi_input.cpp \ - ../native/net/http_client.cpp \ - ../native/net/resolve.cpp \ - ../native/profiler/profiler.cpp \ - ../native/ui/screen.cpp \ - ../native/ui/ui.cpp \ - ../native/ui/virtual_input.cpp \ - ../native/util/bits/bits.cpp \ - ../native/util/bits/varint.cpp \ - ../native/util/hash/hash.cpp \ - ../native/util/random/perlin.cpp + ../native/audio/wav_read.cpp \ + ../native/base/buffer.cpp \ + ../native/base/colorutil.cpp \ + ../native/base/display.cpp \ + ../native/base/error_context.cpp \ + ../native/base/fastlist_test.cpp \ + ../native/base/stringutil.cpp \ + ../native/base/threadutil.cpp \ + ../native/base/timeutil.cpp \ + ../native/file/chunk_file.cpp \ + ../native/file/dialog.cpp \ + ../native/file/easy_file.cpp \ + ../native/file/fd_util.cpp \ + ../native/file/file_util.cpp \ + ../native/file/zip_read.cpp \ + ../native/gfx/gl_debug_log.cpp \ + ../native/gfx/gl_lost_manager.cpp \ + ../native/gfx/texture.cpp \ + ../native/gfx/texture_atlas.cpp \ + ../native/gfx/texture_gen.cpp \ + ../native/gfx_es2/draw_buffer.cpp \ + ../native/gfx_es2/fbo.cpp \ + ../native/gfx_es2/gl_state.cpp \ + ../native/gfx_es2/glsl_program.cpp \ + ../native/gfx_es2/vertex_format.cpp \ + ../native/image/png_load.cpp \ + ../native/image/zim_load.cpp \ + ../native/image/zim_save.cpp \ + ../native/input/gesture_detector.cpp \ + ../native/json/json_writer.cpp \ + ../native/math/curves.cpp \ + ../native/math/lin/aabb.cpp \ + ../native/math/lin/matrix4x4.cpp \ + ../native/math/lin/plane.cpp \ + ../native/math/lin/quat.cpp \ + ../native/math/lin/vec3.cpp \ + ../native/math/math_util.cpp \ + ../native/midi/midi_input.cpp \ + ../native/net/http_client.cpp \ + ../native/net/resolve.cpp \ + ../native/profiler/profiler.cpp \ + ../native/ui/screen.cpp \ + ../native/ui/ui.cpp \ + ../native/ui/virtual_input.cpp \ + ../native/util/bits/bits.cpp \ + ../native/util/bits/varint.cpp \ + ../native/util/hash/hash.cpp \ + ../native/util/random/perlin.cpp HEADERS += ../native/audio/mixer.h \ - ../native/audio/wav_read.h \ - ../native/base/basictypes.h \ - ../native/base/buffer.h \ - ../native/base/color.h \ - ../native/base/colorutil.h \ - ../native/base/display.h \ - ../native/base/error_context.h \ - ../native/base/fastlist.h \ - ../native/base/linked_ptr.h \ - ../native/base/logging.h \ - ../native/base/mutex.h \ - ../native/base/scoped_ptr.h \ - ../native/base/stats.h \ - ../native/base/stringutil.h \ - ../native/base/threadutil.h \ - ../native/base/timeutil.h \ - ../native/file/chunk_file.h \ - ../native/file/dialog.h \ - ../native/file/easy_file.h \ - ../native/file/fd_util.h \ - ../native/file/file_util.h \ - ../native/file/vfs.h \ - ../native/file/zip_read.h \ - ../native/gfx/gl_debug_log.h \ - ../native/gfx/gl_lost_manager.h \ - ../native/gfx/texture.h \ - ../native/gfx/texture_atlas.h \ - ../native/gfx/texture_gen.h \ - ../native/gfx_es2/fbo.h \ - ../native/gfx_es2/gl_state.h \ - ../native/gfx_es2/glsl_program.h \ - ../native/gfx_es2/vertex_format.h \ - ../native/gfx_es2/draw_buffer.h \ - ../native/image/png_load.h \ - ../native/image/zim_load.h \ - ../native/image/zim_save.h \ - ../native/input/gesture_detector.h \ - ../native/input/input_state.h \ - ../native/json/json_writer.h \ - ../native/math/compression.h \ - ../native/math/curves.h \ - ../native/math/lin/aabb.h \ - ../native/math/lin/matrix4x4.h \ - ../native/math/lin/plane.h \ - ../native/math/lin/quat.h \ - ../native/math/lin/ray.h \ - ../native/math/lin/vec3.h \ - ../native/math/math_util.h \ - ../native/midi/midi_input.h \ - ../native/net/http_client.h \ - ../native/net/resolve.h \ - ../native/ui/ui.h \ - ../native/profiler/profiler.h \ - ../native/ui/screen.h \ - ../native/ui/virtual_input.h \ - ../native/util/bits/bits.h \ - ../native/util/bits/hamming.h \ - ../native/util/bits/varint.h \ - ../native/util/hash/hash.h \ - ../native/util/random/perlin.h \ - ../native/util/random/rng.h \ - ../native/ext/rapidxml/rapidxml.hpp \ - ../native/ext/rapidxml/rapidxml_iterators.hpp \ - ../native/ext/rapidxml/rapidxml_print.hpp \ - ../native/ext/rapidxml/rapidxml_utils.hpp -INCLUDEPATH+= ../native + ../native/audio/wav_read.h \ + ../native/base/basictypes.h \ + ../native/base/buffer.h \ + ../native/base/color.h \ + ../native/base/colorutil.h \ + ../native/base/display.h \ + ../native/base/error_context.h \ + ../native/base/fastlist.h \ + ../native/base/linked_ptr.h \ + ../native/base/logging.h \ + ../native/base/mutex.h \ + ../native/base/scoped_ptr.h \ + ../native/base/stats.h \ + ../native/base/stringutil.h \ + ../native/base/threadutil.h \ + ../native/base/timeutil.h \ + ../native/file/chunk_file.h \ + ../native/file/dialog.h \ + ../native/file/easy_file.h \ + ../native/file/fd_util.h \ + ../native/file/file_util.h \ + ../native/file/vfs.h \ + ../native/file/zip_read.h \ + ../native/gfx/gl_debug_log.h \ + ../native/gfx/gl_lost_manager.h \ + ../native/gfx/texture.h \ + ../native/gfx/texture_atlas.h \ + ../native/gfx/texture_gen.h \ + ../native/gfx_es2/fbo.h \ + ../native/gfx_es2/gl_state.h \ + ../native/gfx_es2/glsl_program.h \ + ../native/gfx_es2/vertex_format.h \ + ../native/gfx_es2/draw_buffer.h \ + ../native/image/png_load.h \ + ../native/image/zim_load.h \ + ../native/image/zim_save.h \ + ../native/input/gesture_detector.h \ + ../native/input/input_state.h \ + ../native/json/json_writer.h \ + ../native/math/compression.h \ + ../native/math/curves.h \ + ../native/math/lin/aabb.h \ + ../native/math/lin/matrix4x4.h \ + ../native/math/lin/plane.h \ + ../native/math/lin/quat.h \ + ../native/math/lin/ray.h \ + ../native/math/lin/vec3.h \ + ../native/math/math_util.h \ + ../native/midi/midi_input.h \ + ../native/net/http_client.h \ + ../native/net/resolve.h \ + ../native/ui/ui.h \ + ../native/profiler/profiler.h \ + ../native/ui/screen.h \ + ../native/ui/virtual_input.h \ + ../native/util/bits/bits.h \ + ../native/util/bits/hamming.h \ + ../native/util/bits/varint.h \ + ../native/util/hash/hash.h \ + ../native/util/random/perlin.h \ + ../native/util/random/rng.h \ + ../native/ext/rapidxml/rapidxml.hpp \ + ../native/ext/rapidxml/rapidxml_iterators.hpp \ + ../native/ext/rapidxml/rapidxml_print.hpp \ + ../native/ext/rapidxml/rapidxml_utils.hpp +INCLUDEPATH += ../native -QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter -DEFINES += ARM USING_GLES2 -blackberry: DEFINES += BLACKBERRY BLACKBERRY10 -symbian: { - QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment - DEFINES += SYMBIAN -} diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index b958d46f76..3050a025f7 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -1,41 +1,40 @@ TARGET = PPSSPPQt -QT += core gui opengl multimedia +QT += core gui opengl -symbian: { - LIBS += -lCore.lib -lCommon.lib -lNative.lib -lcone -leikcore -lavkon -lezlib - CONFIG += 4.6.3 +include(Settings.pri) +linux { + CONFIG += mobility + MOBILITY += multimedia } -# They try to force QCC with all mkspecs -# QCC is 4.4.1, we need 4.6.3 -blackberry: { - QMAKE_CC = ntoarmv7-gcc - QMAKE_CXX = ntoarmv7-g++ - DEFINES += "_QNX_SOURCE=1" "_C99=1" - LIBS += -L. -lCore -lCommon -lNative -lscreen -lsocket -lstdc++ +else { + QT += multimedia } +# Libs +symbian: LIBS += -lCore.lib -lCommon.lib -lNative.lib -lcone -leikcore -lavkon -lezlib + +blackberry: LIBS += -L. -lCore -lCommon -lNative -lscreen -lsocket -lstdc++ + +win32: LIBS += -L. -lCore -lCommon -lNative -lwinmm -lws2_32 -lkernel32 -luser32 -lgdi32 -lshell32 -lcomctl32 -ldsound -lxinput + +linux: LIBS += -L. -lCore -lCommon -lNative + # Main SOURCES += ../native/base/QtMain.cpp HEADERS += ../native/base/QtMain.h # Native - SOURCES += ../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 + ../android/jni/EmuScreen.cpp \ + ../android/jni/MenuScreens.cpp \ + ../android/jni/GamepadEmu.cpp \ + ../android/jni/UIShader.cpp \ + ../android/jni/ui_atlas.cpp INCLUDEPATH += .. ../Common ../native -QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter -DEFINES += ARM USING_GLES2 -blackberry: DEFINES += BLACKBERRY BLACKBERRY10 -symbian: { - QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment - DEFINES += SYMBIAN - +# Packaging +symbian { vendorinfo = "%{\"Qtness\"}" ":\"Qtness\"" packageheader = "$${LITERAL_HASH}{\"PPSSPP\"}, (0xE0095B1D), 0, 0, 4, TYPE=SA" my_deployment.pkg_prerules = packageheader vendorinfo diff --git a/Qt/Settings.pri b/Qt/Settings.pri new file mode 100644 index 0000000000..320a37ca37 --- /dev/null +++ b/Qt/Settings.pri @@ -0,0 +1,31 @@ +blackberry|symbian: CONFIG += mobile_platform +unix:!blackberry:!macx: CONFIG += linux + +# Global specific +QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter + +# Arch specific +contains(QT_ARCH, arm): { + DEFINES += ARM + CONFIG += arm +} +contains(QT_ARCH, x86)|contains(QT_ARCH, x86_64): { + QMAKE_CXXFLAGS += -msse2 + CONFIG += x86 +} +mobile_platform: DEFINES += USING_GLES2 + + +# Platform specific +blackberry: { +# They try to force QCC with all mkspecs +# QCC is 4.4.1, we need 4.6.3 + QMAKE_CC = ntoarmv7-gcc + QMAKE_CXX = ntoarmv7-g++ + DEFINES += BLACKBERRY BLACKBERRY10 "_QNX_SOURCE=1" "_C99=1" +} +symbian: { + QMAKE_CXXFLAGS += -march=armv6 -mfpu=vfp -mfloat-abi=softfp -marm -Wno-parentheses -Wno-comment + DEFINES += SYMBIAN + CONFIG += 4.6.3 +} From fba61b2a2a3d97f8f7b2964194fd07b36ee4073b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 15 Dec 2012 13:06:13 +0700 Subject: [PATCH 124/276] Warning fixes (and maybe a bugfix) in sceRtc --- Core/HLE/sceRtc.cpp | 101 ++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 33f28ecb58..58ce61ed15 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -154,13 +154,13 @@ void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks) t.microsecond = ticks % 1000000; } -u64 JumpYMD(u64 year, u64 month, u64 day) { - return 367*year - 7*(year+(month+9)/12)/4 + 275*month/9 + day; +u64 JumpYMD(u64 year, u64 month, u64 day) { + return 367*year - 7*(year+(month+9)/12)/4 + 275*month/9 + day; } u64 JumpSeconds(u64 year, u64 month, u64 day, u64 hour, u64 minute, u64 second) { - static const u64 secs_per_day = 24 * 60 * 60; - return JumpYMD(year, month, day) * secs_per_day + hour * 3600 + minute * 60 + second; + static const u64 secs_per_day = 24 * 60 * 60; + return JumpYMD(year, month, day) * secs_per_day + hour * 3600 + minute * 60 + second; } u64 __RtcPspTimeToTicks(ScePspDateTime &t) @@ -336,7 +336,7 @@ u32 sceRtcGetDaysInMonth(u32 year, u32 month) u32 sceRtcIsLeapYear(u32 year) { ERROR_LOG(HLE, "sceRtcIsLeapYear(%d)", year); - return (year % 4 == 0) && !(year % 100 == 0)|| (year % 400 == 0); + return (year % 4 == 0) && (!(year % 100 == 0) || (year % 400 == 0)); } int sceRtcConvertLocalTimeToUTC(u32 tickLocalPtr,u32 tickUTCPtr) @@ -374,51 +374,56 @@ int sceRtcConvertUtcToLocalTime(u32 tickUTCPtr,u32 tickLocalPtr) int sceRtcCheckValid(u32 datePtr) { DEBUG_LOG(HLE, "sceRtcCheckValid(%d)", datePtr); - int ret = 0; if (Memory::IsValidAddress(datePtr)) { ScePspDateTime pt; Memory::ReadStruct(datePtr, &pt); - if (pt.year < 1 || pt.year > 9999) + if (pt.year < 1 || pt.year > 9999) { - ret = PSP_TIME_INVALID_YEAR; - } - else if (pt.month < 1 || pt.month > 12) + return PSP_TIME_INVALID_YEAR; + } + else if (pt.month < 1 || pt.month > 12) { - ret = PSP_TIME_INVALID_MONTH; - } - else if (pt.day < 1 || pt.day > 31) // TODO: Needs to check actual days in month, including leaps + return PSP_TIME_INVALID_MONTH; + } + else if (pt.day < 1 || pt.day > 31) { - ret = PSP_TIME_INVALID_DAY; - } - else if (pt.hour > 23) + return PSP_TIME_INVALID_DAY; + } + else if (pt.day > 31) // TODO: Needs to check actual days in month, including leaps { - ret = PSP_TIME_INVALID_HOUR; - } - else if (pt.minute > 59) + return PSP_TIME_INVALID_DAY; + } + else if (pt.hour > 23) { - ret = PSP_TIME_INVALID_MINUTES; - } - else if (pt.second > 59) + return PSP_TIME_INVALID_HOUR; + } + else if (pt.minute > 59) { - ret = PSP_TIME_INVALID_SECONDS; - } - else if (pt.microsecond >= 1000000) + return PSP_TIME_INVALID_MINUTES; + } + else if (pt.second > 59) { - ret = PSP_TIME_INVALID_MICROSECONDS; - } + return PSP_TIME_INVALID_SECONDS; + } + else if (pt.microsecond >= 1000000) + { + return PSP_TIME_INVALID_MICROSECONDS; + } + else { + return 0; + } } else { - ret=-1; + return -1; } - return ret; } int sceRtcSetTime_t(u32 datePtr, u32 time) { - ERROR_LOG(HLE, "HACK sceRtcSetTime_t(%d,%d)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcSetTime_t(%08x,%d)", datePtr, time); if (Memory::IsValidAddress(datePtr)) { ScePspDateTime pt; @@ -435,7 +440,7 @@ int sceRtcSetTime_t(u32 datePtr, u32 time) int sceRtcSetTime64_t(u32 datePtr, u64 time) { - ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%d,%lld)", datePtr, time); + ERROR_LOG(HLE, "HACK sceRtcSetTime64_t(%08x,%lld)", datePtr, time); if (Memory::IsValidAddress(datePtr)) { ScePspDateTime pt; @@ -450,10 +455,9 @@ int sceRtcSetTime64_t(u32 datePtr, u64 time) return 0; } - int sceRtcGetTime_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%d,%d)", datePtr, timePtr); + ERROR_LOG(HLE, "HACK sceRtcGetTime_t(%08x,%08x)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -469,10 +473,9 @@ int sceRtcGetTime_t(u32 datePtr, u32 timePtr) return 0; } - int sceRtcGetTime64_t(u32 datePtr, u32 timePtr) { - ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%d,%d)", datePtr, timePtr); + ERROR_LOG(HLE, "HACK sceRtcGetTime64_t(%08x,%08x)", datePtr, timePtr); if (Memory::IsValidAddress(datePtr)&&Memory::IsValidAddress(timePtr)) { ScePspDateTime pt; @@ -488,8 +491,6 @@ int sceRtcGetTime64_t(u32 datePtr, u32 timePtr) return 0; } - - int sceRtcSetDosTime(u32 datePtr, u32 dosTime) { ERROR_LOG(HLE, "HACK sceRtcSetDosTime(%d,%d)", datePtr, dosTime); @@ -544,16 +545,10 @@ int sceRtcCompareTick(u32 tick1Ptr, u32 tick2Ptr) { u64 tick1 = Memory::Read_U64(tick1Ptr); u64 tick2 = Memory::Read_U64(tick2Ptr); - - if (tick1 > tick2) - { + if (tick1 > tick2) return 1; - } - - if (tick1 < tick2) - { + if (tick1 < tick2) return -1; - } } return 0; } @@ -617,7 +612,6 @@ int sceRtcTickAddHours(u32 destTickPtr, u32 srcTickPtr, int numHours) if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) { s64 srcTick = (s64)Memory::Read_U64(srcTickPtr); - srcTick += numHours*3600000000UL; Memory::Write_U64(srcTick, destTickPtr); } @@ -656,7 +650,7 @@ int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths) if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) { u64 srcTick = Memory::Read_U64(srcTickPtr); - + // slightly bodgy but we need to add months to a pt and then convert to ticks to cover different day count in months and leapyears ScePspDateTime pt; memset(&pt, 0, sizeof(pt)); @@ -665,7 +659,7 @@ int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths) numMonths = -numMonths;; int years = numMonths /12; int realmonths = numMonths % 12; - + pt.year = years; pt.month = realmonths; u64 monthTicks =__RtcPspTimeToTicks(pt); @@ -684,7 +678,6 @@ int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths) { int years = numMonths /12; int realmonths = numMonths % 12; - pt.year = years; pt.month = realmonths; srcTick +=__RtcPspTimeToTicks(pt); @@ -696,7 +689,7 @@ int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths) return 0; } -//TODO: off by 6 days every 2000 years. +// TODO: off by 6 days every 2000 years. int sceRtcTickAddYears(u32 destTickPtr, u32 srcTickPtr, int numYears) { if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr)) @@ -739,10 +732,10 @@ int sceRtcParseDateTime(u32 destTickPtr, u32 dateStringPtr) return 0; } -const HLEFunction sceRtc[] = +const HLEFunction sceRtc[] = { {0xC41C2853, WrapU_V, "sceRtcGetTickResolution"}, - {0x3f7ad767, WrapU_U, "sceRtcGetCurrentTick"}, + {0x3f7ad767, WrapU_U, "sceRtcGetCurrentTick"}, {0x011F03C1, WrapU64_V, "sceRtcGetAccumulativeTime"}, {0x029CA3B3, WrapU64_V, "sceRtcGetAccumlativeTime"}, {0x4cfa57b0, WrapU_UI, "sceRtcGetCurrentClock"}, @@ -763,7 +756,7 @@ const HLEFunction sceRtc[] = {0x6FF40ACC, WrapU_UU, "sceRtcGetTick"}, {0x9ED0AE87, WrapI_UU, "sceRtcCompareTick"}, {0x44F45E05, WrapI_UUU64, "sceRtcTickAddTicks"}, - {0x26D25A5D, WrapI_UUU64, "sceRtcTickAddMicroseconds"}, + {0x26D25A5D, WrapI_UUU64, "sceRtcTickAddMicroseconds"}, {0xF2A4AFE5, WrapI_UUU64, "sceRtcTickAddSeconds"}, {0xE6605BCA, WrapI_UUU64, "sceRtcTickAddMinutes"}, {0x26D7A24A, WrapI_UUI, "sceRtcTickAddHours"}, @@ -781,8 +774,6 @@ const HLEFunction sceRtc[] = {0x1909c99b, WrapI_UU64, "sceRtcSetTime64_t"}, }; - - void Register_sceRtc() { RegisterModule("sceRtc", ARRAY_SIZE(sceRtc), sceRtc); From ce214b3943a28672538ec4968bddea95a31ad5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 23 Dec 2012 09:44:43 +0100 Subject: [PATCH 125/276] Assorted warning fixes --- Core/HLE/sceAudio.cpp | 28 +++++++++++-------------- Core/HLE/sceKernelInterrupt.cpp | 37 ++++++++++++++++----------------- Core/HLE/sceSas.cpp | 2 +- Core/HLE/sceUmd.cpp | 2 +- pspautotests | 2 +- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 563824421c..6184e18cdd 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -41,7 +41,7 @@ u32 sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr) { ERROR_LOG(HLE, "sceAudioOutputBlocking - Sample pointer null"); return 0; } - if (chan < 0 || chan >= MAX_CHANNEL) { + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutputBlocking() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } else if (!chans[chan].reserved) { @@ -60,7 +60,7 @@ u32 sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 sampleP if (samplePtr == 0) { ERROR_LOG(HLE, "sceAudioOutputPannedBlocking - Sample pointer null"); return 0; - } else if (chan < 0 || chan >= MAX_CHANNEL) { + } else if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutputPannedBlocking() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } else if (!chans[chan].reserved) { @@ -77,7 +77,7 @@ u32 sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 sampleP u32 sceAudioOutput(u32 chan, u32 vol, u32 samplePtr) { - if (chan < 0 || chan >= MAX_CHANNEL) { + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutput() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } @@ -99,7 +99,7 @@ u32 sceAudioOutput(u32 chan, u32 vol, u32 samplePtr) u32 sceAudioOutputPanned(u32 chan, u32 leftVol, u32 rightVol, u32 samplePtr) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutputPanned() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -122,7 +122,7 @@ u32 sceAudioOutputPanned(u32 chan, u32 leftVol, u32 rightVol, u32 samplePtr) int sceAudioGetChannelRestLen(u32 chan) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE, "sceAudioGetChannelRestLen(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -135,7 +135,7 @@ int sceAudioGetChannelRestLen(u32 chan) int sceAudioGetChannelRestLength(u32 chan) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE, "sceAudioGetChannelRestLength(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -149,12 +149,8 @@ int sceAudioGetChannelRestLength(u32 chan) static int GetFreeChannel() { for (int i = 0; i < MAX_CHANNEL; i++) - { if (!chans[i].reserved) - { return i; - } - } return -1; } @@ -170,7 +166,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun return SCE_ERROR_AUDIO_NO_CHANNELS_AVAILABLE; } - if (channel < 0 || channel >= MAX_CHANNEL) + if (channel >= MAX_CHANNEL) { ERROR_LOG(HLE ,"sceAudioChReserve(channel = %d, sampleCount = %d, format = %d) - BAD CHANNEL", channel, sampleCount, format); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -195,7 +191,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun u32 sceAudioChRelease(u32 chan) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE, "sceAudioChRelease(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -214,7 +210,7 @@ u32 sceAudioChRelease(u32 chan) u32 sceAudioSetChannelDataLen(u32 chan, u32 len) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - BAD CHANNEL", chan, len); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -234,7 +230,7 @@ u32 sceAudioSetChannelDataLen(u32 chan, u32 len) u32 sceAudioChangeChannelConfig(u32 chan, u32 format) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - invalid channel number", chan, format); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -254,7 +250,7 @@ u32 sceAudioChangeChannelConfig(u32 chan, u32 format) u32 sceAudioChangeChannelVolume(u32 chan, u32 lvolume, u32 rvolume) { - if (chan < 0 || chan >= MAX_CHANNEL) + if (chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - invalid channel number", chan, lvolume, rvolume); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -272,7 +268,7 @@ u32 sceAudioChangeChannelVolume(u32 chan, u32 lvolume, u32 rvolume) return 0; } } - + u32 sceAudioInit() { DEBUG_LOG(HLE,"sceAudioInit()"); diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 0c7b71296f..3ee53f9e77 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -382,7 +382,7 @@ u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) { DEBUG_LOG(HLE,"sceKernelEnableSubIntr(%i, %i)", intrNumber, subIntrNumber); - if (intrNumber < 0 || intrNumber >= PSP_NUMBER_INTERRUPTS) + if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; if (!intrHandlers[intrNumber].has(subIntrNumber)) @@ -395,7 +395,7 @@ u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) u32 sceKernelDisableSubIntr(u32 intrNumber, u32 subIntrNumber) { DEBUG_LOG(HLE,"sceKernelDisableSubIntr(%i, %i)", intrNumber, subIntrNumber); - if (intrNumber < 0 || intrNumber >= PSP_NUMBER_INTERRUPTS) + if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; if (!intrHandlers[intrNumber].has(subIntrNumber)) @@ -430,15 +430,14 @@ void QueryIntrHandlerInfo() RETURN(0); } -void sceKernelMemset() +// TODO: speedup +u32 sceKernelMemset(u32 addr, u32 fillc, u32 n) { - u32 addr = PARAM(0); - u8 c = PARAM(1) & 0xff; - u32 n = PARAM(2); + u8 c = fillc & 0xff; DEBUG_LOG(HLE, "sceKernelMemset(ptr = %08x, c = %02x, n = %08x)", addr, c, n); for (size_t i = 0; i < n; i++) Memory::Write_U8((u8)c, addr + i); - RETURN(0); /* TODO: verify it should return this */ + return 0; // TODO: verify it should return this } u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) @@ -451,21 +450,21 @@ u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) return 0; } -const HLEFunction Kernel_Library[] = +const HLEFunction Kernel_Library[] = { {0x092968F4,sceKernelCpuSuspendIntr,"sceKernelCpuSuspendIntr"}, {0x5F10D406,WrapV_U, "sceKernelCpuResumeIntr"}, //int oldstat {0x3b84732d,WrapV_U, "sceKernelCpuResumeIntrWithSync"}, {0x47a0b729,sceKernelIsCpuIntrSuspended, "sceKernelIsCpuIntrSuspended"}, //flags - {0xb55249d2,sceKernelIsCpuIntrEnable, "sceKernelIsCpuIntrEnable"}, - {0xa089eca4,sceKernelMemset, "sceKernelMemset"}, - {0xDC692EE3,&WrapI_UI, "sceKernelTryLockLwMutex"}, - {0x37431849,&WrapI_UI, "sceKernelTryLockLwMutex_600"}, - {0xbea46419,&WrapI_UIU, "sceKernelLockLwMutex"}, - {0x1FC64E09,&WrapI_UIU, "sceKernelLockLwMutexCB"}, - {0x15b6446b,&WrapI_UI, "sceKernelUnlockLwMutex"}, - {0x293b45b8,sceKernelGetThreadId, "sceKernelGetThreadId"}, - {0x1839852A,&WrapU_UUU,"sce_paf_private_memcpy"}, + {0xb55249d2,sceKernelIsCpuIntrEnable, "sceKernelIsCpuIntrEnable"}, + {0xa089eca4,WrapU_UUU, "sceKernelMemset"}, + {0xDC692EE3,WrapI_UI, "sceKernelTryLockLwMutex"}, + {0x37431849,WrapI_UI, "sceKernelTryLockLwMutex_600"}, + {0xbea46419,WrapI_UIU, "sceKernelLockLwMutex"}, + {0x1FC64E09,WrapI_UIU, "sceKernelLockLwMutexCB"}, + {0x15b6446b,WrapI_UI, "sceKernelUnlockLwMutex"}, + {0x293b45b8,sceKernelGetThreadId, "sceKernelGetThreadId"}, + {0x1839852A,WrapU_UUU,"sce_paf_private_memcpy"}, }; void Register_Kernel_Library() @@ -474,7 +473,7 @@ void Register_Kernel_Library() } -const HLEFunction InterruptManager[] = +const HLEFunction InterruptManager[] = { {0xCA04A2B9, WrapU_UUUU, "sceKernelRegisterSubIntrHandler"}, {0xD61E6961, WrapU_UU, "sceKernelReleaseSubIntrHandler"}, @@ -483,7 +482,7 @@ const HLEFunction InterruptManager[] = {0x5CB5A78B, 0, "sceKernelSuspendSubIntr"}, {0x7860E0DC, 0, "sceKernelResumeSubIntr"}, {0xFC4374B8, 0, "sceKernelIsSubInterruptOccurred"}, - {0xD2E8363F, 0, "QueryIntrHandlerInfo"}, // No sce prefix for some reason + {0xD2E8363F, QueryIntrHandlerInfo, "QueryIntrHandlerInfo"}, // No sce prefix for some reason {0xEEE43F47, 0, "sceKernelRegisterUserSpaceIntrStack"}, }; diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 56dcc7ffbd..7693592688 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -315,7 +315,7 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) { DEBUG_LOG(HLE,"UNIMPL 0=sceSasGetEnvelopeHeight(core=%08x, voicenum=%i)", core, voiceNum); } - if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) + if (voiceNum >= PSP_SAS_VOICES_MAX) { WARN_LOG(HLE, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); return ERROR_SAS_INVALID_VOICE; diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index fbe74b1ce8..a4fd3b8b11 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -134,7 +134,7 @@ int sceUmdActivate(u32 unknown, const char *name) int sceUmdDeactivate(u32 unknown, const char *name) { // Why 18? No idea. - if (unknown < 0 || unknown > 18) + if (unknown > 18) return PSP_ERROR_UMD_INVALID_PARAM; bool changed = umdActivated != 0; diff --git a/pspautotests b/pspautotests index 9ea2847b5e..5e5ae52067 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 9ea2847b5e793b9fae8ccd81f25cc8e4f6a81d7d +Subproject commit 5e5ae520672b816943acabed1f223ebcd7cff16f From b6e865c694bd509d0bdc97ff6d6113b03d3a7da3 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 23 Dec 2012 13:23:17 +0800 Subject: [PATCH 126/276] sceAtrac wrapped and change NOTICE to DEBUG for block transfer. --- Core/HLE/FunctionWrappers.h | 28 ++++ Core/HLE/sceAtrac.cpp | 195 ++++++++++++++-------------- GPU/GLES/DisplayListInterpreter.cpp | 4 +- 3 files changed, 130 insertions(+), 97 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 2d560cc0b7..a6b2c0284f 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -132,7 +132,15 @@ template void WrapU_I() { RETURN(retval); } +template void WrapU_II() { + u32 retval = func(PARAM(0), PARAM(1)); + RETURN(retval); +} +template void WrapU_IIU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); + RETURN(retval); +} template void WrapI_I() { int retval = func(PARAM(0)); @@ -230,6 +238,11 @@ template void WrapI_III() { RETURN(retval); } +template void WrapI_IIII() { + int retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapI_IIU() { int retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); @@ -297,11 +310,26 @@ template void WrapU_III() { RETURN(retval); } +template void WrapU_IIII() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapU_IUU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); } +template void WrapU_IUUU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + +template void WrapU_IUUUU() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_UUU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6b442be805..06482a5bf2 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -28,13 +28,15 @@ #define ATRAC_ERROR_API_FAIL 0x80630002 #define ATRAC_ERROR_ALL_DATA_DECODED 0x80630024 -int sceAtracAddStreamData(int atracID, u32 bytesToAdd) + + +u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { - ERROR_LOG(HLE, "UNIMPL sceAtracAddStreamData(%i, %i)", atracID, bytesToAdd); + ERROR_LOG(HLE, "UNIMPL sceAtracAddStreamData(%i, %08x)", atracID, bytesToAdd); return 0; } -int sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishFlagAddr, u32 remainAddr) +u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishFlagAddr, u32 remainAddr) { ERROR_LOG(HLE, "FAKE sceAtracDecodeData(%i, %08x, %08x, %08x, %08x)", atracID, outAddr, numSamplesAddr, finishFlagAddr, remainAddr); @@ -48,76 +50,77 @@ int sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF return 0; } -void sceAtracEndEntry() +u32 sceAtracEndEntry() { - ERROR_LOG(HLE, "UNIMPL sceAtracEndEntry"); - RETURN(0); -} - -void sceAtracGetAtracID() -{ - ERROR_LOG(HLE, "UNIMPL sceAtracGetAtracID"); - RETURN(0); -} - -void sceAtracGetBufferInfoForReseting() -{ - ERROR_LOG(HLE, "UNIMPL sceAtracGetBufferInfoForReseting"); - RETURN(0); -} - -int sceAtracGetBitrate(int atracID, u32 outBitrateAddr) -{ - ERROR_LOG(HLE, "UNIMPL sceAtracGetBitrate"); + ERROR_LOG(HLE, "UNIMPL sceAtracEndEntry(.)"); return 0; } -void sceAtracGetChannel() +u32 sceAtracGetAtracID(int codecType) { - ERROR_LOG(HLE, "UNIMPL sceAtracGetChannel"); - RETURN(0); + int id; + ERROR_LOG(HLE, "UNIMPL sceAtracGetAtracID(%i)", codecType); + return id; } -void sceAtracGetLoopStatus() +u32 sceAtracGetBufferInfoForReseting(int atracID, int sample, u32 bufferInfoAddr) { - ERROR_LOG(HLE, "UNIMPL sceAtracGetLoopStatus"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracGetBufferInfoForReseting(%i, %i, %08x)",atracID, sample, bufferInfoAddr); + return 0; } -void sceAtracGetInternalErrorInfo() +u32 sceAtracGetBitrate(int atracID, u32 outBitrateAddr) { - ERROR_LOG(HLE, "UNIMPL sceAtracGetInternalErrorInfo"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracGetBitrate(%i, %08x)", atracID, outBitrateAddr); + return 0; } -void sceAtracGetMaxSample() +u32 sceAtracGetChannel(int atracID, u32 channelAddr) { - ERROR_LOG(HLE, "UNIMPL sceAtracGetMaxSample"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracGetChannel(%i, %08x)", atracID, channelAddr); + return 0; } -int sceAtracGetNextDecodePosition(int atracID, u32 outposAddr) +u32 sceAtracGetLoopStatus(int atracID, u32 loopNbr, u32 statusAddr) +{ + ERROR_LOG(HLE, "UNIMPL sceAtracGetLoopStatus(%i, %08x, %08x)", atracID, loopNbr, statusAddr ); + return 0; +} + +u32 sceAtracGetInternalErrorInfo(int atracID, u32 errorAddr) +{ + ERROR_LOG(HLE, "UNIMPL sceAtracGetInternalErrorInfo(%i, %08x)", atracID, errorAddr); + return 0; +} + +u32 sceAtracGetMaxSample(int atracID, u32 maxSamplesAddr) +{ + ERROR_LOG(HLE, "UNIMPL sceAtracGetMaxSample(%i, %08x)", atracID, maxSamplesAddr); + return 0; +} + +u32 sceAtracGetNextDecodePosition(int atracID, u32 outposAddr) { ERROR_LOG(HLE, "UNIMPL sceAtracGetNextDecodePosition(%i, %08x)", atracID, outposAddr); Memory::Write_U32(1, outposAddr); // outpos return 0; } -int sceAtracGetNextSample(int atracID, u32 outNAddr) +u32 sceAtracGetNextSample(int atracID, u32 outNAddr) { ERROR_LOG(HLE, "FAKE sceAtracGetNextSample(%i, %08x)", atracID, outNAddr); Memory::Write_U32(0, outNAddr); return 0; } -int sceAtracGetRemainFrame(int atracID, u32 outposAddr) +u32 sceAtracGetRemainFrame(int atracID, u32 outposAddr) { ERROR_LOG(HLE, "sceAtracGetRemainFrame(%i, %08x)", atracID, outposAddr); Memory::Write_U32(12, outposAddr); // outpos return 0; } -int sceAtracGetSecondBufferInfo(int atracID, u32 outposAddr, u32 outBytesAddr) +u32 sceAtracGetSecondBufferInfo(int atracID, u32 outposAddr, u32 outBytesAddr) { ERROR_LOG(HLE, "sceAtracGetSecondBufferInfo(%i, %08x, %08x)", atracID, outposAddr, outBytesAddr); Memory::Write_U32(0, outposAddr); // outpos @@ -125,7 +128,7 @@ int sceAtracGetSecondBufferInfo(int atracID, u32 outposAddr, u32 outBytesAddr) return 0; } -int sceAtracGetSoundSample(int atracID, u32 outEndSampleAddr, u32 outLoopStartSampleAddr, u32 outLoopEndSampleAddr) +u32 sceAtracGetSoundSample(int atracID, u32 outEndSampleAddr, u32 outLoopStartSampleAddr, u32 outLoopEndSampleAddr) { ERROR_LOG(HLE, "UNIMPL sceAtracGetSoundSample(%i, %08x, %08x, %08x)", atracID, outEndSampleAddr, outLoopStartSampleAddr, outLoopEndSampleAddr); Memory::Write_U32(0x10000, outEndSampleAddr); // outEndSample @@ -134,7 +137,7 @@ int sceAtracGetSoundSample(int atracID, u32 outEndSampleAddr, u32 outLoopStartSa return 0; } -int sceAtracGetStreamDataInfo(int atracID, u32 writePointerAddr, u32 availableBytesAddr, u32 readOffsetAddr) +u32 sceAtracGetStreamDataInfo(int atracID, u32 writePointerAddr, u32 availableBytesAddr, u32 readOffsetAddr) { ERROR_LOG(HLE, "FAKE sceAtracGetStreamDataInfo(%i, %08x, %08x, %08x)", atracID, writePointerAddr, availableBytesAddr, readOffsetAddr); Memory::Write_U32(0, readOffsetAddr); @@ -143,58 +146,60 @@ int sceAtracGetStreamDataInfo(int atracID, u32 writePointerAddr, u32 availableBy return 0; } -void sceAtracReleaseAtracID() +u32 sceAtracReleaseAtracID(int atracID) { - ERROR_LOG(HLE, "UNIMPL sceAtracReleaseAtracID"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracReleaseAtracID(%i)", atracID); + return 0; } -void sceAtracResetPlayPosition() +u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFirstBuf, int bytesWrittenSecondBuf) { - ERROR_LOG(HLE, "UNIMPL sceAtracResetPlayPosition"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); + return 0; } -void sceAtracSetHalfwayBuffer() +u32 sceAtracSetHalfwayBuffer(int atracID, u32 halfBuffer, u32 readSize, u32 halfBufferSize) { - ERROR_LOG(HLE, "UNIMPL sceAtracSetHalfwayBuffer"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracSetHalfwayBuffer(%i, %08x, %8x, %8x)", atracID, halfBuffer, readSize, halfBufferSize); + return 0; } -void sceAtracSetSecondBuffer() +u32 sceAtracSetSecondBuffer(int atracID, u32 secondBuffer, u32 secondBufferSize) { - ERROR_LOG(HLE, "UNIMPL sceAtracSetSecondBuffer(%i, %08x, %i)", PARAM(0),PARAM(1),PARAM(2)); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracSetSecondBuffer(%i, %08x, %8x)", atracID, secondBuffer, secondBufferSize); + return 0; } -void sceAtracSetData() +u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) { - ERROR_LOG(HLE, "UNIMPL sceAtracSetData"); - RETURN(0); -} //? + ERROR_LOG(HLE, "UNIMPL sceAtracSetData(%i, %08x, %08x)", atracID, buffer, bufferSize); + return 0; +} -void sceAtracSetDataAndGetID() -{ - ERROR_LOG(HLE, "UNIMPL sceAtracSetDataAndGetID(%08x, %i)", PARAM(0), PARAM(1)); - RETURN(1); +int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize) +{ + int id; + ERROR_LOG(HLE, "UNIMPL sceAtracSetDataAndGetID(%i, %08x, %08x)", buffer, bufferSize); + return id; } -void sceAtracSetHalfwayBufferAndGetID() +int sceAtracSetHalfwayBufferAndGetID(int atracID, u32 halfBuffer, u32 readSize, u32 halfBufferSize) { - ERROR_LOG(HLE, "UNIMPL sceAtracSetHalfwayBufferAndGetID"); - RETURN(0); + int id; + ERROR_LOG(HLE, "UNIMPL sceAtracSetHalfwayBufferAndGetID(%i, %08x, %08x, %08x)", atracID, halfBuffer, readSize, halfBufferSize); + return id; } -void sceAtracStartEntry() +u32 sceAtracStartEntry() { - ERROR_LOG(HLE, "UNIMPL sceAtracStartEntry"); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracStartEntry(.)"); + return 0; } -void sceAtracSetLoopNum() +u32 sceAtracSetLoopNum(int atracID, int loopNum) { - ERROR_LOG(HLE, "UNIMPL sceAtracSetLoopNum(%i, %i)", PARAM(0), PARAM(1)); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceAtracSetLoopNum(%i, %i)", atracID, loopNum); + return 0; } int sceAtracReinit() @@ -206,33 +211,33 @@ int sceAtracReinit() const HLEFunction sceAtrac3plus[] = { - {0x7db31251,WrapI_IU,"sceAtracAddStreamData"}, - {0x6a8c3cd5,WrapI_IUUUU,"sceAtracDecodeData"}, - {0xd5c28cc0,sceAtracEndEntry,"sceAtracEndEntry"}, - {0x780f88d1,sceAtracGetAtracID,"sceAtracGetAtracID"}, - {0xca3ca3d2,sceAtracGetBufferInfoForReseting,"sceAtracGetBufferInfoForReseting"}, - {0xa554a158,WrapI_IU,"sceAtracGetBitrate"}, - {0x31668baa,sceAtracGetChannel,"sceAtracGetChannel"}, - {0xfaa4f89b,sceAtracGetLoopStatus,"sceAtracGetLoopStatus"}, - {0xe88f759b,sceAtracGetInternalErrorInfo,"sceAtracGetInternalErrorInfo"}, - {0xd6a5f2f7,sceAtracGetMaxSample,"sceAtracGetMaxSample"}, - {0xe23e3a35,WrapI_IU,"sceAtracGetNextDecodePosition"}, - {0x36faabfb,WrapI_IU,"sceAtracGetNextSample"}, - {0x9ae849a7,WrapI_IU,"sceAtracGetRemainFrame"}, - {0x83e85ea0,WrapI_IUU,"sceAtracGetSecondBufferInfo"}, - {0xa2bba8be,WrapI_IUUU,"sceAtracGetSoundSample"}, - {0x5d268707,WrapI_IUUU,"sceAtracGetStreamDataInfo"}, - {0x61eb33f5,sceAtracReleaseAtracID,"sceAtracReleaseAtracID"}, - {0x644e5607,sceAtracResetPlayPosition,"sceAtracResetPlayPosition"}, - {0x3f6e26b5,sceAtracSetHalfwayBuffer,"sceAtracSetHalfwayBuffer"}, - {0x83bf7afd,sceAtracSetSecondBuffer,"sceAtracSetSecondBuffer"}, - {0x0E2A73AB,sceAtracSetData,"sceAtracSetData"}, //? - {0x7a20e7af,sceAtracSetDataAndGetID,"sceAtracSetDataAndGetID"}, - {0xd1f59fdb,sceAtracStartEntry,"sceAtracStartEntry"}, - {0x868120b5,sceAtracSetLoopNum,"sceAtracSetLoopNum"}, + {0x7db31251,WrapU_IU,"sceAtracAddStreamData"}, + {0x6a8c3cd5,WrapU_IUUUU,"sceAtracDecodeData"}, + {0xd5c28cc0,WrapU_V,"sceAtracEndEntry"}, + {0x780f88d1,WrapU_I,"sceAtracGetAtracID"}, + {0xca3ca3d2,WrapU_IIU,"sceAtracGetBufferInfoForReseting"}, + {0xa554a158,WrapU_IU,"sceAtracGetBitrate"}, + {0x31668baa,WrapU_IU,"sceAtracGetChannel"}, + {0xfaa4f89b,WrapU_IUU,"sceAtracGetLoopStatus"}, + {0xe88f759b,WrapU_IU,"sceAtracGetInternalErrorInfo"}, + {0xd6a5f2f7,WrapU_IU,"sceAtracGetMaxSample"}, + {0xe23e3a35,WrapU_IU,"sceAtracGetNextDecodePosition"}, + {0x36faabfb,WrapU_IU,"sceAtracGetNextSample"}, + {0x9ae849a7,WrapU_IU,"sceAtracGetRemainFrame"}, + {0x83e85ea0,WrapU_IUU,"sceAtracGetSecondBufferInfo"}, + {0xa2bba8be,WrapU_IUUU,"sceAtracGetSoundSample"}, + {0x5d268707,WrapU_IUUU,"sceAtracGetStreamDataInfo"}, + {0x61eb33f5,WrapU_I,"sceAtracReleaseAtracID"}, + {0x644e5607,WrapU_IIII,"sceAtracResetPlayPosition"}, + {0x3f6e26b5,WrapU_IUUU,"sceAtracSetHalfwayBuffer"}, + {0x83bf7afd,WrapU_IUU,"sceAtracSetSecondBuffer"}, + {0x0E2A73AB,WrapU_IUU,"sceAtracSetData"}, //? + {0x7a20e7af,WrapI_UU,"sceAtracSetDataAndGetID"}, + {0xd1f59fdb,WrapU_V,"sceAtracStartEntry"}, + {0x868120b5,WrapU_II,"sceAtracSetLoopNum"}, {0x132f1eca,WrapI_V,"sceAtracReinit"}, {0xeca32a99,0,"sceAtracIsSecondBufferNeeded"}, - {0x0fae370e,sceAtracSetHalfwayBufferAndGetID,"sceAtracSetHalfwayBufferAndGetID"}, + {0x0fae370e,WrapI_IUUU,"sceAtracSetHalfwayBufferAndGetID"}, {0x2DD3E298,0,"sceAtrac3plus_2DD3E298"}, }; diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index c7317112b9..ca4ce2a0fe 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -634,7 +634,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // We should probably defer to sceGe here, no sense in implementing this stuff in every GPU switch (behaviour) { case 1: // Signal with Wait - ERROR_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + DEBUG_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); break; case 2: DEBUG_LOG(G3D, "Signal without wait. signal/end: %04x %04x", signal, enddata); @@ -1419,7 +1419,7 @@ void GLES_GPU::DoBlockTransfer() int bpp = (gstate.transferstart & 1) ? 4 : 2; - NOTICE_LOG(HLE, "Block transfer: %08x to %08x, %i x %i , ...", srcBasePtr, dstBasePtr, width, height); + DEBUG_LOG(HLE, "Block transfer: %08x to %08x, %i x %i , ...", srcBasePtr, dstBasePtr, width, height); // Do the copy! for (int y = 0; y < height; y++) { From 862a11e7be40e7fe921fd434f222619c299dfddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 23 Dec 2012 11:16:32 +0100 Subject: [PATCH 127/276] Clear some state between runs. Tabs fixing. --- Core/HLE/sceDisplay.cpp | 18 +- Core/HLE/sceKernelThread.cpp | 427 +++++++++++++++++------------------ 2 files changed, 224 insertions(+), 221 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 1a36d9130a..cf28865a48 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -63,12 +63,12 @@ static bool framebufIsLatched; static int enterVblankEvent = -1; static int leaveVblankEvent = -1; -static int hCount = 0; -static int hCountTotal = 0; //unused -static int vCount = 0; -static int isVblank = 0; -static bool hasSetMode = false; -double lastFrameTime = 0; +static int hCount; +static int hCountTotal; //unused +static int vCount; +static int isVblank; +static bool hasSetMode; +double lastFrameTime; // STATE END @@ -110,12 +110,18 @@ void __DisplayInit() CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0); isVblank = 0; vCount = 0; + hCount = 0; + hCountTotal = 0; + hasSetMode = false; + lastFrameTime = 0; InitGfxState(); } void __DisplayShutdown() { + vblankListeners.clear(); + vblankWaitingThreads.clear(); ShutdownGfxState(); } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 113868f9eb..6807fd92d2 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -37,43 +37,42 @@ enum { - ERROR_KERNEL_THREAD_ALREADY_DORMANT = 0x800201a2, - ERROR_KERNEL_THREAD_ALREADY_SUSPEND = 0x800201a3, - ERROR_KERNEL_THREAD_IS_NOT_DORMANT = 0x800201a4, - ERROR_KERNEL_THREAD_IS_NOT_SUSPEND = 0x800201a5, - ERROR_KERNEL_THREAD_IS_NOT_WAIT = 0x800201a6, + ERROR_KERNEL_THREAD_ALREADY_DORMANT = 0x800201a2, + ERROR_KERNEL_THREAD_ALREADY_SUSPEND = 0x800201a3, + ERROR_KERNEL_THREAD_IS_NOT_DORMANT = 0x800201a4, + ERROR_KERNEL_THREAD_IS_NOT_SUSPEND = 0x800201a5, + ERROR_KERNEL_THREAD_IS_NOT_WAIT = 0x800201a6, }; enum { - PSP_THREAD_ATTR_USER = 0x80000000, - PSP_THREAD_ATTR_USBWLAN = 0xa0000000, - PSP_THREAD_ATTR_VSH = 0xc0000000, - PSP_THREAD_ATTR_KERNEL = 0x00001000, - PSP_THREAD_ATTR_VFPU = 0x00004000, // TODO: Should not bother saving VFPU context except when switching between two thread that has this attribute - PSP_THREAD_ATTR_SCRATCH_SRAM = 0x00008000, // Save/restore scratch as part of context??? - PSP_THREAD_ATTR_NO_FILLSTACK = 0x00100000, // TODO: No filling of 0xff - PSP_THREAD_ATTR_CLEAR_STACK = 0x00200000, // TODO: Clear thread stack when deleted + PSP_THREAD_ATTR_USER = 0x80000000, + PSP_THREAD_ATTR_USBWLAN = 0xa0000000, + PSP_THREAD_ATTR_VSH = 0xc0000000, + PSP_THREAD_ATTR_KERNEL = 0x00001000, + PSP_THREAD_ATTR_VFPU = 0x00004000, // TODO: Should not bother saving VFPU context except when switching between two thread that has this attribute + PSP_THREAD_ATTR_SCRATCH_SRAM = 0x00008000, // Save/restore scratch as part of context??? + PSP_THREAD_ATTR_NO_FILLSTACK = 0x00100000, // TODO: No filling of 0xff + PSP_THREAD_ATTR_CLEAR_STACK = 0x00200000, // TODO: Clear thread stack when deleted }; -const char *waitTypeStrings[] = -{ - "NONE", - "Sleep", - "Delay", - "Sema", - "EventFlag", - "Mbx", - "Vpl", - "Fpl", - "", - "ThreadEnd", // These are nonstandard wait types - "AudioChannel", - "Umd", - "Vblank", - "Mutex", - "LwMutex", - "Ctrl", +const char *waitTypeStrings[] = { + "NONE", + "Sleep", + "Delay", + "Sema", + "EventFlag", + "Mbx", + "Vpl", + "Fpl", + "", + "ThreadEnd", // These are nonstandard wait types + "AudioChannel", + "Umd", + "Vblank", + "Mutex", + "LwMutex", + "Ctrl", }; struct SceKernelSysClock { @@ -81,7 +80,6 @@ struct SceKernelSysClock { u32 hi; }; - struct NativeCallback { SceUInt size; @@ -185,9 +183,9 @@ public: nt.waitID, waitInfo.waitValue); } - + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_THID; } - + int GetIDType() const { return SCE_KERNEL_TMID_Thread; } bool AllocateStack(u32 &stackSize) @@ -255,7 +253,7 @@ public: bool isReady() const { return (nt.status & THREADSTATUS_DORMANT) != 0; } bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; } bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; } - + NativeThread nt; ThreadWaitInfo waitInfo; @@ -269,7 +267,7 @@ public: std::set registeredCallbacks[THREAD_CALLBACK_NUM_TYPES]; std::list readyCallbacks[THREAD_CALLBACK_NUM_TYPES]; - + std::list pendingMipsCalls; u32 stackBlock; @@ -319,52 +317,53 @@ Thread *__GetCurrentThread() { u32 __KernelMipsCallReturnAddress() { - return cbReturnHackAddr; + return cbReturnHackAddr; } u32 __KernelInterruptReturnAddress() { - return intReturnHackAddr; + return intReturnHackAddr; } void hleScheduledWakeup(u64 userdata, int cyclesLate); void __KernelThreadingInit() { - u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks" + u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks" dispatchEnabled = true; + g_inCbCount = 0; idleThreadHackAddr = kernelMemory.Alloc(blockSize, false, "threadrethack"); - // Make sure it got allocated where we expect it... at the very start of kernel RAM - //CHECK_EQ(idleThreadHackAddr & 0x3FFFFFFF, 0x08000000); + // Make sure it got allocated where we expect it... at the very start of kernel RAM + //CHECK_EQ(idleThreadHackAddr & 0x3FFFFFFF, 0x08000000); - // Yeah, this is straight out of JPCSP, I should be ashamed. - Memory::Write_U32(MIPS_MAKE_ADDIU(MIPS_REG_A0, MIPS_REG_ZERO, 0), idleThreadHackAddr); - Memory::Write_U32(MIPS_MAKE_LUI(MIPS_REG_RA, 0x0800), idleThreadHackAddr + 4); - Memory::Write_U32(MIPS_MAKE_JR_RA(), idleThreadHackAddr + 8); - //Memory::Write_U32(MIPS_MAKE_SYSCALL("ThreadManForUser", "sceKernelDelayThread"), idleThreadHackAddr + 12); - Memory::Write_U32(MIPS_MAKE_SYSCALL("FakeSysCalls", "_sceKernelIdle"), idleThreadHackAddr + 12); - Memory::Write_U32(MIPS_MAKE_BREAK(), idleThreadHackAddr + 16); + // Yeah, this is straight out of JPCSP, I should be ashamed. + Memory::Write_U32(MIPS_MAKE_ADDIU(MIPS_REG_A0, MIPS_REG_ZERO, 0), idleThreadHackAddr); + Memory::Write_U32(MIPS_MAKE_LUI(MIPS_REG_RA, 0x0800), idleThreadHackAddr + 4); + Memory::Write_U32(MIPS_MAKE_JR_RA(), idleThreadHackAddr + 8); + //Memory::Write_U32(MIPS_MAKE_SYSCALL("ThreadManForUser", "sceKernelDelayThread"), idleThreadHackAddr + 12); + Memory::Write_U32(MIPS_MAKE_SYSCALL("FakeSysCalls", "_sceKernelIdle"), idleThreadHackAddr + 12); + Memory::Write_U32(MIPS_MAKE_BREAK(), idleThreadHackAddr + 16); - threadReturnHackAddr = idleThreadHackAddr + 20; + threadReturnHackAddr = idleThreadHackAddr + 20; WriteSyscall("FakeSysCalls", NID_THREADRETURN, threadReturnHackAddr); - cbReturnHackAddr = threadReturnHackAddr + 8; - WriteSyscall("FakeSysCalls", NID_CALLBACKRETURN, cbReturnHackAddr); + cbReturnHackAddr = threadReturnHackAddr + 8; + WriteSyscall("FakeSysCalls", NID_CALLBACKRETURN, cbReturnHackAddr); - intReturnHackAddr = cbReturnHackAddr + 8; - WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr); + intReturnHackAddr = cbReturnHackAddr + 8; + WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr); eventScheduledWakeup = CoreTiming::RegisterEvent("ScheduledWakeup", &hleScheduledWakeup); - // Create the two idle threads, as well. With the absolute minimal possible priority. - // 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads... - __KernelResetThread(__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL)); - __KernelResetThread(__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL)); - // These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below. + // Create the two idle threads, as well. With the absolute minimal possible priority. + // 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads... + __KernelResetThread(__KernelCreateThread(threadIdleID[0], 0, "idle0", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL)); + __KernelResetThread(__KernelCreateThread(threadIdleID[1], 0, "idle1", idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL)); + // These idle threads are later started in LoadExec, which calls __KernelStartIdleThreads below. - __KernelListenThreadEnd(__KernelCancelWakeup); + __KernelListenThreadEnd(__KernelCancelWakeup); } void __KernelListenThreadEnd(ThreadCallback callback) @@ -384,15 +383,15 @@ void __KernelFireThreadEnd(Thread *thread) void __KernelStartIdleThreads() { - for (int i = 0; i < 2; i++) - { - u32 error; - Thread *t = kernelObjects.Get(threadIdleID[i], error); - t->nt.gpreg = __KernelGetModuleGP(curModule); - t->context.r[MIPS_REG_GP] = t->nt.gpreg; - //t->context.pc += 4; // ADJUSTPC - t->nt.status = THREADSTATUS_READY; - } + for (int i = 0; i < 2; i++) + { + u32 error; + Thread *t = kernelObjects.Get(threadIdleID[i], error); + t->nt.gpreg = __KernelGetModuleGP(curModule); + t->context.r[MIPS_REG_GP] = t->nt.gpreg; + //t->context.pc += 4; // ADJUSTPC + t->nt.status = THREADSTATUS_READY; + } } bool __KernelSwitchOffThread(const char *reason) @@ -421,25 +420,25 @@ bool __KernelSwitchOffThread(const char *reason) void __KernelIdle() { - CoreTiming::Idle(); - // Advance must happen between Idle and Reschedule, so that threads that were waiting for something - // that was triggered at the end of the Idle period must get a chance to be scheduled. - CoreTiming::Advance(); + CoreTiming::Idle(); + // Advance must happen between Idle and Reschedule, so that threads that were waiting for something + // that was triggered at the end of the Idle period must get a chance to be scheduled. + CoreTiming::Advance(); - // In Advance, we might trigger an interrupt such as vblank. - // If we end up in an interrupt, we don't want to reschedule. - // However, we have to reschedule... damn. - __KernelReSchedule("idle"); + // In Advance, we might trigger an interrupt such as vblank. + // If we end up in an interrupt, we don't want to reschedule. + // However, we have to reschedule... damn. + __KernelReSchedule("idle"); } void __KernelThreadingShutdown() { kernelMemory.Free(threadReturnHackAddr); + threadqueue.clear(); threadReturnHackAddr = 0; - cbReturnHackAddr = 0; + cbReturnHackAddr = 0; currentThread = 0; intReturnHackAddr = 0; - threadqueue.clear(); } const char *__KernelGetThreadName(SceUID threadID) @@ -521,29 +520,29 @@ void sceKernelReferThreadStatus() void sceKernelGetThreadExitStatus() { - SceUID threadID = PARAM(0); - if (threadID == 0) - threadID = __KernelGetCurThread(); + SceUID threadID = PARAM(0); + if (threadID == 0) + threadID = __KernelGetCurThread(); - u32 error; - Thread *t = kernelObjects.Get(threadID, error); - if (t) - { - if (t->nt.status == THREADSTATUS_DORMANT) // TODO: can be dormant before starting, too, need to avoid that - { - DEBUG_LOG(HLE,"sceKernelGetThreadExitStatus(%i)", threadID); - RETURN(t->nt.exitStatus); - } - else - { - RETURN(SCE_KERNEL_ERROR_NOT_DORMANT); - } - } - else - { - ERROR_LOG(HLE,"sceKernelGetThreadExitStatus Error %08x", error); - RETURN(SCE_KERNEL_ERROR_UNKNOWN_THID); - } + u32 error; + Thread *t = kernelObjects.Get(threadID, error); + if (t) + { + if (t->nt.status == THREADSTATUS_DORMANT) // TODO: can be dormant before starting, too, need to avoid that + { + DEBUG_LOG(HLE,"sceKernelGetThreadExitStatus(%i)", threadID); + RETURN(t->nt.exitStatus); + } + else + { + RETURN(SCE_KERNEL_ERROR_NOT_DORMANT); + } + } + else + { + ERROR_LOG(HLE,"sceKernelGetThreadExitStatus Error %08x", error); + RETURN(SCE_KERNEL_ERROR_UNKNOWN_THID); + } } u32 sceKernelGetThreadmanIdType(u32 uid) { @@ -597,10 +596,10 @@ void __KernelSaveContext(ThreadContext *ctx) ctx->lo = currentMIPS->lo; ctx->pc = currentMIPS->pc; ctx->fpcond = currentMIPS->fpcond; - // ctx->fcr0 = currentMIPS->fcr0; - // ctx->fcr31 = currentMIPS->fcr31; + // ctx->fcr0 = currentMIPS->fcr0; + // ctx->fcr31 = currentMIPS->fcr31; - // TODO: Make VFPU saving optional/delayed, only necessary between VFPU-attr-marked threads + // TODO: Make VFPU saving optional/delayed, only necessary between VFPU-attr-marked threads } // Loads a CPU context @@ -623,8 +622,8 @@ void __KernelLoadContext(ThreadContext *ctx) currentMIPS->lo = ctx->lo; currentMIPS->pc = ctx->pc; currentMIPS->fpcond = ctx->fpcond; - // currentMIPS->fcr0 = ctx->fcr0; - // currentMIPS->fcr31 = ctx->fcr31; + // currentMIPS->fcr0 = ctx->fcr0; + // currentMIPS->fcr31 = ctx->fcr31; } u32 __KernelResumeThreadFromWait(SceUID threadID) @@ -723,7 +722,7 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time // TODO: time waster char temp[256]; sprintf(temp, "started wait %s", waitTypeStrings[(int)type]); - + hleReSchedule(processCallbacks, temp); // TODO: Remove thread from Ready queue? } @@ -746,21 +745,21 @@ void __KernelCancelWakeup(SceUID threadID) void __KernelRemoveFromThreadQueue(Thread *t) { - for (size_t i = 0; i < threadqueue.size(); i++) - { - if (threadqueue[i] == t) - { + for (size_t i = 0; i < threadqueue.size(); i++) + { + if (threadqueue[i] == t) + { DEBUG_LOG(HLE, "Deleted thread %p (%i) from thread queue", t, t->GetUID()); - threadqueue.erase(threadqueue.begin() + i); - return; - } - } + threadqueue.erase(threadqueue.begin() + i); + return; + } + } } Thread *__KernelNextThread() { // round-robin scheduler // seems to work ? - // not accurate! + // not accurate! int bestthread = -1; int prio = 0xffffff; @@ -852,53 +851,51 @@ void __KernelReSchedule(bool doCallbacks, const char *reason) } } - - ////////////////////////////////////////////////////////////////////////// // Thread Management ////////////////////////////////////////////////////////////////////////// void sceKernelCheckThreadStack() { - u32 error; - Thread *t = kernelObjects.Get(__KernelGetCurThread(), error); - u32 diff = abs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP])); - ERROR_LOG(HLE, "%i=sceKernelCheckThreadStack()", diff); + u32 error; + Thread *t = kernelObjects.Get(__KernelGetCurThread(), error); + u32 diff = abs((long)((s64)t->stackBlock - (s64)currentMIPS->r[MIPS_REG_SP])); + ERROR_LOG(HLE, "%i=sceKernelCheckThreadStack()", diff); RETURN(diff); //Blatant lie } void ThreadContext::reset() { - for (int i = 0; i<32; i++) - { - r[i] = 0; - f[i] = 0.0f; - } - for (int i = 0; i<128; i++) - { - v[i] = 0.0f; - } - for (int i = 0; i<15; i++) - { - vfpuCtrl[i] = 0x00000000; - } - vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // neutral - vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // neutral - vfpuCtrl[VFPU_CTRL_DPREFIX] = 0x0; // neutral - vfpuCtrl[VFPU_CTRL_CC] = 0x3f; - vfpuCtrl[VFPU_CTRL_INF4] = 0; - vfpuCtrl[VFPU_CTRL_RCX0] = 0x3f800001; - vfpuCtrl[VFPU_CTRL_RCX1] = 0x3f800002; - vfpuCtrl[VFPU_CTRL_RCX2] = 0x3f800004; - vfpuCtrl[VFPU_CTRL_RCX3] = 0x3f800008; - vfpuCtrl[VFPU_CTRL_RCX4] = 0x3f800000; - vfpuCtrl[VFPU_CTRL_RCX5] = 0x3f800000; - vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; - vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; - fpcond = 0; - fcr0 = 0; - fcr31 = 0; - hi = 0; - lo = 0; + for (int i = 0; i<32; i++) + { + r[i] = 0; + f[i] = 0.0f; + } + for (int i = 0; i<128; i++) + { + v[i] = 0.0f; + } + for (int i = 0; i<15; i++) + { + vfpuCtrl[i] = 0x00000000; + } + vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // neutral + vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // neutral + vfpuCtrl[VFPU_CTRL_DPREFIX] = 0x0; // neutral + vfpuCtrl[VFPU_CTRL_CC] = 0x3f; + vfpuCtrl[VFPU_CTRL_INF4] = 0; + vfpuCtrl[VFPU_CTRL_RCX0] = 0x3f800001; + vfpuCtrl[VFPU_CTRL_RCX1] = 0x3f800002; + vfpuCtrl[VFPU_CTRL_RCX2] = 0x3f800004; + vfpuCtrl[VFPU_CTRL_RCX3] = 0x3f800008; + vfpuCtrl[VFPU_CTRL_RCX4] = 0x3f800000; + vfpuCtrl[VFPU_CTRL_RCX5] = 0x3f800000; + vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; + vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; + fpcond = 0; + fcr0 = 0; + fcr31 = 0; + hi = 0; + lo = 0; } void __KernelResetThread(Thread *t) @@ -971,7 +968,7 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr u32 location = mipsr4k.r[MIPS_REG_SP]; mipsr4k.r[MIPS_REG_A1] = location; for (int i = 0; i < args; i++) - Memory::Write_U8(argp[i], location + i); + Memory::Write_U8(argp[i], location + i); } @@ -1016,12 +1013,12 @@ int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) if (argBlockPtr && argSize > 0) { startThread->context.r[MIPS_REG_A0] = argSize; - startThread->context.r[MIPS_REG_A1] = sp; + startThread->context.r[MIPS_REG_A1] = sp; } else { startThread->context.r[MIPS_REG_A0] = 0; - startThread->context.r[MIPS_REG_A1] = 0; + startThread->context.r[MIPS_REG_A1] = 0; } startThread->context.r[MIPS_REG_GP] = startThread->nt.gpreg; @@ -1064,16 +1061,16 @@ void sceKernelGetThreadStackFreeSize() } } - // Scan the stack for 0xFF - int sz = 0; - for (u32 addr = thread->stackBlock; addr < thread->stackBlock + thread->nt.stackSize; addr++) - { - if (Memory::Read_U8(addr) != 0xFF) - break; - sz++; - } + // Scan the stack for 0xFF + int sz = 0; + for (u32 addr = thread->stackBlock; addr < thread->stackBlock + thread->nt.stackSize; addr++) + { + if (Memory::Read_U8(addr) != 0xFF) + break; + sz++; + } - RETURN(sz & ~3); + RETURN(sz & ~3); } // Internal function @@ -1116,46 +1113,46 @@ void sceKernelExitThread() void _sceKernelExitThread() { - ERROR_LOG(HLE,"_sceKernelExitThread FAKED"); - currentThread->nt.status = THREADSTATUS_DORMANT; - currentThread->nt.exitStatus = PARAM(0); - __KernelFireThreadEnd(currentThread); + ERROR_LOG(HLE,"_sceKernelExitThread FAKED"); + currentThread->nt.status = THREADSTATUS_DORMANT; + currentThread->nt.exitStatus = PARAM(0); + __KernelFireThreadEnd(currentThread); - //Find threads that waited for this one - // Wake them - if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - hleReSchedule("exit-deleted thread"); + //Find threads that waited for this one + // Wake them + if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) + hleReSchedule("exit-deleted thread"); // The stack will be deallocated when the thread is deleted. } void sceKernelExitDeleteThread() { - int threadHandle = __KernelGetCurThread(); - u32 error; - Thread *t = kernelObjects.Get(threadHandle, error); - if (t) - { - INFO_LOG(HLE,"sceKernelExitDeleteThread()"); - currentThread->nt.status = THREADSTATUS_DORMANT; - currentThread->nt.exitStatus = PARAM(0); + int threadHandle = __KernelGetCurThread(); + u32 error; + Thread *t = kernelObjects.Get(threadHandle, error); + if (t) + { + INFO_LOG(HLE,"sceKernelExitDeleteThread()"); + currentThread->nt.status = THREADSTATUS_DORMANT; + currentThread->nt.exitStatus = PARAM(0); __KernelFireThreadEnd(currentThread); //userMemory.Free(currentThread->stackBlock); currentThread->stackBlock = 0; - __KernelRemoveFromThreadQueue(t); - currentThread = 0; + __KernelRemoveFromThreadQueue(t); + currentThread = 0; - RETURN(kernelObjects.Destroy(threadHandle)); + RETURN(kernelObjects.Destroy(threadHandle)); - __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); - } - else - { - ERROR_LOG(HLE,"sceKernelExitDeleteThread() ERROR - could not find myself!"); - RETURN(error); - } -} + __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); + } + else + { + ERROR_LOG(HLE,"sceKernelExitDeleteThread() ERROR - could not find myself!"); + RETURN(error); + } +} u32 sceKernelSuspendDispatchThread() { @@ -1185,7 +1182,7 @@ int sceKernelDeleteThread(int threadHandle) { //TODO: remove from threadqueue! DEBUG_LOG(HLE,"sceKernelDeleteThread(%i)",threadHandle); - + u32 error; Thread *t = kernelObjects.Get(threadHandle, error); if (t) @@ -1375,7 +1372,7 @@ void sceKernelCancelWakeupThread() t->nt.wakeupCount = 0; DEBUG_LOG(HLE,"sceKernelCancelWakeupThread(%i) - wakeupCount reset from %i", uid, wCount); RETURN(wCount); - } + } else { ERROR_LOG(HLE,"sceKernelCancelWakeupThread(%i) - bad thread id", uid); RETURN(error); @@ -1429,24 +1426,24 @@ void sceKernelWaitThreadEnd() void sceKernelWaitThreadEndCB() { - SceUID id = PARAM(0); - DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id); - u32 error; - Thread *t = kernelObjects.Get(id, error); - if (t) - { - if (t->nt.status != THREADSTATUS_DORMANT) { - __KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, true); - } else { + SceUID id = PARAM(0); + DEBUG_LOG(HLE,"sceKernelWaitThreadEnd(%i)",id); + u32 error; + Thread *t = kernelObjects.Get(id, error); + if (t) + { + if (t->nt.status != THREADSTATUS_DORMANT) { + __KernelWaitCurThread(WAITTYPE_THREADEND, id, 0, 0, true); + } else { DEBUG_LOG(HLE,"sceKernelWaitThreadEnd - thread %i already ended. Doing nothing.", id); } __KernelCheckCallbacks(); - } - else - { - ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id); - } - RETURN(0); + } + else + { + ERROR_LOG(HLE,"sceKernelWaitThreadEnd - bad thread %i", id); + } + RETURN(0); } void sceKernelSuspendThread() @@ -1475,14 +1472,14 @@ u32 __KernelCreateCallback(const char *name, u32 entrypoint, u32 commonArg) SceUID id = kernelObjects.Create(cb); cb->nc.size = sizeof(NativeCallback); - strncpy(cb->nc.name, name, 32); - + strncpy(cb->nc.name, name, 32); + cb->nc.entrypoint = entrypoint; cb->nc.threadId = __KernelGetCurThread(); cb->nc.commonArgument = commonArg; cb->nc.notifyCount = 0; cb->nc.notifyArg = 0; - + cb->forceDelete = false; return id; @@ -1531,7 +1528,7 @@ void sceKernelCancelCallback() Callback *cb = kernelObjects.Get(cbId, error); if (cb) { // This is what JPCSP does. Huh? - cb->nc.notifyArg = 0; + cb->nc.notifyArg = 0; RETURN(0); } else { ERROR_LOG(HLE,"sceKernelCancelCallback(%i) - bad cbId", cbId); @@ -1819,7 +1816,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo call->numArgs = args.size(); call->doAfter = afterAction; call->tag = "callAddress"; - + int callId = mipsCalls.add(call); bool called = false; @@ -1841,7 +1838,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo } } } - + void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) { if (g_inCbCount > 0) { @@ -1849,7 +1846,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) } DEBUG_LOG(HLE, "Executing mipscall %i", callId); MipsCall *call = mipsCalls.get(callId); - + // Save the few regs that need saving call->savedPc = currentMIPS->pc; call->savedRa = currentMIPS->r[MIPS_REG_RA]; From 4a4d126dc7c6e5d061127e82c8f31335e9d9d9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 23 Dec 2012 11:19:55 +0100 Subject: [PATCH 128/276] Init/shutdown mutex --- Core/HLE/sceKernel.cpp | 2 ++ Core/HLE/sceKernelMutex.cpp | 9 ++++++++- Core/HLE/sceKernelMutex.h | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index adcc652b84..d4a34dc894 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -77,6 +77,7 @@ void __KernelInit() __KernelMemoryInit(); __KernelThreadingInit(); + __KernelMutexInit(); __IoInit(); __AudioInit(); __SasInit(); @@ -115,6 +116,7 @@ void __KernelShutdown() __IoShutdown(); __InterruptsShutdown(); __KernelThreadingShutdown(); + __KernelMutexShutdown(); __KernelMemoryShutdown(); CoreTiming::ClearPendingEvents(); diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 77d2a957c6..c4c4b6e1fc 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -123,6 +123,13 @@ void __KernelMutexInit() __KernelListenThreadEnd(&__KernelMutexThreadEnd); mutexInitComplete = true; + mutexWaitTimer = 0; + lwMutexWaitTimer = 0; +} + +void __KernelMutexShutdown() +{ + mutexHeldLocks.clear(); } void __KernelMutexAcquireLock(Mutex *mutex, int count, SceUID thread) @@ -856,4 +863,4 @@ int sceKernelUnlockLwMutex(u32 workareaPtr, int count) Memory::WriteStruct(workareaPtr, &workarea); return 0; -} \ No newline at end of file +} diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index 8d7c09e9f2..de54371948 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -34,4 +34,7 @@ int sceKernelUnlockLwMutex(u32 workareaPtr, int count); void __KernelMutexTimeout(u64 userdata, int cyclesLate); void __KernelLwMutexTimeout(u64 userdata, int cyclesLate); -void __KernelMutexThreadEnd(SceUID thread); \ No newline at end of file +void __KernelMutexThreadEnd(SceUID thread); + +void __KernelMutexInit(); +void __KernelMutexShutdown(); From 8d7ec80e93a6300c0609f7793ecdfc275e62ff44 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 23 Dec 2012 20:26:18 +1000 Subject: [PATCH 129/276] Fix Qt compile for ARM processors. Update README for Qt frontend. --- Qt/Settings.pri | 10 +++++----- README.md | 30 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Qt/Settings.pri b/Qt/Settings.pri index 320a37ca37..5db0598e91 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -5,14 +5,14 @@ unix:!blackberry:!macx: CONFIG += linux QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter # Arch specific -contains(QT_ARCH, arm): { - DEFINES += ARM - CONFIG += arm -} -contains(QT_ARCH, x86)|contains(QT_ARCH, x86_64): { +contains(QT_ARCH, i686)|contains(QT_ARCH, x86)|contains(QT_ARCH, x86_64): { QMAKE_CXXFLAGS += -msse2 CONFIG += x86 } +else { # Assume ARM + DEFINES += ARM + CONFIG += arm +} mobile_platform: DEFINES += USING_GLES2 diff --git a/README.md b/README.md index 40b4544486..1d94abdab2 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,9 @@ Of course in-tree builds are supported, but that makes cleanup harder to do; with out-of-tree builds you can just remove the `build` directory. +Note: There is also a Qt frontend available. Simply compile +PPSSPPQt.pro from [QtCreator][qt-creator]. + Building for Linux/BSD/etc -------------------------- @@ -51,7 +54,9 @@ Install the libsdl1.2 (SDL 1.2) development headers. This is called `sdl12` on BSD ports. Currently the user interface is identical to Android's, operated -with the mouse. A Qt-based interface is planned. +with the mouse. + +Alternatively, a Qt-based frontend is available in the Qt/ dir. Building for OSX ---------------- @@ -92,10 +97,7 @@ other than Microsoft's, but `NMake Makefiles` works fine. Building for Blackberry ----------------------- -To build for Blackberry, you must first have the latest Native SDK installed -from developer.blackberry.com/native and have compiled the SDL port available -from github.com/blackberry/SDL to your NDK workspace. Then checkout the latest -version of PPSSPP to your NDK workspace. +To build for Blackberry, you must first have the [latest Native SDK][blackberry-ndk] installed. To set up your environment for cross-compiling you must then use: source ~/bbndk/bbndk-env.sh @@ -105,20 +107,28 @@ Finally, you are ready to compile. Change directory to ppsspp/SDL and run: If you are on Windows, you will need GNU and CMake to run the bash script. -Alternatively, you can use the Qt UI by compiling the PPSSPPQt.pro in the Qt/ -directory with qmake from the NDK or QtCreator 2.6+. +Alternatively, you can use the Qt frontend by compiling the PPSSPPQt.pro in +the Qt/ directory with `qmake` from the NDK or [QtCreator 2.6+][qt-creator]. Building for Symbian -------------------- To build for Symbian, you require: -1) GCC 4.6.3 from Mentor Graphics: http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/ -2) Symbian Qt libraries. You can find these in the final Nokia Qt SDK. -Then simply compile the PPSSPPQt.pro with qmake from the SDK or QtCreator 2.6+. +1) [GCC 4.6.3][symbian-gcc] from Mentor Graphics. + +2) Symbian Qt libraries. You can find these in the final Nokia Qt SDK or online. + +Then simply compile the PPSSPPQt.pro with `qmake` from the SDK or [QtCreator 2.6+][qt-creator]. [ppsspp-repo]: "https://github.com/hrydgard/ppsspp" [ppsspp-devel]: "http://www.ppsspp.org/development.html" +[qt-creator]: + "http://qt-project.org/downloads" +[blackberry-ndk]: + "http://developer.blackberry.com/native" +[symbian-gcc]: + "http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/" From 9af2325be5ad3aa091d9ecf2df2c06c13741d24b Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 23 Dec 2012 22:52:00 +0800 Subject: [PATCH 130/276] Fix massive corrupted graphic in FF Type-0 --- GPU/GLES/TransformPipeline.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index bece8c27e8..4961d9e6cf 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -640,6 +640,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } break; } + Flush(); } void GLES_GPU::Flush() From c7a9c408270cc188be90b3afb5efc2b7cbcf00ce Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 23 Dec 2012 23:27:54 +0800 Subject: [PATCH 131/276] Fix audio crash in FF type-0 --- Core/HW/SasAudio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index d8025e7196..6b56144d31 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -215,7 +215,7 @@ 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; @@ -491,4 +491,4 @@ void ADSREnvelope::KeyOn() { void ADSREnvelope::KeyOff() { SetState(STATE_RELEASE); height_ = sustainLevel; -} \ No newline at end of file +} From 764a75df1aef0245f8cad08ce2e636f6f7a14143 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 00:42:28 +0800 Subject: [PATCH 132/276] Add 3 new functions for sceVaudio --- Core/HLE/sceVaudio.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index 8b7168e631..68493f583d 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -19,13 +19,13 @@ #include "FunctionWrappers.h" #include "sceVaudio.h" -u32 sceVaudioOutputBlocking() { - ERROR_LOG(HLE, "UNIMPL sceVaudioOutputBlocking(...)"); +u32 sceVaudioOutputBlocking(int vol, u32 buffer) { + ERROR_LOG(HLE, "UNIMPL sceVaudioOutputBlocking(%i, %08x)", vol, buffer); return 0; } -u32 sceVaudioChReserve() { - ERROR_LOG(HLE, "UNIMPL sceVaudioChReserve(...)"); +u32 sceVaudioChReserve(int sampleCount, int freq, int format) { + ERROR_LOG(HLE, "UNIMPL sceVaudioChReserve(%i, %i, %i)", sampleCount, freq, format); return 0; } @@ -34,10 +34,22 @@ u32 sceVaudioChRelease() { return 0; } +u32 sceVaudioSetEffectType(int effectType, int vol) { + ERROR_LOG(HLE, "UNIMPL sceVaudioSetEffectType(%i, %i)", effectType, vol); + return 0; +} + +u32 sceVaudioSetAlcMode(int alcMode) { + ERROR_LOG(HLE, "UNIMPL sceVaudioSetAlcMode(%i)", alcMode); + return 0; +} + const HLEFunction sceVaudio[] = { - {0x03b6807d, WrapU_V, "sceVaudioOutputBlockingFunction"}, - {0x67585dfd, WrapU_V, "sceVaudioChReserveFunction"}, + {0x03b6807d, WrapU_IU, "sceVaudioOutputBlockingFunction"}, + {0x67585dfd, WrapU_III, "sceVaudioChReserveFunction"}, {0x8986295e, WrapU_V, "sceVaudioChReleaseFunction"}, + {0x346FBE94, WrapU_II, "sceVaudioSetEffectType"}, + {0xCBD4AC51, WrapU_I, "sceVaudioSetAlcMode"}, }; void Register_sceVaudio() { From 415be25653ecfcbab12390e7a94601effaa2bed7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 00:43:42 +0800 Subject: [PATCH 133/276] Add WrapU_II for functions in SceVaudio --- Core/HLE/FunctionWrappers.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index a6b2c0284f..375ca7d87d 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -310,6 +310,11 @@ template void WrapU_III() { RETURN(retval); } +template void WrapU_II() { + u32 retval = func(PARAM(0), PARAM(1)); + RETURN(retval); +} + template void WrapU_IIII() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); From f2cb19d7ba076e65520af8e4ec009b49d4174f91 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 08:52:51 -0800 Subject: [PATCH 134/276] Switch OSK to using a std::string buffer. Back as a class member, hurray. --- Core/Dialog/PSPOskDialog.cpp | 41 +++++++++++------------------------- Core/Dialog/PSPOskDialog.h | 3 +-- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index e4cc8331cb..a6cfbf9201 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -30,8 +30,6 @@ const char oskKeys[NUMKEYROWS][KEYSPERROW] = {'Z','X','C','V','B','N','M',',','.','/','?','\\','\0'}, }; -char inputChars[255]; // must be a better way of doing this... - PSPOskDialog::PSPOskDialog() : PSPDialog() { @@ -69,10 +67,9 @@ int PSPOskDialog::Init(u32 oskPtr) memset(&oskParams, 0, sizeof(oskParams)); memset(&oskData, 0, sizeof(oskData)); // TODO: should this be init'd to oskIntext? - memset(inputChars, 0x00, sizeof(inputChars)); + inputChars.clear(); oskParamsAddr = oskPtr; selectedChar = 0; - currentInputChar = 0; if (Memory::IsValidAddress(oskPtr)) { @@ -83,13 +80,6 @@ int PSPOskDialog::Init(u32 oskPtr) HackyGetStringWide(oskOuttext, oskData.outtextPtr); Memory::WriteStruct(oskParams.SceUtilityOskDataPtr, &oskData); Memory::WriteStruct(oskPtr, &oskParams); - - if (oskData.outtextlimit >= sizeof(inputChars)) - { - // TODO: Check actual behavior. - ERROR_LOG(HLE, "OskDialog requested %d characters, failing", oskData.outtextlimit); - return -1; - } } else { @@ -118,9 +108,9 @@ void PSPOskDialog::RenderKeyboard() for (int i = 0; i < limit; ++i) { u32 color = 0xFFFFFFFF; - if (inputChars[i] != 0) + if (i < inputChars.size()) temp[0] = inputChars[i]; - else if (currentInputChar == i) + else if (i == inputChars.size()) { temp[0] = oskKeys[selectedRow][selectedExtra]; color = 0xFF3060FF; @@ -212,23 +202,13 @@ void PSPOskDialog::Update() // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) { - if (currentInputChar < limit) - { - inputChars[currentInputChar]= oskKeys[selectedRow][selectedExtra]; - currentInputChar++; - } - else - { - currentInputChar = limit; // just in case - } + if (inputChars.size() < limit) + inputChars += oskKeys[selectedRow][selectedExtra]; } else if (IsButtonPressed(CTRL_CIRCLE)) { - if (currentInputChar > 0) - { - inputChars[currentInputChar] = 0x00; - currentInputChar--; - } + if (inputChars.size() > 0) + inputChars.resize(inputChars.size() - 1); } else if (IsButtonPressed(CTRL_START)) { @@ -243,10 +223,13 @@ void PSPOskDialog::Update() for (int i = 0; i < limit; ++i) { - Memory::Write_U16(0x0000^inputChars[i],oskData.outtextPtr + (2*i)); + u16 value = 0; + if (i < inputChars.size()) + value = 0x0000 ^ inputChars[i]; + Memory::Write_U16(value, oskData.outtextPtr + (2 * i)); } - oskData.outtextlength = currentInputChar; + oskData.outtextlength = inputChars.size(); oskParams.base.result= 0; oskData.result = PSP_UTILITY_OSK_RESULT_CHANGED; Memory::WriteStruct(oskParams.SceUtilityOskDataPtr, &oskData); diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h index 76ea15c1c3..9939923499 100644 --- a/Core/Dialog/PSPOskDialog.h +++ b/Core/Dialog/PSPOskDialog.h @@ -157,8 +157,7 @@ private: std::string oskOuttext; int oskParamsAddr; - int currentInputChar; int selectedChar; - + std::string inputChars; }; From 1c4409e082b2d235c3a844fdebf26315bb772b13 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 08:59:34 -0800 Subject: [PATCH 135/276] Naive fix for repeat rate issues in OSK. Not sure if the latch should actually be consumed but makes sense. Needs tests. --- Core/Dialog/PSPOskDialog.cpp | 10 +++++----- Core/HLE/sceCtrl.cpp | 7 +++++++ Core/HLE/sceCtrl.h | 3 ++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index a6cfbf9201..3400c80dbe 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -108,7 +108,7 @@ void PSPOskDialog::RenderKeyboard() for (int i = 0; i < limit; ++i) { u32 color = 0xFFFFFFFF; - if (i < inputChars.size()) + if (i < (int) inputChars.size()) temp[0] = inputChars[i]; else if (i == inputChars.size()) { @@ -146,7 +146,7 @@ void PSPOskDialog::RenderKeyboard() void PSPOskDialog::Update() { - buttons = __CtrlPeekButtons(); + buttons = __CtrlReadLatch(); int selectedRow = selectedChar / (KEYSPERROW-1); int selectedExtra = selectedChar % (KEYSPERROW-1); @@ -179,7 +179,7 @@ void PSPOskDialog::Update() } else if (IsButtonPressed(CTRL_DOWN)) { - selectedChar -=10; + selectedChar -= 10; } else if (IsButtonPressed(CTRL_LEFT)) { @@ -202,7 +202,7 @@ void PSPOskDialog::Update() // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) { - if (inputChars.size() < limit) + if ((int) inputChars.size() < limit) inputChars += oskKeys[selectedRow][selectedExtra]; } else if (IsButtonPressed(CTRL_CIRCLE)) @@ -224,7 +224,7 @@ void PSPOskDialog::Update() for (int i = 0; i < limit; ++i) { u16 value = 0; - if (i < inputChars.size()) + if (i < (int) inputChars.size()) value = 0x0000 ^ inputChars[i]; Memory::Write_U16(value, oskData.outtextPtr + (2 * i)); } diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 73e03def9d..bbcde95559 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -125,6 +125,13 @@ u32 __CtrlPeekButtons() return ctrlCurrent.buttons; } +u32 __CtrlReadLatch() +{ + u32 ret = latch.btnMake; + __CtrlResetLatch(); + return ret; +} + // Functions so that the rest of the emulator can control what the sceCtrl interface should return // to the game: diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index 2f658d73c0..dcb465f305 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -40,4 +40,5 @@ void __CtrlButtonUp(u32 buttonBit); void __CtrlSetAnalog(float x, float y); // For use by internal UI like MsgDialog -u32 __CtrlPeekButtons(); \ No newline at end of file +u32 __CtrlPeekButtons(); +u32 __CtrlReadLatch(); \ No newline at end of file From 2bdaaba2ab39f686f1b6b9d6a6c5feebf545f6f8 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 00:55:54 +0800 Subject: [PATCH 136/276] Change MAX_CHANNEL to PSP_AUDIO_CHANNEL_MAX --- Core/HLE/__sceAudio.cpp | 2 +- Core/HLE/sceAudio.cpp | 24 ++++++++++++------------ Core/HLE/sceAudio.h | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index fc474706f0..7676ac0ea6 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -132,7 +132,7 @@ void __AudioUpdate() s32 mixBuffer[hwBlockSize * 2]; memset(mixBuffer, 0, sizeof(mixBuffer)); - for (int i = 0; i < MAX_CHANNEL; i++) + for (int i = 0; i < PSP_AUDIO_CHANNEL_MAX; i++) { if (!chans[i].reserved) continue; diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 6184e18cdd..0bd420577d 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -41,7 +41,7 @@ u32 sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr) { ERROR_LOG(HLE, "sceAudioOutputBlocking - Sample pointer null"); return 0; } - if (chan >= MAX_CHANNEL) { + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioOutputBlocking() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } else if (!chans[chan].reserved) { @@ -60,7 +60,7 @@ u32 sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 sampleP if (samplePtr == 0) { ERROR_LOG(HLE, "sceAudioOutputPannedBlocking - Sample pointer null"); return 0; - } else if (chan >= MAX_CHANNEL) { + } else if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioOutputPannedBlocking() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } else if (!chans[chan].reserved) { @@ -77,7 +77,7 @@ u32 sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 sampleP u32 sceAudioOutput(u32 chan, u32 vol, u32 samplePtr) { - if (chan >= MAX_CHANNEL) { + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioOutput() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } @@ -99,7 +99,7 @@ u32 sceAudioOutput(u32 chan, u32 vol, u32 samplePtr) u32 sceAudioOutputPanned(u32 chan, u32 leftVol, u32 rightVol, u32 samplePtr) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioOutputPanned() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -122,7 +122,7 @@ u32 sceAudioOutputPanned(u32 chan, u32 leftVol, u32 rightVol, u32 samplePtr) int sceAudioGetChannelRestLen(u32 chan) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE, "sceAudioGetChannelRestLen(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -135,7 +135,7 @@ int sceAudioGetChannelRestLen(u32 chan) int sceAudioGetChannelRestLength(u32 chan) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE, "sceAudioGetChannelRestLength(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -148,7 +148,7 @@ int sceAudioGetChannelRestLength(u32 chan) static int GetFreeChannel() { - for (int i = 0; i < MAX_CHANNEL; i++) + for (int i = 0; i < PSP_AUDIO_CHANNEL_MAX ; i++) if (!chans[i].reserved) return i; return -1; @@ -166,7 +166,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun return SCE_ERROR_AUDIO_NO_CHANNELS_AVAILABLE; } - if (channel >= MAX_CHANNEL) + if (channel >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE ,"sceAudioChReserve(channel = %d, sampleCount = %d, format = %d) - BAD CHANNEL", channel, sampleCount, format); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -191,7 +191,7 @@ u32 sceAudioChReserve(u32 channel, u32 sampleCount, u32 format) //.Allocate soun u32 sceAudioChRelease(u32 chan) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE, "sceAudioChRelease(%i) - BAD CHANNEL", chan); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -210,7 +210,7 @@ u32 sceAudioChRelease(u32 chan) u32 sceAudioSetChannelDataLen(u32 chan, u32 len) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - BAD CHANNEL", chan, len); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -230,7 +230,7 @@ u32 sceAudioSetChannelDataLen(u32 chan, u32 len) u32 sceAudioChangeChannelConfig(u32 chan, u32 format) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - invalid channel number", chan, format); return SCE_ERROR_AUDIO_INVALID_CHANNEL; @@ -250,7 +250,7 @@ u32 sceAudioChangeChannelConfig(u32 chan, u32 format) u32 sceAudioChangeChannelVolume(u32 chan, u32 lvolume, u32 rvolume) { - if (chan >= MAX_CHANNEL) + if (chan >= PSP_AUDIO_CHANNEL_MAX) { ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - invalid channel number", chan, lvolume, rvolume); return SCE_ERROR_AUDIO_INVALID_CHANNEL; diff --git a/Core/HLE/sceAudio.h b/Core/HLE/sceAudio.h index 6f1305b0d6..ba37523c36 100644 --- a/Core/HLE/sceAudio.h +++ b/Core/HLE/sceAudio.h @@ -36,7 +36,7 @@ enum PspAudioFrequencies { PSP_AUDIO_FREQ_44K = 44100, PSP_AUDIO_FREQ_48K = 48 #define SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED 0x80260008 #define SCE_ERROR_AUDIO_NOT_OUTPUT 0x80260009 -#define MAX_CHANNEL 8 +#define PSP_AUDIO_CHANNEL_MAX 8 struct AudioChannel { From 64d8763d0a5c8244e649764fb76a88863ec3f7dd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 09:05:01 -0800 Subject: [PATCH 137/276] Fix left/right/up/down wrapping issues in OSK. --- Core/Dialog/PSPOskDialog.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 3400c80dbe..a4feb82cde 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -20,9 +20,9 @@ #include "../HLE/sceCtrl.h" #define NUMKEYROWS 4 -#define KEYSPERROW 13 -#define NUMBEROFVALIDCHARS 44 -const char oskKeys[NUMKEYROWS][KEYSPERROW] = +#define KEYSPERROW 12 +#define NUMBEROFVALIDCHARS (KEYSPERROW * NUMKEYROWS) +const char oskKeys[NUMKEYROWS][KEYSPERROW + 1] = { {'1','2','3','4','5','6','7','8','9','0','-','+','\0'}, {'Q','W','E','R','T','Y','U','I','O','P','[',']','\0'}, @@ -92,8 +92,8 @@ int PSPOskDialog::Init(u32 oskPtr) void PSPOskDialog::RenderKeyboard() { - int selectedRow = selectedChar / (KEYSPERROW-1); - int selectedExtra = selectedChar % (KEYSPERROW-1); + int selectedRow = selectedChar / KEYSPERROW; + int selectedExtra = selectedChar % KEYSPERROW; char SelectedLine[KEYSPERROW + 1]; char temp[2]; @@ -147,8 +147,8 @@ void PSPOskDialog::RenderKeyboard() void PSPOskDialog::Update() { buttons = __CtrlReadLatch(); - int selectedRow = selectedChar / (KEYSPERROW-1); - int selectedExtra = selectedChar % (KEYSPERROW-1); + int selectedRow = selectedChar / KEYSPERROW; + int selectedExtra = selectedChar % KEYSPERROW; int limit = oskData.outtextlimit; // TODO: Test more thoroughly. Encountered a game where this was 0. @@ -175,11 +175,11 @@ void PSPOskDialog::Update() if (IsButtonPressed(CTRL_UP)) { - selectedChar += 10; + selectedChar -= KEYSPERROW; } else if (IsButtonPressed(CTRL_DOWN)) { - selectedChar -= 10; + selectedChar += KEYSPERROW; } else if (IsButtonPressed(CTRL_LEFT)) { @@ -190,14 +190,7 @@ void PSPOskDialog::Update() selectedChar++; } - if (selectedChar < 0) - { - selectedChar = NUMBEROFVALIDCHARS; - } - if (selectedChar > NUMBEROFVALIDCHARS) - { - selectedChar = 0; - } + selectedChar = (selectedChar + NUMBEROFVALIDCHARS) % NUMBEROFVALIDCHARS; // TODO : Dialogs should take control over input and not send them to the game while displaying if (IsButtonPressed(CTRL_CROSS)) From f7878c83510afb1c214d0792bfb26a11eae624b6 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 24 Dec 2012 03:19:52 +1000 Subject: [PATCH 138/276] Get Symbian running again --- Common/FileUtil.cpp | 2 ++ Common/MemoryUtil.cpp | 1 + Qt/Settings.pri | 2 +- android/jni/NativeApp.cpp | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index e0a3fe8609..3bebbe77f8 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -713,6 +713,8 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath) #ifdef _WIN32 // TODO: use GetExeDirectory() here instead of ROOT_DIR so that if the cwd is changed we still have the correct paths? paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; +#elif defined(__SYMBIAN32__) + paths[D_USER_IDX] = "E:" DIR_SEP "PPSSPP" DIR_SEP; #else if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index 2a4d74a469..282ffe2ee4 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -55,6 +55,7 @@ void* AllocateExecutableMemory(size_t size, bool low) void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #elif defined(__SYMBIAN32__) // On Symbian, we will need to create an RChunk and allocate with ->CreateLocalCode(size, size); + static char *map_hint = 0; void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, -1, 0); #else static char *map_hint = 0; diff --git a/Qt/Settings.pri b/Qt/Settings.pri index 5db0598e91..87d3a408e3 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -1,5 +1,5 @@ blackberry|symbian: CONFIG += mobile_platform -unix:!blackberry:!macx: CONFIG += linux +unix:!blackberry:!symbian:!macx: CONFIG += linux # Global specific QMAKE_CXXFLAGS += -std=c++0x -Wno-unused-function -Wno-unused-variable -Wno-multichar -Wno-uninitialized -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-unused-parameter diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 4b749797c1..251a98a534 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -219,7 +219,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co #endif } -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ANDROID) || defined(BLACKBERRY) || defined(__SYMBIAN32__) g_Config.memCardDirectory = user_data_path; g_Config.flashDirectory = user_data_path+"/flash/"; #else From c89c46cbf9fb2bba542dbe6c3b1528a3508a1357 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 09:21:10 -0800 Subject: [PATCH 139/276] Center and space out the OSK. --- Core/Dialog/PSPOskDialog.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index a4feb82cde..b636fd7013 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -94,7 +94,6 @@ void PSPOskDialog::RenderKeyboard() { int selectedRow = selectedChar / KEYSPERROW; int selectedExtra = selectedChar % KEYSPERROW; - char SelectedLine[KEYSPERROW + 1]; char temp[2]; temp[1] = '\0'; @@ -104,6 +103,9 @@ void PSPOskDialog::RenderKeyboard() if (limit <= 0) limit = 16; + const float keyboardLeftSide = (480.0f - (16.0f * KEYSPERROW)) / 2.0f; + float previewLeftSide = (480.0f - (16.0f * limit)) / 2.0f; + PPGeDrawText(oskDesc.c_str(), 480/2, 20, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); for (int i = 0; i < limit; ++i) { @@ -118,29 +120,23 @@ void PSPOskDialog::RenderKeyboard() else temp[0] = '_'; - PPGeDrawText(temp, 20.0f + (i * 16.0f), 40, NULL, 0.5f, color); + PPGeDrawText(temp, previewLeftSide + (i * 16.0f), 40.0f, NULL, 0.5f, color); } - for (int row = 0; row < NUMKEYROWS; row++) + for (int row = 0; row < NUMKEYROWS; ++row) { - u32 color = 0xFFFFFFFF; - if (selectedRow == row) - color = 0xFF7f7f7f; - PPGeDrawText(oskKeys[row], 20.0f, 70.0f + (25.0f * row), NULL, 0.6f, color); - } - for (int selectedItemCounter = 0; selectedItemCounter < KEYSPERROW; selectedItemCounter++ ) - { - if (selectedItemCounter!=selectedExtra) + for (int col = 0; col < KEYSPERROW; ++col) { - SelectedLine[selectedItemCounter] = oskKeys[selectedRow][selectedItemCounter]; - } - else - { - SelectedLine[selectedItemCounter] = '_'; - } - } + u32 color = 0xFFFFFFFF; + if (selectedRow == row && col == selectedExtra) + color = 0xFF7f7f7f; - SelectedLine[KEYSPERROW] = '\0'; - PPGeDrawText(SelectedLine, 20, 71.0f + (25.0f * selectedRow), NULL, 0.6f, 0xFFFFFFFF); + temp[0] = oskKeys[row][col]; + PPGeDrawText(temp, keyboardLeftSide + (16.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, color); + + if (selectedRow == row && col == selectedExtra) + PPGeDrawText("_", keyboardLeftSide + (16.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, 0xFFFFFFFF); + } + } } From bfcf6e3aca8d58f349769eaa72b15b70e660b22d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 09:23:01 -0800 Subject: [PATCH 140/276] Stop always selecting the first char in OSK. --- Core/Dialog/PSPOskDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index b636fd7013..a7380c510f 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -86,6 +86,9 @@ int PSPOskDialog::Init(u32 oskPtr) return -1; } + // Eat any keys pressed before the dialog inited. + __CtrlReadLatch(); + return 0; } From 7c35b145eaa8536f32cc5a3aa3937fe77d27d3b9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 09:25:42 -0800 Subject: [PATCH 141/276] Make the OSK go left/right like SNES/etc. ones. --- Core/Dialog/PSPOskDialog.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index a7380c510f..f2d186c5a5 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -183,10 +183,14 @@ void PSPOskDialog::Update() else if (IsButtonPressed(CTRL_LEFT)) { selectedChar--; + if (((selectedChar + KEYSPERROW) % KEYSPERROW) == KEYSPERROW - 1) + selectedChar += KEYSPERROW; } else if (IsButtonPressed(CTRL_RIGHT)) { selectedChar++; + if ((selectedChar % KEYSPERROW) == 0) + selectedChar -= KEYSPERROW; } selectedChar = (selectedChar + NUMBEROFVALIDCHARS) % NUMBEROFVALIDCHARS; From 5f7553c467a02314dda947a1aed35ff31a268d82 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 01:26:37 +0800 Subject: [PATCH 142/276] Buildfix --- Core/HLE/FunctionWrappers.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 375ca7d87d..0a511e71ae 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -132,11 +132,6 @@ template void WrapU_I() { RETURN(retval); } -template void WrapU_II() { - u32 retval = func(PARAM(0), PARAM(1)); - RETURN(retval); -} - template void WrapU_IIU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); From b45c9a2747fcc388b9510b80c33eca876a85d81d Mon Sep 17 00:00:00 2001 From: TMaul Date: Sun, 23 Dec 2012 19:50:50 +0000 Subject: [PATCH 143/276] Fix some atrac warnings Shouldn't be returning uninited vars, just in case.. --- Core/HLE/sceAtrac.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index c64bb1b878..ae6b3e8589 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -58,9 +58,8 @@ u32 sceAtracEndEntry() u32 sceAtracGetAtracID(int codecType) { - int id; ERROR_LOG(HLE, "UNIMPL sceAtracGetAtracID(%i)", codecType); - return id; + return 0; } u32 sceAtracGetBufferInfoForReseting(int atracID, int sample, u32 bufferInfoAddr) @@ -178,16 +177,14 @@ u32 sceAtracSetData(int atracID, u32 buffer, u32 bufferSize) int sceAtracSetDataAndGetID(u32 buffer, u32 bufferSize) { - int id; - ERROR_LOG(HLE, "UNIMPL sceAtracSetDataAndGetID(%i, %08x, %08x)", buffer, bufferSize); - return id; + ERROR_LOG(HLE, "UNIMPL sceAtracSetDataAndGetID(%08x, %08x)", buffer, bufferSize); + return 0; } int sceAtracSetHalfwayBufferAndGetID(int atracID, u32 halfBuffer, u32 readSize, u32 halfBufferSize) { - int id; ERROR_LOG(HLE, "UNIMPL sceAtracSetHalfwayBufferAndGetID(%i, %08x, %08x, %08x)", atracID, halfBuffer, readSize, halfBufferSize); - return id; + return 0; } u32 sceAtracStartEntry() From e8f240c1d488667792e8616291763e9588fff9b9 Mon Sep 17 00:00:00 2001 From: TMaul Date: Sun, 23 Dec 2012 20:51:05 +0000 Subject: [PATCH 144/276] Fix some more possible errors Shadowed var n in MIPSIntVFPU Possible buffer overflow in vertexdecoder.h fix valid address checking in sceRtc function --- Core/HLE/sceRtc.cpp | 2 +- Core/Host.h | 1 + Core/MIPS/MIPSIntVFPU.cpp | 6 +++--- GPU/GLES/VertexDecoder.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 58ce61ed15..5692a12f73 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -541,7 +541,7 @@ int sceRtcGetWin32FileTime(u32 datePtr, u32 win32TimePtr) int sceRtcCompareTick(u32 tick1Ptr, u32 tick2Ptr) { ERROR_LOG(HLE, "HACK sceRtcCompareTick(%d,%d)", tick1Ptr, tick2Ptr); - if (Memory::IsValidAddress(tick1Ptr)&&Memory::IsValidAddress(tick1Ptr)) + if (Memory::IsValidAddress(tick1Ptr) && Memory::IsValidAddress(tick2Ptr)) { u64 tick1 = Memory::Read_U64(tick1Ptr); u64 tick2 = Memory::Read_U64(tick2Ptr); diff --git a/Core/Host.h b/Core/Host.h index 9936e8db8f..5600e01393 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -26,6 +26,7 @@ class PMixer { public: PMixer() {} + virtual ~PMixer() {} virtual int Mix(short *stereoout, int numSamples) {memset(stereoout,0,numSamples*2*sizeof(short)); return numSamples;} }; diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index f24dd2cc4e..b552e0bd82 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -1452,7 +1452,7 @@ namespace MIPSInt int vd = _VD; int cond = op&15; VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); + int numElements = GetNumVectorElements(sz); float s[4]; float t[4]; float d[4]; @@ -1510,7 +1510,7 @@ namespace MIPSInt int vd = _VD; int cond = op&15; VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); + int numElements = GetNumVectorElements(sz); float s[4]; float t[4]; float d[4]; @@ -1535,7 +1535,7 @@ namespace MIPSInt int vd = _VD; int cond = op&15; VectorSize sz = GetVecSize(op); - int n = GetNumVectorElements(sz); + int numElements = GetNumVectorElements(sz); float s[4]; float t[4]; float d[4]; diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index f664d303a3..76bb3fde84 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -261,7 +261,7 @@ public: } break; case DEC_FLOAT_4: - memcpy(color, data_ + decFmt_.c1off, 16); break; + memcpy(color, data_ + decFmt_.c1off, 3); break; default: ERROR_LOG(G3D, "Reader: Unsupported C1 Format"); break; From 976537d3140c8724021600e15b05c396f46acd72 Mon Sep 17 00:00:00 2001 From: TMaul Date: Sun, 23 Dec 2012 21:30:19 +0000 Subject: [PATCH 145/276] 3 foats, not 3 bytes.... --- GPU/GLES/VertexDecoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index 76bb3fde84..d41e5f1fd2 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -261,7 +261,7 @@ public: } break; case DEC_FLOAT_4: - memcpy(color, data_ + decFmt_.c1off, 3); break; + memcpy(color, data_ + decFmt_.c1off, 12); break; default: ERROR_LOG(G3D, "Reader: Unsupported C1 Format"); break; From 61d116b5f16e1657930f1fe499cebe3344bfff7d Mon Sep 17 00:00:00 2001 From: Xele02 Date: Mon, 24 Dec 2012 01:22:28 +0100 Subject: [PATCH 146/276] Copy right size of save request. --- Core/Dialog/PSPSaveDialog.cpp | 27 ++++++++++++++++++--------- Core/Dialog/PSPSaveDialog.h | 2 ++ Core/MemMap.cpp | 5 +++++ Core/MemMap.h | 1 + 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index fcb4ad4e84..0e4f27beb3 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -38,10 +38,19 @@ u32 PSPSaveDialog::Init(int paramAddr) { return 0; } - u32 retval = param.SetPspParam((SceUtilitySavedataParam*)Memory::GetPointer(paramAddr)); + + int size = Memory::Read_U32(paramAddr); + memset(&request,0,sizeof(request)); + // Only copy the right size to support different save request format + Memory::Memcpy(&request,paramAddr,size); + requestAddr = paramAddr; + + u32 retval = param.SetPspParam(&request); + + DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); DEBUG_LOG(HLE,"Mode: %i", param.GetPspParam()->mode); - switch (param.GetPspParam()->mode) + switch(param.GetPspParam()->mode) { case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD: case SCE_UTILITY_SAVEDATA_TYPE_LOAD: @@ -312,6 +321,8 @@ void PSPSaveDialog::Update() case SCE_UTILITY_STATUS_FINISHED: status = SCE_UTILITY_STATUS_SHUTDOWN; break; + default: + break; } if (status != SCE_UTILITY_STATUS_RUNNING) @@ -632,7 +643,6 @@ void PSPSaveDialog::Update() else param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA; status = SCE_UTILITY_STATUS_FINISHED; - return; break; case SCE_UTILITY_SAVEDATA_TYPE_SAVE: // Only save and exit case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE: @@ -641,7 +651,6 @@ void PSPSaveDialog::Update() else param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE; status = SCE_UTILITY_STATUS_FINISHED; - return; break; case SCE_UTILITY_SAVEDATA_TYPE_SIZES: if(param.GetSizes(param.GetPspParam())) @@ -653,28 +662,28 @@ void PSPSaveDialog::Update() param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; } status = SCE_UTILITY_STATUS_FINISHED; - return; case SCE_UTILITY_SAVEDATA_TYPE_LIST: param.GetList(param.GetPspParam()); param.GetPspParam()->result = 0; status = SCE_UTILITY_STATUS_FINISHED; - return; default: status = SCE_UTILITY_STATUS_FINISHED; - return; break; } } break; default: status = SCE_UTILITY_STATUS_FINISHED; - return; break; } lastButtons = buttons; - + if(status == SCE_UTILITY_STATUS_FINISHED) + { + Memory::Memcpy(requestAddr,&request,request.size); + } + } void PSPSaveDialog::Shutdown() diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index 3c00817280..6ee98f59f3 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -102,6 +102,8 @@ private : DisplayState display; SavedataParam param; + SceUtilitySavedataParam request; + int requestAddr; int currentSelectedSave; int yesnoChoice; diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 38a5027173..662f081cdc 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -160,6 +160,11 @@ void Memcpy(const u32 address, const void *data, const u32 len) memcpy(GetPointer(address), data, len); } +void Memcpy(void *data, const u32 address, const u32 len) +{ + memcpy(data,GetPointer(address),len); +} + void GetString(std::string& _string, const u32 em_address) { char stringBuffer[2048]; diff --git a/Core/MemMap.h b/Core/MemMap.h index 6f9a13b91e..2179bf9c9e 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -255,6 +255,7 @@ inline const char* GetCharPointer(const u32 address) { void Memset(const u32 _Address, const u8 _Data, const u32 _iLength); void Memcpy(const u32 _Address, const void *_Data, const u32 _iLength); +void Memcpy(void *data, const u32 address, const u32 len); template void ReadStruct(u32 address, T *ptr) From 0861636fe063d2a8e3346d33ea5d3f09cafa27c7 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Mon, 24 Dec 2012 01:54:46 +0100 Subject: [PATCH 147/276] sync submodules to latest --- native | 2 +- pspautotests | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native b/native index 0de5e114f3..8fd4f592ad 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 0de5e114f337859a03d0763c30beaf6e03af03c4 +Subproject commit 8fd4f592ad44655031e3111a8594a6dfc1b195a4 diff --git a/pspautotests b/pspautotests index 8c1284c758..5e5ae52067 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 8c1284c758c05811517c043bbc781ba8ab724d5e +Subproject commit 5e5ae520672b816943acabed1f223ebcd7cff16f From 65cfc8de86a79b05957644d5cd7737f1282000d7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 18:27:07 -0800 Subject: [PATCH 148/276] Cleanup and fix mutex init, no need for a flag now. --- Core/HLE/sceKernelMutex.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index c4c4b6e1fc..c90bec98cf 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -107,7 +107,6 @@ struct LwMutex : public KernelObject std::vector waitingThreads; }; -bool mutexInitComplete = false; int mutexWaitTimer = 0; int lwMutexWaitTimer = 0; // Thread -> Mutex locks for thread end. @@ -119,12 +118,7 @@ void __KernelMutexInit() mutexWaitTimer = CoreTiming::RegisterEvent("MutexTimeout", &__KernelMutexTimeout); lwMutexWaitTimer = CoreTiming::RegisterEvent("LwMutexTimeout", &__KernelLwMutexTimeout); - // TODO: Install on first mutex (if it's slow?) __KernelListenThreadEnd(&__KernelMutexThreadEnd); - - mutexInitComplete = true; - mutexWaitTimer = 0; - lwMutexWaitTimer = 0; } void __KernelMutexShutdown() @@ -191,9 +185,6 @@ std::vector::iterator __KernelMutexFindPriority(std::vector &wai int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { - if (!mutexInitComplete) - __KernelMutexInit(); - if (!name) { WARN_LOG(HLE, "%08x=sceKernelCreateMutex(): invalid name", SCE_KERNEL_ERROR_ERROR); @@ -507,9 +498,6 @@ int sceKernelUnlockMutex(SceUID id, int count) int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr) { - if (!mutexInitComplete) - __KernelMutexInit(); - if (!name) { WARN_LOG(HLE, "%08x=sceKernelCreateLwMutex(): invalid name", SCE_KERNEL_ERROR_ERROR); From 9ba0ed46fded26e67ed95cb0df10ffff6a486aeb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 21:27:26 -0800 Subject: [PATCH 149/276] Always create CoreTiming timers during kernel init. --- Core/HLE/sceCtrl.cpp | 23 ++++++++--------------- Core/HLE/sceKernel.cpp | 6 +++++- Core/HLE/sceKernelAlarm.cpp | 20 ++++++-------------- Core/HLE/sceKernelAlarm.h | 4 +++- Core/HLE/sceKernelEventFlag.cpp | 5 ----- Core/HLE/sceKernelEventFlag.h | 2 ++ Core/HLE/sceKernelMbx.cpp | 8 +------- Core/HLE/sceKernelMbx.h | 2 ++ Core/HLE/sceKernelMutex.cpp | 6 +++--- Core/HLE/sceKernelSemaphore.cpp | 7 +------ Core/HLE/sceKernelSemaphore.h | 2 ++ Core/HLE/sceKernelThread.cpp | 1 + Core/HLE/sceUmd.cpp | 8 ++++---- 13 files changed, 38 insertions(+), 56 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index ac85a3f1a8..d47cea7df8 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -62,7 +62,6 @@ struct CtrlLatch { ////////////////////////////////////////////////////////////////////////// // STATE BEGIN -static bool ctrlInited = false; static bool analogEnabled = false; static int ctrlLatchBufs = 0; static u32 ctrlOldButtons = 0; @@ -259,13 +258,15 @@ void __CtrlTimerUpdate(u64 userdata, int cyclesLate) void __CtrlInit() { - std::lock_guard guard(ctrlMutex); + ctrlTimer = CoreTiming::RegisterEvent("CtrlSampleTimer", __CtrlTimerUpdate); + __DisplayListenVblank(__CtrlVblank); + waitingThreads.clear(); - if (!ctrlInited) - { - __DisplayListenVblank(__CtrlVblank); - ctrlInited = true; - } + ctrlIdleReset = -1; + ctrlIdleBack = -1; + ctrlCycle = 0; + + std::lock_guard guard(ctrlMutex); ctrlBuf = 1; ctrlBufRead = 0; @@ -282,14 +283,6 @@ void __CtrlInit() for (int i = 0; i < NUM_CTRL_BUFFERS; i++) memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data)); - - ctrlIdleReset = -1; - ctrlIdleBack = -1; - ctrlCycle = 0; - - waitingThreads.clear(); - - ctrlTimer = CoreTiming::RegisterEvent("CtrlSampleTimer", __CtrlTimerUpdate); } u32 sceCtrlSetSamplingCycle(u32 cycle) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index d4a34dc894..92b0c192f1 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -78,6 +78,10 @@ void __KernelInit() __KernelMemoryInit(); __KernelThreadingInit(); __KernelMutexInit(); + __KernelSemaInit(); + __KernelAlarmInit(); + __KernelEventFlagInit(); + __KernelMbxInit(); __IoInit(); __AudioInit(); __SasInit(); @@ -115,8 +119,8 @@ void __KernelShutdown() __AudioShutdown(); __IoShutdown(); __InterruptsShutdown(); - __KernelThreadingShutdown(); __KernelMutexShutdown(); + __KernelThreadingShutdown(); __KernelMemoryShutdown(); CoreTiming::ClearPendingEvents(); diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 984c558e04..4e378b2a49 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -78,17 +78,7 @@ public: Alarm *alarm; }; -bool alarmInitComplete = false; -int alarmTimer = 0; - -void __KernelTriggerAlarm(u64 userdata, int cyclesLate); - -void __KernelAlarmInit() -{ - alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); - - alarmInitComplete = true; -} +static int alarmTimer = 0; void __KernelTriggerAlarm(u64 userdata, int cyclesLate) { @@ -100,6 +90,11 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); } +void __KernelAlarmInit() +{ + alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); +} + void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) { alarm->alm.schedule = (CoreTiming::GetTicks() + ticks) / (u64) CoreTiming::GetClockFrequencyMHz(); @@ -108,9 +103,6 @@ void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) { - if (!alarmInitComplete) - __KernelAlarmInit(); - if (!Memory::IsValidAddress(handlerPtr)) return SCE_KERNEL_ERROR_ILLEGAL_ADDR; diff --git a/Core/HLE/sceKernelAlarm.h b/Core/HLE/sceKernelAlarm.h index f430a20da9..09dd2e2f82 100644 --- a/Core/HLE/sceKernelAlarm.h +++ b/Core/HLE/sceKernelAlarm.h @@ -20,4 +20,6 @@ SceUID sceKernelSetAlarm(SceUInt clock, u32 handlerPtr, u32 commonPtr); SceUID sceKernelSetSysClockAlarm(u32 sysClockPtr, u32 handlerPtr, u32 commonPtr); int sceKernelCancelAlarm(SceUID uid); -int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); \ No newline at end of file +int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); + +void __KernelAlarmInit(); diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index ed237a1e25..a28c06c0d6 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -90,13 +90,11 @@ enum PspEventFlagWaitTypes PSP_EVENT_WAITKNOWN = PSP_EVENT_WAITCLEAR | PSP_EVENT_WAITCLEARALL | PSP_EVENT_WAITOR, }; -bool eventFlagInitComplete = false; int eventFlagWaitTimer = 0; void __KernelEventFlagInit() { eventFlagWaitTimer = CoreTiming::RegisterEvent("EventFlagTimeout", &__KernelEventFlagTimeout); - eventFlagInitComplete = true; } bool __KernelEventFlagMatches(u32 *pattern, u32 bits, u8 wait, u32 outAddr) @@ -168,9 +166,6 @@ bool __KernelClearEventFlagThreads(EventFlag *e, int reason) //SceUID sceKernelCreateEventFlag(const char *name, int attr, int bits, SceKernelEventFlagOptParam *opt); int sceKernelCreateEventFlag(const char *name, u32 flag_attr, u32 flag_initPattern, u32 optPtr) { - if (!eventFlagInitComplete) - __KernelEventFlagInit(); - if (!name) { WARN_LOG(HLE, "%08x=sceKernelCreateEventFlag(): invalid name", SCE_KERNEL_ERROR_ERROR); diff --git a/Core/HLE/sceKernelEventFlag.h b/Core/HLE/sceKernelEventFlag.h index b47b43c53b..4243b8d897 100644 --- a/Core/HLE/sceKernelEventFlag.h +++ b/Core/HLE/sceKernelEventFlag.h @@ -26,3 +26,5 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeoutPtr); u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr); u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr); + +void __KernelEventFlagInit(); diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index bcd3b74d84..c8c758a215 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -30,8 +30,7 @@ const int PSP_MBX_ERROR_DUPLICATE_MSG = 0x800201C9; typedef std::pair MbxWaitingThread; void __KernelMbxTimeout(u64 userdata, int cyclesLate); -bool mbxInitComplete = false; -int mbxWaitTimer = 0; +static int mbxWaitTimer = 0; struct NativeMbx { @@ -162,8 +161,6 @@ struct Mbx : public KernelObject void __KernelMbxInit() { mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", &__KernelMbxTimeout); - - mbxInitComplete = true; } bool __KernelUnlockMbxForThread(Mbx *m, MbxWaitingThread &th, u32 &error, int result, bool &wokeThreads) @@ -263,9 +260,6 @@ std::vector::iterator __KernelMbxFindPriority(std::vector waitingThreads; }; -int mutexWaitTimer = 0; -int lwMutexWaitTimer = 0; +static int mutexWaitTimer = 0; +static int lwMutexWaitTimer = 0; // Thread -> Mutex locks for thread end. typedef std::multimap MutexMap; -MutexMap mutexHeldLocks; +static MutexMap mutexHeldLocks; void __KernelMutexInit() { diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 5b9bdd3d7a..39dc209928 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -61,13 +61,11 @@ struct Semaphore : public KernelObject std::vector waitingThreads; }; -bool semaInitComplete = false; -int semaWaitTimer = 0; +static int semaWaitTimer = 0; void __KernelSemaInit() { semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout); - semaInitComplete = true; } // Returns whether the thread should be removed. @@ -173,9 +171,6 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) //SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { - if (!semaInitComplete) - __KernelSemaInit(); - if (!name) { WARN_LOG(HLE, "%08x=sceKernelCreateSema(): invalid name", SCE_KERNEL_ERROR_ERROR); diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index 32150c6307..9a8b9f2640 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -27,3 +27,5 @@ int sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr); int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); void __KernelSemaTimeout(u64 userdata, int cycleslate); + +void __KernelSemaInit(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 6807fd92d2..fed0a7fa11 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -435,6 +435,7 @@ void __KernelThreadingShutdown() { kernelMemory.Free(threadReturnHackAddr); threadqueue.clear(); + threadEndListeners.clear(); threadReturnHackAddr = 0; cbReturnHackAddr = 0; currentThread = 0; diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index a4fd3b8b11..3e358d36a3 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -47,8 +47,11 @@ struct PspUmdInfo { u32 type; }; +void __UmdStatTimeout(u64 userdata, int cyclesLate); -void __UmdInit() { +void __UmdInit() +{ + umdStatTimer = CoreTiming::RegisterEvent("UmdTimeout", &__UmdStatTimeout); umdActivated = 1; umdStatus = 0; umdErrorStat = 0; @@ -214,9 +217,6 @@ void __UmdStatTimeout(u64 userdata, int cyclesLate) void __UmdWaitStat(u32 timeout) { - if (umdStatTimer == 0) - umdStatTimer = CoreTiming::RegisterEvent("UmdTimeout", &__UmdStatTimeout); - // This happens to be how the hardware seems to time things. if (timeout <= 4) timeout = 15; From 49d4c45670c947a9e01c668c23c535b2c65000cc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 21:49:44 -0800 Subject: [PATCH 150/276] Make sure threading state is cleared on shutdown. --- Core/HLE/sceKernelThread.cpp | 97 ++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index fed0a7fa11..55709e3709 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -162,7 +162,50 @@ struct ThreadWaitInfo { u32 timeoutPtr; }; -class ActionAfterMipsCall; +// Owns outstanding MIPS calls and provides a way to get them by ID. +// TODO: MipsCall structs are kinda big, try to cut down on the copying by owning pointers instead. +class MipsCallManager { +public: + MipsCallManager() : idGen_(0) {} + int add(MipsCall *call) { + int id = genId(); + calls_.insert(std::pair(id, call)); + return id; + } + MipsCall *get(int id) { + return calls_[id]; + } + MipsCall *pop(int id) { + MipsCall *temp = calls_[id]; + calls_.erase(id); + return temp; + } + void clear() { + calls_.clear(); + idGen_ = 0; + } + +private: + int genId() { return ++idGen_; } + std::map calls_; + int idGen_; +}; + +class ActionAfterMipsCall : public Action +{ +public: + virtual void run(); + Thread *thread; + + // Saved thread state + int status; + WaitType waitType; + int waitID; + ThreadWaitInfo waitInfo; + bool isProcessingCallbacks; + + Action *chainedAction; +}; class Thread : public KernelObject { @@ -276,8 +319,6 @@ public: void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter); -int g_inCbCount = 0; - Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr); void __KernelResetThread(Thread *t); void __KernelCancelWakeup(SceUID threadID); @@ -286,6 +327,7 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force); ////////////////////////////////////////////////////////////////////////// //STATE BEGIN ////////////////////////////////////////////////////////////////////////// +int g_inCbCount = 0; Thread *currentThread; u32 idleThreadHackAddr; u32 threadReturnHackAddr; @@ -300,6 +342,8 @@ int eventScheduledWakeup; bool dispatchEnabled = true; +class MipsCallManager; +MipsCallManager mipsCalls; // This seems nasty SceUID curModule; @@ -436,10 +480,12 @@ void __KernelThreadingShutdown() kernelMemory.Free(threadReturnHackAddr); threadqueue.clear(); threadEndListeners.clear(); + mipsCalls.clear(); threadReturnHackAddr = 0; cbReturnHackAddr = 0; currentThread = 0; intReturnHackAddr = 0; + curModule = 0; } const char *__KernelGetThreadName(SceUID threadID) @@ -1569,50 +1615,6 @@ void sceKernelReferCallbackStatus() } } -// Owns outstanding MIPS calls and provides a way to get them by ID. -// TODO: MipsCall structs are kinda big, try to cut down on the copying by owning pointers instead. -class MipsCallManager { -public: - MipsCallManager() : idGen_(0) {} - int add(MipsCall *call) { - int id = genId(); - calls_.insert(std::pair(id, call)); - return id; - } - MipsCall *get(int id) { - return calls_[id]; - } - MipsCall *pop(int id) { - MipsCall *temp = calls_[id]; - calls_.erase(id); - return temp; - } - -private: - int genId() { return ++idGen_; } - std::map calls_; - int idGen_; -}; - -MipsCallManager mipsCalls; - - -class ActionAfterMipsCall : public Action -{ -public: - virtual void run(); - Thread *thread; - - // Saved thread state - int status; - WaitType waitType; - int waitID; - ThreadWaitInfo waitInfo; - bool isProcessingCallbacks; - - Action *chainedAction; -}; - void ActionAfterMipsCall::run() { thread->nt.status = status; thread->nt.waitType = waitType; @@ -1626,7 +1628,6 @@ void ActionAfterMipsCall::run() { } } - ActionAfterMipsCall *Thread::getRunningCallbackAction() { if (this == currentThread && g_inCbCount > 0) From 036f0f3ad93831f19460fff7470c0a4ad630ad6a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 22:07:17 -0800 Subject: [PATCH 151/276] Properly clear interrupt state on shutdown. --- Core/HLE/sceKernelInterrupt.cpp | 125 +++++++++++++++++++------------- 1 file changed, 73 insertions(+), 52 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 3ee53f9e77..bc00c82254 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -33,35 +33,9 @@ struct Interrupt PSPInterrupt intno; }; -// Yeah, this bit is a bit silly. -static int interruptsEnabled = 1; -static bool inInterrupt; - - -void __InterruptsInit() -{ - interruptsEnabled = 1; -} - -void __InterruptsShutdown() -{ -} - -void __DisableInterrupts() -{ - interruptsEnabled = 0; -} - -void __EnableInterrupts() -{ - interruptsEnabled = 1; -} - -bool __InterruptsEnabled() -{ - return interruptsEnabled != 0; -} - +void __DisableInterrupts(); +void __EnableInterrupts(); +bool __InterruptsEnabled(); // InterruptsManager ////////////////////////////////////////////////////////////////////////// @@ -116,18 +90,6 @@ void sceKernelCpuResumeIntrWithSync(u32 enable) sceKernelCpuResumeIntr(enable); } - - -bool __IsInInterrupt() -{ - return inInterrupt; -} - -bool __CanExecuteInterrupt() -{ - return !inInterrupt; -} - class IntrHandler { public: void add(int subIntrNum, SubIntrHandler *handler) @@ -154,6 +116,13 @@ public: return 0; // what to do, what to do... } + void clear() + { + std::map::iterator it, end; + for (it = subIntrHandlers.begin(), end = subIntrHandlers.end(); it != end; ++it) + delete it->second; + subIntrHandlers.clear(); + } void queueUp(int subintr) { @@ -184,17 +153,9 @@ private: class InterruptState { public: - void save() - { - insideInterrupt = __IsInInterrupt(); - __KernelSaveContext(&savedCpu); - } - - void restore() - { - ::inInterrupt = insideInterrupt; - __KernelLoadContext(&savedCpu); - } + void save(); + void restore(); + void clear(); bool insideInterrupt; ThreadContext savedCpu; @@ -208,6 +169,66 @@ InterruptState intState; IntrHandler intrHandlers[PSP_NUMBER_INTERRUPTS]; std::list pendingInterrupts; +// Yeah, this bit is a bit silly. +static int interruptsEnabled = 1; +static bool inInterrupt; + + +void __InterruptsInit() +{ + interruptsEnabled = 1; + inInterrupt = false; + intState.clear(); +} + +void __InterruptsShutdown() +{ + for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) + intrHandlers[i].clear(); + pendingInterrupts.clear(); +} + +void __DisableInterrupts() +{ + interruptsEnabled = 0; +} + +void __EnableInterrupts() +{ + interruptsEnabled = 1; +} + +bool __InterruptsEnabled() +{ + return interruptsEnabled != 0; +} + +bool __IsInInterrupt() +{ + return inInterrupt; +} + +bool __CanExecuteInterrupt() +{ + return !inInterrupt; +} + +void InterruptState::save() +{ + insideInterrupt = __IsInInterrupt(); + __KernelSaveContext(&savedCpu); +} + +void InterruptState::restore() +{ + ::inInterrupt = insideInterrupt; + __KernelLoadContext(&savedCpu); +} + +void InterruptState::clear() +{ + insideInterrupt = false; +} // http://forums.ps2dev.org/viewtopic.php?t=5687 From 41db5c46a5e631bb127004579a61ee1254c44d36 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 22:47:52 -0800 Subject: [PATCH 152/276] Fix random modules not reseting on shutdown. --- Core/HLE/sceImpose.cpp | 5 +++++ Core/HLE/sceImpose.h | 1 + Core/HLE/sceIo.cpp | 6 +++++- Core/HLE/sceKernel.cpp | 4 ++++ Core/HLE/scePower.cpp | 7 +++---- Core/HLE/sceUsb.cpp | 5 +++++ Core/HLE/sceUsb.h | 2 ++ Core/HLE/sceUtility.cpp | 5 +++++ 8 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 93a417a088..4122d1e40b 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -36,6 +36,11 @@ const int PSP_LANGUAGE_SIMPLIFIED_CHINESE = 11; static u32 iLanguage = PSP_LANGUAGE_ENGLISH; static u32 iButtonValue = 0; +void __ImposeInit() +{ + iLanguage = PSP_LANGUAGE_ENGLISH; + iButtonValue = 0; +} u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) { diff --git a/Core/HLE/sceImpose.h b/Core/HLE/sceImpose.h index 1de2aea93e..86eabedcec 100644 --- a/Core/HLE/sceImpose.h +++ b/Core/HLE/sceImpose.h @@ -18,3 +18,4 @@ #pragma once void Register_sceImpose(); +void __ImposeInit(); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 941d3a63ef..9f03b26d17 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -84,7 +84,7 @@ const std::string &EmuDebugOutput() { typedef u32 (*DeferredAction)(SceUID id, int param); DeferredAction defAction = 0; -u32 defParam; +u32 defParam = 0; #define SCE_STM_FDIR 0x1000 #define SCE_STM_FREG 0x2000 @@ -154,6 +154,8 @@ public: void __IoInit() { INFO_LOG(HLE, "Starting up I/O..."); + MemoryStick_SetFatState(PSP_FAT_MEMORYSTICK_STATE_ASSIGNED); + #ifdef _WIN32 char path_buffer[_MAX_PATH], drive[_MAX_DRIVE] ,dir[_MAX_DIR], file[_MAX_FNAME], ext[_MAX_EXT]; @@ -192,6 +194,8 @@ void __IoInit() { } void __IoShutdown() { + defAction = 0; + defParam = 0; } u32 sceIoAssign(const char *aliasname, const char *physname, const char *devname, u32 flag) { diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 92b0c192f1..713c4090ba 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -53,6 +53,8 @@ #include "sceUmd.h" #include "sceSsl.h" #include "sceSas.h" +#include "sceImpose.h" +#include "sceUsb.h" #include "../Util/PPGeDraw.h" @@ -93,6 +95,8 @@ void __KernelInit() __UmdInit(); __CtrlInit(); __SslInit(); + __ImposeInit(); + __UsbInit(); // "Internal" PSP libraries __PPGeInit(); diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index bfe1943bc1..c6b0fecb7d 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -22,16 +22,15 @@ #include "scePower.h" #include "sceKernelThread.h" -static bool volatileMemLocked; - const int POWER_CB_AUTO = -1; - const int numberOfCBPowerSlots = 16; -static int powerCbSlots[numberOfCBPowerSlots]; +static bool volatileMemLocked; +static int powerCbSlots[numberOfCBPowerSlots]; void __PowerInit() { memset(powerCbSlots, 0, sizeof(powerCbSlots)); + volatileMemLocked = false; } int scePowerGetBatteryLifePercent() { diff --git a/Core/HLE/sceUsb.cpp b/Core/HLE/sceUsb.cpp index faec5397a9..1d1ebc2189 100644 --- a/Core/HLE/sceUsb.cpp +++ b/Core/HLE/sceUsb.cpp @@ -22,6 +22,11 @@ bool usbActivated = false; +void __UsbInit() +{ + usbActivated = false; +} + u32 sceUsbActivate() { ERROR_LOG(HLE, "UNIMPL sceUsbActivate"); usbActivated = true; diff --git a/Core/HLE/sceUsb.h b/Core/HLE/sceUsb.h index 009f44ec96..d521a0a9da 100644 --- a/Core/HLE/sceUsb.h +++ b/Core/HLE/sceUsb.h @@ -18,3 +18,5 @@ #pragma once void Register_sceUsb(); + +void __UsbInit(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 3155748cf3..f686d722de 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -36,6 +36,11 @@ PSPPlaceholderDialog netDialog; void __UtilityInit() { + saveDialog.Shutdown(); + msgDialog.Shutdown(); + oskDialog.Shutdown(); + netDialog.Shutdown(); + SavedataParam::Init(); } From 2736012719973dddeecf202835246f0a17c35c65 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 23:12:53 -0800 Subject: [PATCH 153/276] Cleanup some state on reset in the GPU code. --- GPU/GLES/DisplayListInterpreter.cpp | 2 ++ GPU/GPUState.cpp | 2 ++ GPU/Null/NullGpu.cpp | 7 +++++++ GPU/Null/NullGpu.h | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index b5bab73b78..40c44a7fd2 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -191,6 +191,8 @@ GLES_GPU::~GLES_GPU() delete (*iter); } vfbs_.clear(); + + delete flushBeforeCommand; } void GLES_GPU::InitClear() diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 2f60deb5d6..4eb3fcb33c 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -56,6 +56,8 @@ void InitGfxState() memcpy(gstate.boneMatrix + i * 12, identity4x3, 12 * sizeof(float)); } + gpuStats.reset(); + switch (PSP_CoreParameter().gpuCore) { case GPU_NULL: gpu = new NullGPU(); diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 3dd5228a02..c7668b0fb6 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -46,6 +46,13 @@ static bool finished; static int dlIdGenerator = 1; +NullGPU::NullGPU() +{ + interruptsEnabled_ = true; + dlIdGenerator = 1; + dlQueue.clear(); +} + bool NullGPU::ProcessDLQueue() { std::vector::iterator iter = dlQueue.begin(); diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 93e9de9488..a642ac11f8 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -24,7 +24,7 @@ class ShaderManager; class NullGPU : public GPUInterface { public: - NullGPU() : interruptsEnabled_(true) {} + NullGPU(); virtual void InitClear() {} virtual u32 EnqueueList(u32 listpc, u32 stall); virtual void UpdateStall(int listid, u32 newstall); From 3c08a87404b5a9e4382122f2e87ea79ff5ca0dff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 23:33:10 -0800 Subject: [PATCH 154/276] Properly cleanup the jit on reset. --- Core/MIPS/MIPS.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 73dc9e129b..477b2dd4f7 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -52,7 +52,9 @@ MIPSState::~MIPSState() void MIPSState::Reset() { - if (!MIPSComp::jit && PSP_CoreParameter().cpuCore == CPU_JIT) + if (MIPSComp::jit) + delete MIPSComp::jit; + if (PSP_CoreParameter().cpuCore == CPU_JIT) MIPSComp::jit = new MIPSComp::Jit(this); memset(r, 0, sizeof(r)); From 5163745871e81f45416913492d0717bcc9555300 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 23:43:57 -0800 Subject: [PATCH 155/276] Switch the Windows RC file to UTF-16. UTF-8 not supported, and the encoding got messed up. This should keep it correct. Contents not changed. --- Windows/ppsspp.rc | Bin 14383 -> 28756 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 64c828266771a92e6b00a612d27f341396af3ee8..40f6f0e24f4608edab308ad315a56c3577fc3b70 100644 GIT binary patch literal 28756 zcmeI5>24gk5y$&;fV{&*3kY7s>$N5M*!^aY&R7?uvAqrg2tE}dl59wFyc^_o^BPJ1 zKbA@)d)U+6GtxpiFc@`DA7ruaDi*1K{qy_k`)W{aRY%pk>a6-yo$LFty3nR?y;VJAD*2Xd;ebb=V~rI&70qZ=RSt_X!~ikTkTh)>P59&ZB#qeLA6({=<2f0 zx2w(SwXW>z?^g9pS2lG{E7sC@-(N$!?*;u=L0#|pi(m!Hk2CgbZO}U-*buD40Od$< zkMw(}tKU@*t{??lxAWt)90=DRM8gYF&p4#c1?N|zf#zWFcNrz$S9dh})#|593hs+q zFGS0ssCgg^ZR+!_-uk;fgT^<(;9j++H@5ZO3%vn^o4UHKt1on1)AhmC6@PA|x1Q?i zUESN)bI%%|FwXfL#(7wsXtV?I@23FKfjIn4kcm5@-a_?IUxUE$bi1kOP!5Feqd><` z8jWA&$QOQH4m8;iuAb_HTdWp^71}{+U+WF%v8-Rn z>58tc2FV@iDwMW6t7`ox-R0M7eeK?>@Yb%L-xbYvv#Ucvvm2xdJ&-6zO7zbwJ+rNG?C6ZP>u}EL z3ZpTN7jf|bn&wO9_o2`H^uq=>gP)x@=P$Tg?{OAaQWF3#J~oo zOCKOXo_`E&m$cN~>XCX~&=+pMTRjOQ^0uJXhFWjx#amn!6wfqbq;@F0ybyjyYHcx$ zhISXLAFlcUy9at^SD%%jAK*ZE2yU^vPjw%Buj|fG&w%&M?1{RKu(!AMB-k+eVlVbI z26{>H26gt;HZU_f<1ZieK-iksSUzP~ThmiuiO=23aV>=_OFi4(7fn7%&p>a-AiRkT z(1YO$K3LE>SMnYh&uZYX@)+hcHZ1vP;bC4qoQD4Dy{%mK_Bc?6-ke5xZ|%5Bd)ul0 zs-Dlr#zt>D@<5;j<9cw_>r%jFeT-dtov;2P9aqQWbB!20E{L-q>e!6OuH20$vMjja z%zd?J9Izm&+|?-H255FS+@FrG`|{?lWFn;}ylMP1yn@g13J!p;Zy%c)aj6fkgI%wO zOI@jJ4ZDMPK|6-66eqw71g2|pSowu6{UVPN**y_PQ{12>-HyK0`HJ+<-S7t5_gJvv zc|X>sMfYGYBbsYi|2vCo79o|jtjcF3>FS_G#kf#U2d5T}>?J^x> z+_5S+sTlRaa+9Pm8QUwWY}G)z~|cuT!4tJh79#(h?!#htFmv~?&a)M&x3S9H_nZ>jn|1*&|p~qx_%@&uX}u{zNftn@d5rR z7N2A8sYM-WF%iD)LgiR%(Lnes(f6=c!U3;%5|Dh}7gcuopx4}qs2sR#uV;)bmL-|x%lZeQ& z5M)`1&(8$Wxvp~dK}TYDMuT;@2(Xjm;w@sTBVF|z7SFuX^`qdI4)oU7kh3{cd-tk8 z>3kI48R)qaarUwLz{1l4R%f7g?H8G`FKUbXN4j>ZGa!AVGw=hf_`b)w_gQU$OK|*I zZ=LBcnK-g)z;LRkz_`DA6rNaNU~^}aT=)pCeAq$ogAV+2xCz2J6(t4h%wi6<>-pX&?zPCqGz1; zTRKCg$^E|9o6w)pG0vv9+pzy6_^WX0G~)!0_Zmem+vL2FJ+7Zm%%WJY_?C6uSN1W; zOJVo-!?c+Q%MTIZKT^B2jqRP3K})rGzlb-t{KmhfSl1{O zDbzp8C3AxmF&3g*`{kZ>^sFq#X^V~WnImxIZR5?r2lPi@9{bD^5ltWOv{PeV(FziP zpKzS%eTyK_G-#Bq5K9o5K9h#N2%LEup0^B&=T?a|@N{?dT$%@sF+t2EfTg7nqoUzV z+vOf;7x;;kPh?Gqjn9iCs8egYF#xS)<_ub>n@e0AS($&x(wl{CwmV=1Zi0vKn2_)V zed;pSB@1TR5R2aT1GMN0B>PFgx@U!NDhpP&Qe*&#!@EYp7XPAIAL`TBPF;T-T#sNQ zXLpHqhl&jFSny8=^6injFFKzt_Pu_qgFe6t=CH*`^<~flFG7~XX2Q$@!C6m&r;^J= zS1VNK3b$+MX<}_;uAe2ECf0u#WN$G@T{+Hg&mav0eW`Fr^(iyW%vm#+j9fFWQa@#x z@w`);S4V7RUdWPkhGh-w z$Di`!p6*-5y#74)AlJYCj?I#e^q!C1+GpM|h0~wMgRxoct>F8mP?3$xGm`!mS@ON= zkF{QMpKkKA^}K4%zy7Xczn)dU2?~@)+Drqy#C+D$p)S(^nw2Qf^mHHk65E$sx4FtX z|Ku}q4)-KpK+oj!OOq*<<|wA8Rx|d=YUJK>mr;PHM;R3+j{^Bjec0(o(j@t1N;Hof zI^-kpabFjuiPTa)os1#3ztdx;d91`pW&BLyRN|^!F5?K|**CHyn(@yI?H)7D*`~)?| z%%gMnL`SPK2IBf$oJ&jT*fzIUe`hX?h&cd8cJFc|=81aWUM*68xBk0--;TEjEj_#E z;xp^B_Y9tyr>ghdEK}X8gKxJqrSft+A&nAL$M+pc0)F!wN#n7o$9#&-U&T88^Pm}M zqfM^-RP=PJbL5NW*;54q9vBtQ4@7G}=YBatNvo)- z@miHOV{Xl~nd^-5yMEVuq3V|zDyxOvk){CBd*MTT?9aCy8Oeblv8w6=(RN31lf`!R zcguYbgAHR2yidQhZGAHec*^FJsr#TxeZ2n9p&5sQ+GKJXR$Oz0c?i`IR~ktjLynRfAP6%+3vaYVlOH6BnZE<6a|crpTUXw4II3 zM>I|kczZYKLAb);c+we;W*DF`b>X&R!29>(I2_aS#hylhPxfI7&S-|;DwN5)r95&I z@Xw1AscvE3-l{0hqtUoSRcLV@vty2%Ha&pn zK&{QZ<}zlL|4sRgZ$h*%FU?9sFu1ZbZT7)Nh^6<{B5n`JZtPy!iEjLB^nY_%*)=;X zRB)5YnHH8kVcBGw)je^hb0DswHrQ-&$##z8CCYL-BWl@b@(|rHG`)tJmyIS?LzWm5 zv$n_=+Sb+-9c%UIa*@BsN8|Ae)s*0uIOcW7F+gQ_?l4FI5hE*8!DSB1W=B|TeOovD zF$p4}*5_AuZR zImTBw7N+;5yU<{GeP&_3_S1EajgFNVUUg1|JC*3H)Ux##D;jSft8P3OD;)R4f6Q;L z3Kpw%M2mgY$14UWLt}imD|nuY-|*jFsV%RuMhC6x)6e2iQ{fO;)&#k?RmIfKGGA;M zdsyR#$*`u-F#CZ9pgJAsut{qft-Y;ruLOBn7q+O{{ThzUUXKC>ksYgNJ?RD8x-iE& zx>wp6? z=PS_?383QAc#jIj5Ax@&?)XSL5xN82u_EBI?^A}1IZ@~vd9gcOtQ#e#$NZI7&?2wE zfo1?-sJueU?CFauA`Gl`}hL|63(6mAsyEa#j{$yPhR+F_> ztOMc-S(04t+Pwo-a2!iN&F&Xa(du&mtQEOXt3QUhlCK)ySLK1om&d$0csbPlbi70> zoAM71WFx4W*p~gk^QTIHIIo)o&O)=eUTGi*;%c6@IK_2k96_ADPN9wziD%sJo<;AT z)xDkhYM^4o{{26cvta-{(gGHpc{^q|&%;dKovSN&9k(I-zaOII_WfD*gWQ`hz8*3e z_5E4$CrpC=*K_|dlj}Y{l}~;Sj>_>~e2?5cKI(}wBmk$m@Ujo@81bW7^ZH1rE8JC- z8LMugk-y`|5>~RWX(>MF`NyP2E zq7qhC;Wgncw2#e3l=6b@DFbfvoj6h$eM}|%Mrhz!;-fR++g62I1;QQiF)K%Z9*g59 zK?BbcAu)Fm*WTkZbdN5&!Ish{Mw7)0#C%s@^BaBG`V5*;6Z*ydgmTYvdKsBhn=upOK5uG|C-HkbWU0Oyu;ve`Rck!vYJ9+=S{FMOTj!z?ioaRjb~t*?`*O9 zO}_2W`4QVSQYMYLY1Y>;YlZLW_c`*VQmoIX+-h?R?CpCYIH>JCmF$01yz*8@))zYr zH;I?o+D@@WOH_)#(}%1n-l^~Xl0L^d97jE#?-a`XChyw5p?F^SH&z>FUO_o#no~RN z`XbK6u-l#QEQj3t%(+V}_8tmS5%T)7MkL+Ej^}(QFJGg=c$~g-vbg==vDtI)-`nxy z?C`AggeTSPu|9?s)W9@5JgYOn1I3s(1+MFYr(R>=n75;8#*}|j{J3`*sW&@*Y*(Bd ziuh|B9<$Q6a|2T2l(Khbh3BOtfyl#l+Kq7dnZbh`)hj|{?O()BiGLU zHur9^ZT+orY)tBXPP)HImaXUUnP2wEv>FX&MBDq%*Us|%WQdw)M%y7`CiMCtYMv2o zhlm-_>xZa$CbS(QW&xA*8o3+D460ZyO*OIC7S?;_ z`SITS@wQ`$s;E-?Wh|AdqwMW*cuJD>pY6fE3_h0cwpRDC*t7RQbTO-7JE2&8FqtGM zmfj)v%60Q*obLHEtjV_BSy*xJYip@9X1`6#*>-uuTVEAN@!tp7EuYFF_Gz;n+8^r< zkmT#z@!q`BHHR~{PJaIWRexkah(o&CQdc;w0)VoGOIl&FA-`s z?Y{{I--X#B;|=d2KjtHI>{BV0{s$Ld34-p)$Ju8z-g++AJ{n{X4om;`X`S)fssh_- zvyLt3)EyI>!hr3B={XSaZ0iOb;_*9F{0+lgJ9~Ao6U=vE*ABG4?}#{wYSTezwVLk* zF;TYded;hiz0A5YJI?-8Hjl-QpK&ixTYJE~3lVMJ4ts!3vr}rHk?aH>W(RMhob!pp z=wnIc>z+pYv%Y=$+0AfJ=a01Y>06zZx1+^&IUT=}>$#VK=8m&z^k%LDjGLJEw7qRp z*~faBRz*r}KRmaS25*Emo*{L7XUoOhD*XDDr-a21xQMN4j zdH5~V?GbBxj-7at|3%|e_aoYtER+8~EWhsU;J0q5C2H1*Q^7j5a;)1=KXdY5$iGoF zK<>(|7ZpRs?K!=!Yg}Ykw?ovJLW31q6BJmlx(xfsSl_d&cMVVZ+vzVb#BQ35iU056 znMHrb+pA+d`YZmV9p{9u%e~lKvkc@6bmB2o8qhSQlS%{!t_)^OzzDlCtB)00M2%GBFYCJ({Q^gV6;& z3p~|Qm_Hd*A3%buESxVx_L$D1=_;H@C!Owj7XW?&i=0h84j1X1E(wRJ>r>tIRe#KM zQ?;Ct@s*t^^uOQ1SFhLo_`whEEraR))Hi~mV+ZU{x*3{Z4c))@ad+oWUB{ic;!;!H zz;tYJg8^g1o`{>^+SG1_o;o%@elWfYu$XInovNBJ%EN8-vMcsyP!oPl1T2;A9DK(ZP*o^E&ompk#V2a_Oxy!fZp9;Je`k)w1v9R;}hN~gbPv|pqv$%*4C z9Z-b{z0CyO7}hYf{32ShwwV+q7C$gB?UJSuNBi;6H0N8CNou884mdk3>pk*myPA|{;J6yWBU;Y^Z{G~d+s?4S z;FaKRGedLW*aps5sZFFEBPVc7Xhy$BgD=jM%L_#t_*30;TR7#*Ip>pl%K(oJG zDm}TdBhQ(*72-+V*j5+FzbX(8tl_My^e^8-nP-fMJwcWi&Evd?G7I1P2~)1Hpg_>= zf7ydUFl`ybfVfdw{%anD4_cZOS-R+TTS}n8j=0@GNtBD8a(RVi70`&B3XhCdXgIMo z@=Bc4j&cPPIqQLdOU1%E`Hn~HLzgx!q%nfCzBbI!H9aoP_SW>x0UY6xb*$MNR<}8!y;MpS+nJ-KtJf@^KNsxe@e_M^W!F)X#eXpG zbvFO+fBsiCW8Je3G_A5t0A>%XcHWaa#STyvTM>eYS+oqZKXMjk5nE;HD$0simOioK zIf^q1FjmoH5r2zV`hvhKKm9!ko+B15*Nd=7GZyFU2|v+n{TLQ;njk0%lNln7Z_y%M zEu*Aht972SC*s&dx+RNM=)2UY_-6%dAP*L*L2NhDIc(i=HUYK zfd2F?hukp1Vz=B2c6fAscT1|E>tQ{gZ?^{SMaa!!(GJK;Gkpg*g=Q|X9B*r)WbluM!t>$*=1eAm}+X#Ov&dReta7vz2RgZj@! z{6K*I5rxTbi*&tWqcA3kom9yE#N|H5N;7q~h%$Ck<7Nlv)%ii3>TDL5tNoZoxX$ZA z3drqmBwFzqV`J=i_dDTRzpt?F6NOd?AMj#?OS1x1}Q3=uZY(HY_EsY=Y-R`?!>hPx9#g5y_=sKguRQRHS%rP4~}m|e=UM&+iA887ee>3MHsf@jgf`42J50ola_-0j)dW=6oerV!3OUuSC?4qD>#1yw0|WCtC*B&yN%m0c3_2_Bg|;Fsdw+fM>byVIZWme z`xY+N(T^~lwjI5c(D-(Ct6CGoMj8eKg8h6sWI|FDWNR1LzL6yGP<+RT_V4@W9i`W= z?)p0+k`^Y9ks?;1yfU)TlWBE;;_%2G~0t#V-a=Eyefp(CpYzr;_q3XW;tIyVNQ z+0n$*4a>BV&g+#~m85)Icu>mq6qa2X!hI)FfHA5nrj7VljG)IJh34{k|E!D%=naz6 zfMdt_PG!cxL6SX|Q+mBJl%y%wj`ttsl+x3^c`CD~Qoi(-$d|$T`x&Spt#Q!(Qf?Il zy23%fGNJmoncwbJWjOLm$!wX%5$w7YI^@de@f*fOL~)R<8u|Tx>6UjO0jj$37{3$-sx3tXuD>z62*#ZQC@ zWyVdZbYm<(uhwTirirvwpr%{)5*N>Gk-kKE0mj9)Kxx7w5{9QZ!&9UUQIfBbyM(LN zA{IFai%VEYUzTB< zFvh6bIIAc*JwZpHP#?*3D>~``^Wwy3JcHTUf{LR!DPb}ogj?ERl0fcY3 zs;440Z+O=-+TUZ;*CgIIzmhoPtBJ*+m)r}{g_MB7OASc5kBY%tC%+fN%VuOXM!ZQ` zZzn_*QMe(B5rA>k1fvGQRVO}<253HgHZTs#!fQu)v{x84_$VnGr9|EjpNi#Ch7tw7 zcR2uj97#;6X6U(|f$s+TTWxN)ytRQ1Eqs+lB8o7&k)VSL)kbYS%=2jZuz3Bwpkn*4`WDXy z4X?=i#&}@eH?nM{bEaX7Oczjo4#jGKf)lr<*=6mdO|=FHy#z2W0c>axff`jO1dz9D z3@1hvrTo|`w}W&(Uqo!U#xCxo`V^7TQ}we{D~BKH;m~hlSvbKkjAm1Zd!fQ?kcCN(I_t6-+O_KGcd#Rz+uHsRg_EXrYLh*)aHwqxgJ4W zILkl3WN{JE3RZYWR_=I)X<5cdwdlOLT)Q22a2+jHM|}Z55oFIrvHJVx&o3`8r)6xO zX7kSi@3mpMusXxOGX_4wrG^DO%o#sfV&c^1?Vdu6aRfZQ7N9vJ{0qTlHJOqjdSj^j z?;ouHl+2I$FE~BOpVP9eNcc{Wfs0Pv8YX`eW34RjJI%dVdiOA=HCiar^;6|15VWmW*C3G?MK|G=qjhqDYLAQDnQuZ(+NwsADk z%fX>?l$ zff9nc9QBE<7Hx5qISgWXR1}&*k=E8W%kWE_%k8X!=*@W>Dbuh`m~@!p8*ISrX`OI2 z-7gjB`gLQn(P|@hrD#sVs9WilXT+^IlaZY&%{EFf7SvoLUhnl>?PF9E8fu1_-XLx` zj5CYo??Jg;5O`NQ`Q;u~hJawR>=Y`U<-rxHtZwO*Bpj)WbzuLZAs_R+63Ic&tF`%Y zU42zcHRK`c2Ff*BK}%;)jc9&C4Uj-GFPM&1+Z-A`%w4p5b~bd?FDgT8FIrhKU4}{g zbovlet>|Zwsy^cUk6Mt^Op;1&Pj1@ zO)t1H?okmDO?C=;x=?<{QIRmCRwXsB!9jXnRlK8cjJki=&?A(c*JFGDJPK!c5RPxC zo`%rtI2>6qAg1tnLl19jpyx;F@%GRI)rJo-JYwn{aBgp=L$vK~KA>k?2<6qkH*o69 zMAI+#O~-C4Uv1c_PjA%{Qs9<_1DS~K%-^RjwPbV$Q1|P*0o4-G9YDSJ1F9vVJAnG{ z21Fu0m*iueDxh}CD{|OAao_DI4X>F`Y^oN@$;XwCNJ2+yRcYkHZOc)3-9Sc}GX5;D zb&K9Tgs#$K-J-o0ra(n~IwYrqT)Ghl=8SkRpD=1?!9O@3*K>44w!1HA_|Q^E{#f;I zsHOeVLTV+>+l7u6mn!}zTjde%Sta@K!1D+e_Uq(?lXLAP_dq!^fD!Imft zuxg`W1x9_+DokE&L{~I#r-Rc>9#5NR5(9c9{>X)nK{i{@Fc&dd8~ z+mwXK0xXeEpOR;b>N*sI@IF)myt!c~+9x!io?ZM#U8qg%sm+);UR^R*gf6K1zX;KUHHotf=|+(2qIO*#T~sW~ zL|^v^2?9m!t{PlRskPj&pufhVdm1yb&9Q44$Zi5dF9)?INxWPwc$yi_Fu3%L@4+=P zY)>Aew?=4^mMcuiRM(}XMbg55TW*Sk_75H~(t|4D+_#jYTfys!V3oAg3VVlYSU;hz z$6agvuhBN`89x{u1>y+KA;|Ji?w+!ANuA-0{^rO;RyNTM*4v!fqnkoZ`GIuMPElz| Lp`P)kwv_(?>WzI# From cd407dc84c335dc51a26b193abfa9591fb6ea64b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Dec 2012 23:56:49 -0800 Subject: [PATCH 156/276] In Windows, disable run/reset/pause when closed. Saw this a lot while testing and couldn't help but fix it. I know this is probably going away soon. --- Windows/WndMainWindow.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 1309ebddb3..debfc928bd 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -648,11 +648,12 @@ namespace MainWindow CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); CHECKITEM(ID_OPTIONS_FASTMEMORY, g_Config.bFastMemory); - BOOL enable = !Core_IsStepping(); - EnableMenuItem(menu,ID_EMULATION_RUN,enable); - EnableMenuItem(menu,ID_EMULATION_PAUSE,!enable); + UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED; + EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED); + EnableMenuItem(menu,ID_EMULATION_PAUSE, g_State.bEmuThreadStarted ? !enable : MF_GRAYED); + EnableMenuItem(menu,ID_EMULATION_RESET, g_State.bEmuThreadStarted ? MF_ENABLED : MF_GRAYED); - enable = g_State.bEmuThreadStarted; + enable = g_State.bEmuThreadStarted ? MF_GRAYED : MF_ENABLED; EnableMenuItem(menu,ID_FILE_LOAD,enable); EnableMenuItem(menu,ID_CPU_DYNAREC,enable); EnableMenuItem(menu,ID_CPU_INTERPRETER,enable); From 2dfbc0fec3563fc381188f6e2accdccb6f1aed21 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 01:38:29 -0800 Subject: [PATCH 157/276] Oops, don't need this here after all. --- GPU/GPUState.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 4eb3fcb33c..2f60deb5d6 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -56,8 +56,6 @@ void InitGfxState() memcpy(gstate.boneMatrix + i * 12, identity4x3, 12 * sizeof(float)); } - gpuStats.reset(); - switch (PSP_CoreParameter().gpuCore) { case GPU_NULL: gpu = new NullGPU(); From d378b1c32494cba0bd4a71544012b782ed33a075 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 01:41:15 -0800 Subject: [PATCH 158/276] Deallocate properly in shutdown, not in init. --- Core/HLE/sceCtrl.cpp | 6 +++++- Core/HLE/sceCtrl.h | 1 + Core/HLE/sceKernel.cpp | 2 ++ Core/HLE/sceUtility.cpp | 7 +++++-- Core/HLE/sceUtility.h | 1 + GPU/Null/NullGpu.cpp | 4 ++++ GPU/Null/NullGpu.h | 1 + 7 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index d47cea7df8..5874ae2865 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -260,7 +260,6 @@ void __CtrlInit() { ctrlTimer = CoreTiming::RegisterEvent("CtrlSampleTimer", __CtrlTimerUpdate); __DisplayListenVblank(__CtrlVblank); - waitingThreads.clear(); ctrlIdleReset = -1; ctrlIdleBack = -1; @@ -285,6 +284,11 @@ void __CtrlInit() memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data)); } +void __CtrlShutdown() +{ + waitingThreads.clear(); +} + u32 sceCtrlSetSamplingCycle(u32 cycle) { DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%u)", cycle); diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index dcb465f305..62dff53bcc 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -33,6 +33,7 @@ void Register_sceCtrl(); #define CTRL_RTRIGGER 0x0200 void __CtrlInit(); +void __CtrlShutdown(); void __CtrlButtonDown(u32 buttonBit); void __CtrlButtonUp(u32 buttonBit); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 713c4090ba..3197c11107 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -118,6 +118,8 @@ void __KernelShutdown() __PPGeShutdown(); + __CtrlShutdown(); + __UtilityShutdown(); __GeShutdown(); __SasShutdown(); __AudioShutdown(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index f686d722de..b66f705066 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -35,13 +35,16 @@ PSPOskDialog oskDialog; PSPPlaceholderDialog netDialog; void __UtilityInit() +{ + SavedataParam::Init(); +} + +void __UtilityShutdown() { saveDialog.Shutdown(); msgDialog.Shutdown(); oskDialog.Shutdown(); netDialog.Shutdown(); - - SavedataParam::Init(); } int sceUtilitySavedataInitStart(u32 paramAddr) diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index 3eefa42b8e..ba85cd06c9 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -18,5 +18,6 @@ #pragma once void __UtilityInit(); +void __UtilityShutdown(); void Register_sceUtility(); diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index c7668b0fb6..8502418850 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -50,6 +50,10 @@ NullGPU::NullGPU() { interruptsEnabled_ = true; dlIdGenerator = 1; +} + +NullGPU::~NullGPU() +{ dlQueue.clear(); } diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index a642ac11f8..199ad07e04 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -25,6 +25,7 @@ class NullGPU : public GPUInterface { public: NullGPU(); + ~NullGPU(); virtual void InitClear() {} virtual u32 EnqueueList(u32 listpc, u32 stall); virtual void UpdateStall(int listid, u32 newstall); From 23db819e90e5efb049593ec351c1c49ea091453f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 01:42:33 -0800 Subject: [PATCH 159/276] No longer need this forward decl. --- Core/HLE/sceKernelThread.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 55709e3709..8d03a17f8a 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -342,7 +342,6 @@ int eventScheduledWakeup; bool dispatchEnabled = true; -class MipsCallManager; MipsCallManager mipsCalls; // This seems nasty From 6250348f06e8cdddfcc306e8f6fd53539b124b17 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 21:33:27 +0800 Subject: [PATCH 160/276] Add GE_CMD_TEXBUFWIDTH0 to flush cmd list --- GPU/GLES/DisplayListInterpreter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 40c44a7fd2..d05fced423 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -74,6 +74,7 @@ const int flushBeforeCommandList[] = { GE_CMD_TEXSHADELS, GE_CMD_CLUTFORMAT, GE_CMD_TRANSFERSTART, + GE_CMD_TEXBUFWIDTH0, GE_CMD_TEXSIZE0, GE_CMD_TEXSIZE1, GE_CMD_TEXSIZE2, From fb3649ea97f1bf5336232a6a2882e7a9ab033d26 Mon Sep 17 00:00:00 2001 From: raven02 Date: Mon, 24 Dec 2012 21:34:02 +0800 Subject: [PATCH 161/276] Remove flush() --- GPU/GLES/TransformPipeline.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 4961d9e6cf..bece8c27e8 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -640,7 +640,6 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } break; } - Flush(); } void GLES_GPU::Flush() From 49e9a5738ca6ff4a29db16e94c3b908bb5e45cd0 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 25 Dec 2012 09:06:27 +0800 Subject: [PATCH 162/276] Put back byte array to stack and increase buffer size --- Core/ELF/PrxDecrypter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/ELF/PrxDecrypter.cpp b/Core/ELF/PrxDecrypter.cpp index 4419dcd665..84c7ce446c 100644 --- a/Core/ELF/PrxDecrypter.cpp +++ b/Core/ELF/PrxDecrypter.cpp @@ -576,9 +576,9 @@ static TAG_INFO2 *GetTagInfo2(u32 tagFind) } // Moving these out here is a really ugly hack to avoid a stack corruption warning, warranted or not -static u8 padding1[0x100]; -static u8 tmp1[0x150], tmp2[0x90+0x14], tmp3[0x60+0x14], tmp4[0x20]; -static u8 padding2[0x100]; +//static u8 padding1[0x100]; +//static u8 tmp1[0x150], tmp2[0x90+0x14], tmp3[0x60+0x14], tmp4[0x20]; +//static u8 padding2[0x100]; static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) { @@ -590,10 +590,11 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) } int retsize = *(int *)&inbuf[0xB0]; + u8 tmp1[0x150], tmp2[0x90+0x14], tmp3[0x90+0x14], tmp4[0x20]; memset(tmp1, 0, 0x150); memset(tmp2, 0, 0x90+0x14); - memset(tmp3, 0, 0x60+0x14); + memset(tmp3, 0, 0x90+0x14); memset(tmp4, 0, 0x20); if (inbuf != outbuf) From b8ae91237e1d55ffe8da2fac86ced7f1e94ba4cf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:04:28 -0800 Subject: [PATCH 163/276] Oops, missed some state in HLE to reset. --- Core/HLE/HLE.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 2290737f36..7812209467 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -57,7 +57,9 @@ void HLEInit() void HLEShutdown() { + hleAfterSyscall = HLE_AFTER_NOTHING; moduleDB.clear(); + unresolvedSyscalls.clear(); } void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable) From a4dd204ce8f3f9197f6654fab31e455b5624b306 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 25 Dec 2012 13:33:37 +0800 Subject: [PATCH 164/276] Fix I_CIRCLE right/bottom cutoff --- Core/Util/ppge_atlas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Util/ppge_atlas.cpp b/Core/Util/ppge_atlas.cpp index 7a8bf0fde9..b211096eb3 100644 --- a/Core/Util/ppge_atlas.cpp +++ b/Core/Util/ppge_atlas.cpp @@ -112,7 +112,7 @@ const AtlasFont *ppge_fonts[1] = { }; const AtlasImage ppge_images[6] = { {0.458984f, 0.001953f, 0.576172f, 0.119141f, 31, 31, "I_CROSS"}, - {0.193359f, 0.001953f, 0.314453f, 0.123047f, 32, 32, "I_CIRCLE"}, + {0.193359f, 0.001953f, 0.324453f, 0.133047f, 32, 32, "I_CIRCLE"}, {0.685547f, 0.001953f, 0.794922f, 0.111328f, 29, 29, "I_SQUARE"}, {0.322266f, 0.001953f, 0.451172f, 0.111328f, 34, 29, "I_TRIANGLE"}, {0.802734f, 0.001953f, 0.861328f, 0.193359f, 16, 50, "I_BUTTON"}, From dc21d5c462d0d9daf8e6c976306d228a3844d71b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:47:54 -0800 Subject: [PATCH 165/276] Add a mechanism for HLE to trigger a debug break. --- Core/HLE/HLE.cpp | 32 ++++++++++++++++++++++++++++++-- Core/HLE/HLE.h | 2 ++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 7812209467..dd9fe56a1a 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -28,6 +28,7 @@ #include "sceKernelThread.h" #include "sceKernelInterrupt.h" #include "../MIPS/MIPSCodeUtils.h" +#include "../Host.h" enum { @@ -43,6 +44,8 @@ enum HLE_AFTER_RESCHED_CALLBACKS = 0x08, // Run interrupts (and probably reschedule) after the syscall. HLE_AFTER_RUN_INTERRUPTS = 0x10, + // Switch to CORE_STEPPING after the syscall (for debugging.) + HLE_AFTER_DEBUG_BREAK = 0x20, }; static std::vector moduleDB; @@ -241,8 +244,33 @@ void hleRunInterrupts() hleAfterSyscall |= HLE_AFTER_RUN_INTERRUPTS; } -inline void hleFinishSyscall() +void hleDebugBreak() { + hleAfterSyscall |= HLE_AFTER_DEBUG_BREAK; +} + +// Pauses execution after an HLE call. +void hleExecuteDebugBreak(const HLEFunction &func) +{ + const u32 NID_SUSPEND_INTR = 0x092968F4, NID_RESUME_INTR = 0x5F10D406; + + // Never break on these, they're noise. + u32 blacklistedNIDs[] = {NID_SUSPEND_INTR, NID_RESUME_INTR, NID_IDLE}; + for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) + { + if (func.ID == blacklistedNIDs[i]) + return; + } + + Core_EnableStepping(true); + host->SetDebugMode(true); +} + +inline void hleFinishSyscall(int modulenum, int funcnum) +{ + if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) + hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum]); + if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -278,7 +306,7 @@ void CallSyscall(u32 op) func(); if (hleAfterSyscall != HLE_AFTER_NOTHING) - hleFinishSyscall(); + hleFinishSyscall(modulenum, funcnum); } else { diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 05ff70c612..fb0eefa1be 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -83,6 +83,8 @@ void hleReSchedule(const char *reason); void hleReSchedule(bool callbacks, const char *reason); // Run interrupts after the syscall finishes. void hleRunInterrupts(); +// Pause emulation after the syscall finishes. +void hleDebugBreak(); void HLEInit(); void HLEShutdown(); From 1d7a42f0b8b82999ccb9b6edcd8ebcce0edd409d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:48:19 -0800 Subject: [PATCH 166/276] Add a button on Windows to enable HLE stepping. --- Windows/Debugger/Debugger_Disasm.cpp | 33 +++++++++++++++++++-------- Windows/ppsspp.rc | Bin 28756 -> 28864 bytes Windows/resource.h | 3 ++- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index b326bc75bc..6d2097f1ee 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -14,6 +14,7 @@ #include "../../Core/Core.h" #include "../../Core/CPU.h" +#include "../../Core/HLE/HLE.h" #include "base/stringutil.h" @@ -136,10 +137,10 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_FUNCTIONLIST: - switch (HIWORD(wParam)) - { - case CBN_DBLCLK: - case CBN_SELCHANGE: + switch (HIWORD(wParam)) + { + case CBN_DBLCLK: + case CBN_SELCHANGE: { HWND lb = GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ListBox_GetCurSel(lb); @@ -154,9 +155,9 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_GOTOINT: - switch (HIWORD(wParam)) - { - case LBN_SELCHANGE: + switch (HIWORD(wParam)) + { + case LBN_SELCHANGE: { HWND lb =GetDlgItem(m_hDlg,LOWORD(wParam)); int n = ComboBox_GetCurSel(lb); @@ -192,7 +193,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) SetDebugMode(false); CBreakPoints::AddBreakPoint(cpu->GetPC()+cpu->getInstructionSize(0),true); _dbg_update_(); - Core_EnableStepping(false); + Core_EnableStepping(false); MainWindow::UpdateMenus(); Sleep(1); ptr->gotoPC(); @@ -200,6 +201,16 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) } break; + case IDC_STEPHLE: + { + hleDebugBreak(); + SetDebugMode(false); + _dbg_update_(); + Core_EnableStepping(false); + MainWindow::UpdateMenus(); + } + break; + case IDC_STOP: { SetDebugMode(true); @@ -241,8 +252,8 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) HWND list = GetDlgItem(hDlg,IDC_CALLSTACK); ComboBox_ResetContent(list); - u32 pc = currentMIPS->pc; - u32 ra = currentMIPS->r[MIPS_REG_RA]; + u32 pc = currentMIPS->pc; + u32 ra = currentMIPS->r[MIPS_REG_RA]; DWORD addr = Memory::ReadUnchecked_U32(pc); int count=1; ComboBox_SetItemData(list,ComboBox_AddString(list,symbolMap.GetDescription(pc)),pc); @@ -341,6 +352,7 @@ void CDisasm::SetDebugMode(bool _bDebug) EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEPOVER), TRUE); + EnableWindow( GetDlgItem(hDlg, IDC_STEPHLE), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STOP), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_SKIP), TRUE); CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); @@ -353,6 +365,7 @@ void CDisasm::SetDebugMode(bool _bDebug) EnableWindow( GetDlgItem(hDlg, IDC_GO), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STEPOVER), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_STEPHLE), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_STOP), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_SKIP), FALSE); } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 40f6f0e24f4608edab308ad315a56c3577fc3b70..3c691428661e75dc9a4105a434f708ed81e8a7dd 100644 GIT binary patch delta 84 zcmccefbqaX#tkZ*jGU7j*_Dm`7*ZK37)lrv7}OX%76usMbELmB`x$P-Nf delta 21 dcmX@`knzd`#tkZ*lkc!|O!i~bSbTsp9RO+K2$cW; diff --git a/Windows/resource.h b/Windows/resource.h index 09a16838bb..134447f2a5 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -246,13 +246,14 @@ #define ID_OPTIONS_WIREFRAME 40123 #define ID_OPTIONS_HARDWARETRANSFORM 40124 #define ID_OPTIONS_FASTMEMORY 40125 +#define IDC_STEPHLE 40126 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 232 -#define _APS_NEXT_COMMAND_VALUE 40126 +#define _APS_NEXT_COMMAND_VALUE 40127 #define _APS_NEXT_CONTROL_VALUE 1162 #define _APS_NEXT_SYMED_VALUE 101 #endif From 6a6db5f53a558ebab998e37a1fe26c72b912dc30 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 21:58:54 -0800 Subject: [PATCH 167/276] Remember to break on HLE after an ignored syscall. --- Core/HLE/HLE.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index dd9fe56a1a..f58a2aca4f 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -250,7 +250,7 @@ void hleDebugBreak() } // Pauses execution after an HLE call. -void hleExecuteDebugBreak(const HLEFunction &func) +bool hleExecuteDebugBreak(const HLEFunction &func) { const u32 NID_SUSPEND_INTR = 0x092968F4, NID_RESUME_INTR = 0x5F10D406; @@ -259,18 +259,16 @@ void hleExecuteDebugBreak(const HLEFunction &func) for (int i = 0; i < ARRAY_SIZE(blacklistedNIDs); ++i) { if (func.ID == blacklistedNIDs[i]) - return; + return false; } Core_EnableStepping(true); host->SetDebugMode(true); + return true; } inline void hleFinishSyscall(int modulenum, int funcnum) { - if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) - hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum]); - if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -285,6 +283,17 @@ inline void hleFinishSyscall(int modulenum, int funcnum) else if ((hleAfterSyscall & HLE_AFTER_ALL_CALLBACKS) != 0) __KernelCheckCallbacks(); + if ((hleAfterSyscall & HLE_AFTER_DEBUG_BREAK) != 0) + { + if (!hleExecuteDebugBreak(moduleDB[modulenum].funcTable[funcnum])) + { + // We'll do it next syscall. + hleAfterSyscall = HLE_AFTER_DEBUG_BREAK; + hleAfterSyscallReschedReason[0] = 0; + return; + } + } + hleAfterSyscall = HLE_AFTER_NOTHING; hleAfterSyscallReschedReason[0] = 0; } From b8fcdc37e653c2e5d2e422ea68d3564a6c783cc5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 22:12:52 -0800 Subject: [PATCH 168/276] When not ignoring bad mem access, break to debug. --- Core/MemMapFunctions.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index e468e79a51..faa0e5fa18 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -20,6 +20,7 @@ #include "MemMap.h" #include "Config.h" +#include "Host.h" #include "MIPS/MIPS.h" @@ -84,8 +85,8 @@ inline void ReadFromHardware(T &var, const u32 address) { WARN_LOG(MEMMAP, "ReadFromHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); if (!g_Config.bIgnoreBadMemAccess) { - // TODO: Not sure what the best way to crash is... - exit(0); + Core_EnableStepping(true); + host->SetDebugMode(true); } var = 0; } @@ -112,8 +113,8 @@ inline void WriteToHardware(u32 address, const T data) { WARN_LOG(MEMMAP, "WriteToHardware: Invalid address %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); if (!g_Config.bIgnoreBadMemAccess) { - // TODO: Not sure what the best way to crash is... - exit(0); + Core_EnableStepping(true); + host->SetDebugMode(true); } } } From 875f3569eee6c53054423d388997261e6fc73fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 08:20:39 +0100 Subject: [PATCH 169/276] Don't let DecryptPRX1 scramble the keys in-place (!), make a copy instead. Could now make all the keys const, as they should be. --- Core/ELF/PrxDecrypter.cpp | 345 +++++++++++++++++++------------------- 1 file changed, 171 insertions(+), 174 deletions(-) diff --git a/Core/ELF/PrxDecrypter.cpp b/Core/ELF/PrxDecrypter.cpp index 84c7ce446c..8541c0358c 100644 --- a/Core/ELF/PrxDecrypter.cpp +++ b/Core/ELF/PrxDecrypter.cpp @@ -10,248 +10,248 @@ extern "C" // Thank you PSARDUMPER & JPCSP keys // PRXDecrypter 16-byte tag keys. -u8 keys260_0[] = {0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E, 0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1}; -u8 keys260_1[] = {0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7, 0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A}; -u8 keys260_2[] = {0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82, 0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C}; -u8 keys280_0[] = {0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40, 0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1}; -u8 keys280_1[] = {0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F, 0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74}; -u8 keys280_2[] = {0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07, 0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5}; -u8 keys300_0[] = {0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B, 0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77}; -u8 keys300_1[] = {0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34, 0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2}; -u8 keys300_2[] = {0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C, 0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73}; -u8 keys303_0[] = {0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13, 0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf}; -u8 keys310_0[] = {0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb, 0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f}; -u8 keys310_1[] = {0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65, 0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA}; -u8 keys310_2[] = {0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D, 0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B}; -u8 keys310_3[] = {0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A, 0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F}; -u8 keys330_0[] = {0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED, 0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A}; -u8 keys330_1[] = {0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, 0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26}; -u8 keys330_2[] = {0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, 0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7}; -u8 keys330_3[] = {0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, 0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B}; -u8 keys330_4[] = {0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9, 0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F}; -u8 keys360_0[] = {0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, 0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED}; -u8 keys360_1[] = {0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, 0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34}; -u8 keys370_0[] = {0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, 0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB}; -u8 keys370_1[] = {0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, 0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA}; -u8 keys370_2[] = {0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, 0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89}; -u8 keys390_0[] = {0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, 0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D}; -u8 keys390_1[] = {0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, 0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9}; -u8 keys500_0[] = {0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, 0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0}; -u8 keys500_1[] = {0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, 0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B}; -u8 keys500_2[] = {0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, 0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B}; -u8 keys500_c[] = {0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA, 0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D}; -u8 keys505_a[] = {0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B, 0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87}; -u8 keys505_0[] = {0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73, 0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0}; -u8 keys505_1[] = {0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D, 0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11}; -u8 keys570_5k[] = {0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1, 0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66}; -u8 keys600_1[] = {0xE3, 0x52, 0x39, 0x97, 0x3B, 0x84, 0x41, 0x1C, 0xC3, 0x23, 0xF1, 0xB8, 0xA9, 0x09, 0x4B, 0xF0}; -u8 keys600_2[] = {0xE1, 0x45, 0x93, 0x2C, 0x53, 0xE2, 0xAB, 0x06, 0x6F, 0xB6, 0x8F, 0x0B, 0x66, 0x91, 0xE7, 0x1E}; -u8 keys620_0[] = {0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6, 0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB}; -u8 keys620_1[] = {0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2, 0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7}; -u8 keys620_a[] = {0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F, 0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2}; -u8 keys620_e[] = {0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6, 0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3}; -u8 keys620_5[] = {0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30, 0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E}; -u8 keys620_5k[] = {0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04, 0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21}; -u8 keys620_5v[] = {0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E, 0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32}; -u8 keys630_k1[] = {0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, 0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B}; -u8 keys630_k2[] = {0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, 0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d}; -u8 keys630_k3[] = {0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA, 0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50}; -u8 keys630_k4[] = {0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD, 0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD}; -u8 keys630_k5[] = {0x87, 0x37, 0x21, 0xCC, 0x65, 0xAE, 0xAA, 0x5F, 0x40, 0xF6, 0x6F, 0x2A, 0x86, 0xC7, 0xA1, 0xC8}; -u8 keys630_k6[] = {0x8D, 0xDB, 0xDC, 0x5C, 0xF2, 0x70, 0x2B, 0x40, 0xB2, 0x3D, 0x00, 0x09, 0x61, 0x7C, 0x10, 0x60}; -u8 keys630_k7[] = {0x77, 0x1C, 0x06, 0x5F, 0x53, 0xEC, 0x3F, 0xFC, 0x22, 0xCE, 0x5A, 0x27, 0xFF, 0x78, 0xA8, 0x48}; -u8 keys630_k8[] = {0x81, 0xD1, 0x12, 0x89, 0x35, 0xC8, 0xEA, 0x8B, 0xE0, 0x02, 0x2D, 0x2D, 0x6A, 0x18, 0x67, 0xB8}; -u8 keys636_k1[] = {0x07, 0xE3, 0x08, 0x64, 0x7F, 0x60, 0xA3, 0x36, 0x6A, 0x76, 0x21, 0x44, 0xC9, 0xD7, 0x06, 0x83}; -u8 keys636_k2[] = {0x91, 0xF2, 0x02, 0x9E, 0x63, 0x32, 0x30, 0xA9, 0x1D, 0xDA, 0x0B, 0xA8, 0xB7, 0x41, 0xA3, 0xCC}; -u8 keys638_k4[] = {0x98, 0x43, 0xFF, 0x85, 0x68, 0xB2, 0xDB, 0x3B, 0xD4, 0x22, 0xD0, 0x4F, 0xAB, 0x5F, 0x0A, 0x31}; -u8 keys639_k3[] = {0x01, 0x7B, 0xF0, 0xE9, 0xBE, 0x9A, 0xDD, 0x54, 0x37, 0xEA, 0x0E, 0xC4, 0xD6, 0x4D, 0x8E, 0x9E}; -u8 keys660_k1[] = {0x76, 0xF2, 0x6C, 0x0A, 0xCA, 0x3A, 0xBA, 0x4E, 0xAC, 0x76, 0xD2, 0x40, 0xF5, 0xC3, 0xBF, 0xF9}; -u8 keys660_k2[] = {0x7A, 0x3E, 0x55, 0x75, 0xB9, 0x6A, 0xFC, 0x4F, 0x3E, 0xE3, 0xDF, 0xB3, 0x6C, 0xE8, 0x2A, 0x82}; -u8 keys660_k3[] = {0xFA, 0x79, 0x09, 0x36, 0xE6, 0x19, 0xE8, 0xA4, 0xA9, 0x41, 0x37, 0x18, 0x81, 0x02, 0xE9, 0xB3}; -u8 keys660_v1[] = {0xBA, 0x76, 0x61, 0x47, 0x8B, 0x55, 0xA8, 0x72, 0x89, 0x15, 0x79, 0x6D, 0xD7, 0x2F, 0x78, 0x0E}; -u8 keys660_v2[] = {0xF9, 0x4A, 0x6B, 0x96, 0x79, 0x3F, 0xEE, 0x0A, 0x04, 0xC8, 0x8D, 0x7E, 0x5F, 0x38, 0x3A, 0xCF}; -u8 keys660_v3[] = {0x88, 0xAF, 0x18, 0xE9, 0xC3, 0xAA, 0x6B, 0x56, 0xF7, 0xC5, 0xA8, 0xBF, 0x1A, 0x84, 0xE9, 0xF3}; -u8 keys660_v4[] = {0xD1, 0xB0, 0xAE, 0xC3, 0x24, 0x36, 0x13, 0x49, 0xD6, 0x49, 0xD7, 0x88, 0xEA, 0xA4, 0x99, 0x86}; -u8 keys660_v5[] = {0xCB, 0x93, 0x12, 0x38, 0x31, 0xC0, 0x2D, 0x2E, 0x7A, 0x18, 0x5C, 0xAC, 0x92, 0x93, 0xAB, 0x32}; -u8 keys660_v6[] = {0x92, 0x8C, 0xA4, 0x12, 0xD6, 0x5C, 0x55, 0x31, 0x5B, 0x94, 0x23, 0x9B, 0x62, 0xB3, 0xDB, 0x47}; -u8 keys660_k4[] = {0xC8, 0xA0, 0x70, 0x98, 0xAE, 0xE6, 0x2B, 0x80, 0xD7, 0x91, 0xE6, 0xCA, 0x4C, 0xA9, 0x78, 0x4E}; -u8 keys660_k5[] = {0xBF, 0xF8, 0x34, 0x02, 0x84, 0x47, 0xBD, 0x87, 0x1C, 0x52, 0x03, 0x23, 0x79, 0xBB, 0x59, 0x81}; -u8 keys660_k6[] = {0xD2, 0x83, 0xCC, 0x63, 0xBB, 0x10, 0x15, 0xE7, 0x7B, 0xC0, 0x6D, 0xEE, 0x34, 0x9E, 0x4A, 0xFA}; -u8 keys660_k7[] = {0xEB, 0xD9, 0x1E, 0x05, 0x3C, 0xAE, 0xAB, 0x62, 0xE3, 0xB7, 0x1F, 0x37, 0xE5, 0xCD, 0x68, 0xC3}; -u8 keys660_v7[] = {0xC5, 0x9C, 0x77, 0x9C, 0x41, 0x01, 0xE4, 0x85, 0x79, 0xC8, 0x71, 0x63, 0xA5, 0x7D, 0x4F, 0xFB}; -u8 keys660_v8[] = {0x86, 0xA0, 0x7D, 0x4D, 0xB3, 0x6B, 0xA2, 0xFD, 0xF4, 0x15, 0x85, 0x70, 0x2D, 0x6A, 0x0D, 0x3A}; -u8 keys660_k8[] = {0x85, 0x93, 0x1F, 0xED, 0x2C, 0x4D, 0xA4, 0x53, 0x59, 0x9C, 0x3F, 0x16, 0xF3, 0x50, 0xDE, 0x46}; -u8 key_21C0[] = {0x6A, 0x19, 0x71, 0xF3, 0x18, 0xDE, 0xD3, 0xA2, 0x6D, 0x3B, 0xDE, 0xC7, 0xBE, 0x98, 0xE2, 0x4C}; -u8 key_2250[] = {0x50, 0xCC, 0x03, 0xAC, 0x3F, 0x53, 0x1A, 0xFA, 0x0A, 0xA4, 0x34, 0x23, 0x86, 0x61, 0x7F, 0x97}; -u8 key_22E0[] = {0x66, 0x0F, 0xCB, 0x3B, 0x30, 0x75, 0xE3, 0x10, 0x0A, 0x95, 0x65, 0xC7, 0x3C, 0x93, 0x87, 0x22}; -u8 key_2D80[] = {0x40, 0x02, 0xC0, 0xBF, 0x20, 0x02, 0xC0, 0xBF, 0x5C, 0x68, 0x2B, 0x95, 0x5F, 0x40, 0x7B, 0xB8}; -u8 key_2D90[] = {0x55, 0x19, 0x35, 0x10, 0x48, 0xD8, 0x2E, 0x46, 0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F}; -u8 key_2DA8[] = {0x80, 0x02, 0xC0, 0xBF, 0x00, 0x0A, 0xC0, 0xBF, 0x40, 0x03, 0xC0, 0xBF, 0x40, 0x00, 0x00, 0x00}; -u8 key_2DB8[] = {0x4C, 0x2D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -u8 key_D91605F0[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31}; -u8 key_D91606F0[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7}; -u8 key_D91608F0[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF}; -u8 key_D91609F0[] = {0xD0, 0x36, 0x12, 0x75, 0x80, 0x56, 0x20, 0x43, 0xC4, 0x30, 0x94, 0x3E, 0x1C, 0x75, 0xD1, 0xBF}; -u8 key_D9160AF0[] = {0x10, 0xA9, 0xAC, 0x16, 0xAE, 0x19, 0xC0, 0x7E, 0x3B, 0x60, 0x77, 0x86, 0x01, 0x6F, 0xF2, 0x63}; -u8 key_D9160BF0[] = {0x83, 0x83, 0xF1, 0x37, 0x53, 0xD0, 0xBE, 0xFC, 0x8D, 0xA7, 0x32, 0x52, 0x46, 0x0A, 0xC2, 0xC2}; -u8 key_D91611F0[] = {0x61, 0xB0, 0xC0, 0x58, 0x71, 0x57, 0xD9, 0xFA, 0x74, 0x67, 0x0E, 0x5C, 0x7E, 0x6E, 0x95, 0xB9}; -u8 key_D91612F0[] = {0x9E, 0x20, 0xE1, 0xCD, 0xD7, 0x88, 0xDE, 0xC0, 0x31, 0x9B, 0x10, 0xAF, 0xC5, 0xB8, 0x73, 0x23}; -u8 key_D91613F0[] = {0xEB, 0xFF, 0x40, 0xD8, 0xB4, 0x1A, 0xE1, 0x66, 0x91, 0x3B, 0x8F, 0x64, 0xB6, 0xFC, 0xB7, 0x12}; -u8 key_D91614F0[] = {0xFD, 0xF7, 0xB7, 0x3C, 0x9F, 0xD1, 0x33, 0x95, 0x11, 0xB8, 0xB5, 0xBB, 0x54, 0x23, 0x73, 0x85}; -u8 key_D91615F0[] = {0xC8, 0x03, 0xE3, 0x44, 0x50, 0xF1, 0xE7, 0x2A, 0x6A, 0x0D, 0xC3, 0x61, 0xB6, 0x8E, 0x5F, 0x51}; -u8 key_D91616F0[] = {0x53, 0x03, 0xB8, 0x6A, 0x10, 0x19, 0x98, 0x49, 0x1C, 0xAF, 0x30, 0xE4, 0x25, 0x1B, 0x6B, 0x28}; -u8 key_D91617F0[] = {0x02, 0xFA, 0x48, 0x73, 0x75, 0xAF, 0xAE, 0x0A, 0x67, 0x89, 0x2B, 0x95, 0x4B, 0x09, 0x87, 0xA3}; -u8 key_D91618F0[] = {0x96, 0x96, 0x7C, 0xC3, 0xF7, 0x12, 0xDA, 0x62, 0x1B, 0xF6, 0x9A, 0x9A, 0x44, 0x44, 0xBC, 0x48}; -u8 key_D91619F0[] = {0xE0, 0x32, 0xA7, 0x08, 0x6B, 0x2B, 0x29, 0x2C, 0xD1, 0x4D, 0x5B, 0xEE, 0xA8, 0xC8, 0xB4, 0xE9}; -u8 key_D9161AF0[] = {0x27, 0xE5, 0xA7, 0x49, 0x52, 0xE1, 0x94, 0x67, 0x35, 0x66, 0x91, 0x0C, 0xE8, 0x9A, 0x25, 0x24}; -u8 key_D91620F0[] = {0x52, 0x1C, 0xB4, 0x5F, 0x40, 0x3B, 0x9A, 0xDD, 0xAC, 0xFC, 0xEA, 0x92, 0xFD, 0xDD, 0xF5, 0x90}; -u8 key_D91621F0[] = {0xD1, 0x91, 0x2E, 0xA6, 0x21, 0x14, 0x29, 0x62, 0xF6, 0xED, 0xAE, 0xCB, 0xDD, 0xA3, 0xBA, 0xFE}; -u8 key_D91622F0[] = {0x59, 0x5D, 0x78, 0x4D, 0x21, 0xB2, 0x01, 0x17, 0x6C, 0x9A, 0xB5, 0x1B, 0xDA, 0xB7, 0xF9, 0xE6}; -u8 key_D91623F0[] = {0xAA, 0x45, 0xEB, 0x4F, 0x62, 0xFB, 0xD1, 0x0D, 0x71, 0xD5, 0x62, 0xD2, 0xF5, 0xBF, 0xA5, 0x2F}; -u8 key_D91624F0[] = {0x61, 0xB7, 0x26, 0xAF, 0x8B, 0xF1, 0x41, 0x58, 0x83, 0x6A, 0xC4, 0x92, 0x12, 0xCB, 0xB1, 0xE9}; -u8 key_D91628F0[] = {0x49, 0xA4, 0xFC, 0x66, 0xDC, 0xE7, 0x62, 0x21, 0xDB, 0x18, 0xA7, 0x50, 0xD6, 0xA8, 0xC1, 0xB6}; -u8 key_D91680F0[] = {0x2C, 0x22, 0x9B, 0x12, 0x36, 0x74, 0x11, 0x67, 0x49, 0xD1, 0xD1, 0x88, 0x92, 0xF6, 0xA1, 0xD8}; -u8 key_D91681F0[] = {0x52, 0xB6, 0x36, 0x6C, 0x8C, 0x46, 0x7F, 0x7A, 0xCC, 0x11, 0x62, 0x99, 0xC1, 0x99, 0xBE, 0x98}; -u8 key_2E5E10F0[] = {0x9D, 0x5C, 0x5B, 0xAF, 0x8C, 0xD8, 0x69, 0x7E, 0x51, 0x9F, 0x70, 0x96, 0xE6, 0xD5, 0xC4, 0xE8}; -u8 key_2E5E12F0[] = {0x8A, 0x7B, 0xC9, 0xD6, 0x52, 0x58, 0x88, 0xEA, 0x51, 0x83, 0x60, 0xCA, 0x16, 0x79, 0xE2, 0x07}; -u8 key_2E5E13F0[] = {0xFF, 0xA4, 0x68, 0xC3, 0x31, 0xCA, 0xB7, 0x4C, 0xF1, 0x23, 0xFF, 0x01, 0x65, 0x3D, 0x26, 0x36}; -u8 key_2FD30BF0[] = {0xD8, 0x58, 0x79, 0xF9, 0xA4, 0x22, 0xAF, 0x86, 0x90, 0xAC, 0xDA, 0x45, 0xCE, 0x60, 0x40, 0x3F}; -u8 key_2FD311F0[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44}; -u8 key_2FD312F0[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE}; -u8 keys02G_E[] = {0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, 0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E}; -u8 keys03G_E[] = {0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, 0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA}; -u8 keys05G_E[] = {0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C, 0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54}; -u8 oneseg_310[] = {0xC7, 0x27, 0x72, 0x85, 0xAB, 0xA7, 0xF7, 0xF0, 0x4C, 0xC1, 0x86, 0xCC, 0xE3, 0x7F, 0x17, 0xCA}; -u8 oneseg_300[] = {0x76, 0x40, 0x9E, 0x08, 0xDB, 0x9B, 0x3B, 0xA1, 0x47, 0x8A, 0x96, 0x8E, 0xF3, 0xF7, 0x62, 0x92}; -u8 oneseg_280[] = {0x23, 0xDC, 0x3B, 0xB5, 0xA9, 0x82, 0xD6, 0xEA, 0x63, 0xA3, 0x6E, 0x2B, 0x2B, 0xE9, 0xE1, 0x54}; -u8 oneseg_260_271[] = {0x22, 0x43, 0x57, 0x68, 0x2F, 0x41, 0xCE, 0x65, 0x4C, 0xA3, 0x7C, 0xC6, 0xC4, 0xAC, 0xF3, 0x60}; -u8 oneseg_slim[] = {0x12, 0x57, 0x0D, 0x8A, 0x16, 0x6D, 0x87, 0x06, 0x03, 0x7D, 0xC8, 0x8B, 0x62, 0xA3, 0x32, 0xA9}; -u8 ms_app_main[] = {0x1E, 0x2E, 0x38, 0x49, 0xDA, 0xD4, 0x16, 0x08, 0x27, 0x2E, 0xF3, 0xBC, 0x37, 0x75, 0x80, 0x93}; -u8 demokeys_280[] = {0x12, 0x99, 0x70, 0x5E, 0x24, 0x07, 0x6C, 0xD0, 0x2D, 0x06, 0xFE, 0x7E, 0xB3, 0x0C, 0x11, 0x26}; -u8 demokeys_3XX_1[] = {0x47, 0x05, 0xD5, 0xE3, 0x56, 0x1E, 0x81, 0x9B, 0x09, 0x2F, 0x06, 0xDB, 0x6B, 0x12, 0x92, 0xE0}; -u8 demokeys_3XX_2[] = {0xF6, 0x62, 0x39, 0x6E, 0x26, 0x22, 0x4D, 0xCA, 0x02, 0x64, 0x16, 0x99, 0x7B, 0x9A, 0xE7, 0xB8}; -u8 ebootbin_271_new[] = {0xF4, 0xAE, 0xF4, 0xE1, 0x86, 0xDD, 0xD2, 0x9C, 0x7C, 0xC5, 0x42, 0xA6, 0x95, 0xA0, 0x83, 0x88}; -u8 ebootbin_280_new[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31}; -u8 ebootbin_300_new[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7}; -u8 ebootbin_310_new[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF}; -u8 gameshare_260_271[] = {0xF9, 0x48, 0x38, 0x0C, 0x96, 0x88, 0xA7, 0x74, 0x4F, 0x65, 0xA0, 0x54, 0xC2, 0x76, 0xD9, 0xB8}; -u8 gameshare_280[] = {0x2D, 0x86, 0x77, 0x3A, 0x56, 0xA4, 0x4F, 0xDD, 0x3C, 0x16, 0x71, 0x93, 0xAA, 0x8E, 0x11, 0x43}; -u8 gameshare_300[] = {0x78, 0x1A, 0xD2, 0x87, 0x24, 0xBD, 0xA2, 0x96, 0x18, 0x3F, 0x89, 0x36, 0x72, 0x90, 0x92, 0x85}; -u8 gameshare_310[] = {0xC9, 0x7D, 0x3E, 0x0A, 0x54, 0x81, 0x6E, 0xC7, 0x13, 0x74, 0x99, 0x74, 0x62, 0x18, 0xE7, 0xDD}; -u8 key_380210F0[] = {0x32, 0x2C, 0xFA, 0x75, 0xE4, 0x7E, 0x93, 0xEB, 0x9F, 0x22, 0x80, 0x85, 0x57, 0x08, 0x98, 0x48}; -u8 key_380280F0[] = {0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, 0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C}; -u8 key_380283F0[] = {0x34, 0x20, 0x0C, 0x8E, 0xA1, 0x86, 0x79, 0x84, 0xAF, 0x13, 0xAE, 0x34, 0x77, 0x6F, 0xEA, 0x89}; -u8 key_407810F0[] = {0xAF, 0xAD, 0xCA, 0xF1, 0x95, 0x59, 0x91, 0xEC, 0x1B, 0x27, 0xD0, 0x4E, 0x8A, 0xF3, 0x3D, 0xE7}; -u8 drmkeys_6XX_1[] = {0x36, 0xEF, 0x82, 0x4E, 0x74, 0xFB, 0x17, 0x5B, 0x14, 0x14, 0x05, 0xF3, 0xB3, 0x8A, 0x76, 0x18}; -u8 drmkeys_6XX_2[] = {0x21, 0x52, 0x5D, 0x76, 0xF6, 0x81, 0x0F, 0x15, 0x2F, 0x4A, 0x40, 0x89, 0x63, 0xA0, 0x10, 0x55}; +static const u8 keys260_0[] = {0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E, 0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1}; +static const u8 keys260_1[] = {0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7, 0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A}; +static const u8 keys260_2[] = {0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82, 0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C}; +static const u8 keys280_0[] = {0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40, 0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1}; +static const u8 keys280_1[] = {0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F, 0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74}; +static const u8 keys280_2[] = {0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07, 0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5}; +static const u8 keys300_0[] = {0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B, 0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77}; +static const u8 keys300_1[] = {0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34, 0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2}; +static const u8 keys300_2[] = {0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C, 0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73}; +static const u8 keys303_0[] = {0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13, 0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf}; +static const u8 keys310_0[] = {0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb, 0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f}; +static const u8 keys310_1[] = {0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65, 0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA}; +static const u8 keys310_2[] = {0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D, 0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B}; +static const u8 keys310_3[] = {0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A, 0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F}; +static const u8 keys330_0[] = {0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED, 0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A}; +static const u8 keys330_1[] = {0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, 0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26}; +static const u8 keys330_2[] = {0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, 0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7}; +static const u8 keys330_3[] = {0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, 0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B}; +static const u8 keys330_4[] = {0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9, 0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F}; +static const u8 keys360_0[] = {0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, 0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED}; +static const u8 keys360_1[] = {0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, 0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34}; +static const u8 keys370_0[] = {0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, 0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB}; +static const u8 keys370_1[] = {0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, 0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA}; +static const u8 keys370_2[] = {0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, 0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89}; +static const u8 keys390_0[] = {0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, 0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D}; +static const u8 keys390_1[] = {0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, 0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9}; +static const u8 keys500_0[] = {0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, 0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0}; +static const u8 keys500_1[] = {0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, 0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B}; +static const u8 keys500_2[] = {0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, 0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B}; +static const u8 keys500_c[] = {0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA, 0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D}; +static const u8 keys505_a[] = {0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B, 0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87}; +static const u8 keys505_0[] = {0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73, 0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0}; +static const u8 keys505_1[] = {0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D, 0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11}; +static const u8 keys570_5k[] = {0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1, 0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66}; +static const u8 keys600_1[] = {0xE3, 0x52, 0x39, 0x97, 0x3B, 0x84, 0x41, 0x1C, 0xC3, 0x23, 0xF1, 0xB8, 0xA9, 0x09, 0x4B, 0xF0}; +static const u8 keys600_2[] = {0xE1, 0x45, 0x93, 0x2C, 0x53, 0xE2, 0xAB, 0x06, 0x6F, 0xB6, 0x8F, 0x0B, 0x66, 0x91, 0xE7, 0x1E}; +static const u8 keys620_0[] = {0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6, 0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB}; +static const u8 keys620_1[] = {0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2, 0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7}; +static const u8 keys620_a[] = {0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F, 0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2}; +static const u8 keys620_e[] = {0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6, 0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3}; +static const u8 keys620_5[] = {0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30, 0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E}; +static const u8 keys620_5k[] = {0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04, 0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21}; +static const u8 keys620_5v[] = {0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E, 0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32}; +static const u8 keys630_k1[] = {0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, 0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B}; +static const u8 keys630_k2[] = {0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, 0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d}; +static const u8 keys630_k3[] = {0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA, 0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50}; +static const u8 keys630_k4[] = {0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD, 0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD}; +static const u8 keys630_k5[] = {0x87, 0x37, 0x21, 0xCC, 0x65, 0xAE, 0xAA, 0x5F, 0x40, 0xF6, 0x6F, 0x2A, 0x86, 0xC7, 0xA1, 0xC8}; +static const u8 keys630_k6[] = {0x8D, 0xDB, 0xDC, 0x5C, 0xF2, 0x70, 0x2B, 0x40, 0xB2, 0x3D, 0x00, 0x09, 0x61, 0x7C, 0x10, 0x60}; +static const u8 keys630_k7[] = {0x77, 0x1C, 0x06, 0x5F, 0x53, 0xEC, 0x3F, 0xFC, 0x22, 0xCE, 0x5A, 0x27, 0xFF, 0x78, 0xA8, 0x48}; +static const u8 keys630_k8[] = {0x81, 0xD1, 0x12, 0x89, 0x35, 0xC8, 0xEA, 0x8B, 0xE0, 0x02, 0x2D, 0x2D, 0x6A, 0x18, 0x67, 0xB8}; +static const u8 keys636_k1[] = {0x07, 0xE3, 0x08, 0x64, 0x7F, 0x60, 0xA3, 0x36, 0x6A, 0x76, 0x21, 0x44, 0xC9, 0xD7, 0x06, 0x83}; +static const u8 keys636_k2[] = {0x91, 0xF2, 0x02, 0x9E, 0x63, 0x32, 0x30, 0xA9, 0x1D, 0xDA, 0x0B, 0xA8, 0xB7, 0x41, 0xA3, 0xCC}; +static const u8 keys638_k4[] = {0x98, 0x43, 0xFF, 0x85, 0x68, 0xB2, 0xDB, 0x3B, 0xD4, 0x22, 0xD0, 0x4F, 0xAB, 0x5F, 0x0A, 0x31}; +static const u8 keys639_k3[] = {0x01, 0x7B, 0xF0, 0xE9, 0xBE, 0x9A, 0xDD, 0x54, 0x37, 0xEA, 0x0E, 0xC4, 0xD6, 0x4D, 0x8E, 0x9E}; +static const u8 keys660_k1[] = {0x76, 0xF2, 0x6C, 0x0A, 0xCA, 0x3A, 0xBA, 0x4E, 0xAC, 0x76, 0xD2, 0x40, 0xF5, 0xC3, 0xBF, 0xF9}; +static const u8 keys660_k2[] = {0x7A, 0x3E, 0x55, 0x75, 0xB9, 0x6A, 0xFC, 0x4F, 0x3E, 0xE3, 0xDF, 0xB3, 0x6C, 0xE8, 0x2A, 0x82}; +static const u8 keys660_k3[] = {0xFA, 0x79, 0x09, 0x36, 0xE6, 0x19, 0xE8, 0xA4, 0xA9, 0x41, 0x37, 0x18, 0x81, 0x02, 0xE9, 0xB3}; +static const u8 keys660_v1[] = {0xBA, 0x76, 0x61, 0x47, 0x8B, 0x55, 0xA8, 0x72, 0x89, 0x15, 0x79, 0x6D, 0xD7, 0x2F, 0x78, 0x0E}; +static const u8 keys660_v2[] = {0xF9, 0x4A, 0x6B, 0x96, 0x79, 0x3F, 0xEE, 0x0A, 0x04, 0xC8, 0x8D, 0x7E, 0x5F, 0x38, 0x3A, 0xCF}; +static const u8 keys660_v3[] = {0x88, 0xAF, 0x18, 0xE9, 0xC3, 0xAA, 0x6B, 0x56, 0xF7, 0xC5, 0xA8, 0xBF, 0x1A, 0x84, 0xE9, 0xF3}; +static const u8 keys660_v4[] = {0xD1, 0xB0, 0xAE, 0xC3, 0x24, 0x36, 0x13, 0x49, 0xD6, 0x49, 0xD7, 0x88, 0xEA, 0xA4, 0x99, 0x86}; +static const u8 keys660_v5[] = {0xCB, 0x93, 0x12, 0x38, 0x31, 0xC0, 0x2D, 0x2E, 0x7A, 0x18, 0x5C, 0xAC, 0x92, 0x93, 0xAB, 0x32}; +static const u8 keys660_v6[] = {0x92, 0x8C, 0xA4, 0x12, 0xD6, 0x5C, 0x55, 0x31, 0x5B, 0x94, 0x23, 0x9B, 0x62, 0xB3, 0xDB, 0x47}; +static const u8 keys660_k4[] = {0xC8, 0xA0, 0x70, 0x98, 0xAE, 0xE6, 0x2B, 0x80, 0xD7, 0x91, 0xE6, 0xCA, 0x4C, 0xA9, 0x78, 0x4E}; +static const u8 keys660_k5[] = {0xBF, 0xF8, 0x34, 0x02, 0x84, 0x47, 0xBD, 0x87, 0x1C, 0x52, 0x03, 0x23, 0x79, 0xBB, 0x59, 0x81}; +static const u8 keys660_k6[] = {0xD2, 0x83, 0xCC, 0x63, 0xBB, 0x10, 0x15, 0xE7, 0x7B, 0xC0, 0x6D, 0xEE, 0x34, 0x9E, 0x4A, 0xFA}; +static const u8 keys660_k7[] = {0xEB, 0xD9, 0x1E, 0x05, 0x3C, 0xAE, 0xAB, 0x62, 0xE3, 0xB7, 0x1F, 0x37, 0xE5, 0xCD, 0x68, 0xC3}; +static const u8 keys660_v7[] = {0xC5, 0x9C, 0x77, 0x9C, 0x41, 0x01, 0xE4, 0x85, 0x79, 0xC8, 0x71, 0x63, 0xA5, 0x7D, 0x4F, 0xFB}; +static const u8 keys660_v8[] = {0x86, 0xA0, 0x7D, 0x4D, 0xB3, 0x6B, 0xA2, 0xFD, 0xF4, 0x15, 0x85, 0x70, 0x2D, 0x6A, 0x0D, 0x3A}; +static const u8 keys660_k8[] = {0x85, 0x93, 0x1F, 0xED, 0x2C, 0x4D, 0xA4, 0x53, 0x59, 0x9C, 0x3F, 0x16, 0xF3, 0x50, 0xDE, 0x46}; +static const u8 key_21C0[] = {0x6A, 0x19, 0x71, 0xF3, 0x18, 0xDE, 0xD3, 0xA2, 0x6D, 0x3B, 0xDE, 0xC7, 0xBE, 0x98, 0xE2, 0x4C}; +static const u8 key_2250[] = {0x50, 0xCC, 0x03, 0xAC, 0x3F, 0x53, 0x1A, 0xFA, 0x0A, 0xA4, 0x34, 0x23, 0x86, 0x61, 0x7F, 0x97}; +static const u8 key_22E0[] = {0x66, 0x0F, 0xCB, 0x3B, 0x30, 0x75, 0xE3, 0x10, 0x0A, 0x95, 0x65, 0xC7, 0x3C, 0x93, 0x87, 0x22}; +static const u8 key_2D80[] = {0x40, 0x02, 0xC0, 0xBF, 0x20, 0x02, 0xC0, 0xBF, 0x5C, 0x68, 0x2B, 0x95, 0x5F, 0x40, 0x7B, 0xB8}; +static const u8 key_2D90[] = {0x55, 0x19, 0x35, 0x10, 0x48, 0xD8, 0x2E, 0x46, 0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F}; +static const u8 key_2DA8[] = {0x80, 0x02, 0xC0, 0xBF, 0x00, 0x0A, 0xC0, 0xBF, 0x40, 0x03, 0xC0, 0xBF, 0x40, 0x00, 0x00, 0x00}; +static const u8 key_2DB8[] = {0x4C, 0x2D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u8 key_D91605F0[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31}; +static const u8 key_D91606F0[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7}; +static const u8 key_D91608F0[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF}; +static const u8 key_D91609F0[] = {0xD0, 0x36, 0x12, 0x75, 0x80, 0x56, 0x20, 0x43, 0xC4, 0x30, 0x94, 0x3E, 0x1C, 0x75, 0xD1, 0xBF}; +static const u8 key_D9160AF0[] = {0x10, 0xA9, 0xAC, 0x16, 0xAE, 0x19, 0xC0, 0x7E, 0x3B, 0x60, 0x77, 0x86, 0x01, 0x6F, 0xF2, 0x63}; +static const u8 key_D9160BF0[] = {0x83, 0x83, 0xF1, 0x37, 0x53, 0xD0, 0xBE, 0xFC, 0x8D, 0xA7, 0x32, 0x52, 0x46, 0x0A, 0xC2, 0xC2}; +static const u8 key_D91611F0[] = {0x61, 0xB0, 0xC0, 0x58, 0x71, 0x57, 0xD9, 0xFA, 0x74, 0x67, 0x0E, 0x5C, 0x7E, 0x6E, 0x95, 0xB9}; +static const u8 key_D91612F0[] = {0x9E, 0x20, 0xE1, 0xCD, 0xD7, 0x88, 0xDE, 0xC0, 0x31, 0x9B, 0x10, 0xAF, 0xC5, 0xB8, 0x73, 0x23}; +static const u8 key_D91613F0[] = {0xEB, 0xFF, 0x40, 0xD8, 0xB4, 0x1A, 0xE1, 0x66, 0x91, 0x3B, 0x8F, 0x64, 0xB6, 0xFC, 0xB7, 0x12}; +static const u8 key_D91614F0[] = {0xFD, 0xF7, 0xB7, 0x3C, 0x9F, 0xD1, 0x33, 0x95, 0x11, 0xB8, 0xB5, 0xBB, 0x54, 0x23, 0x73, 0x85}; +static const u8 key_D91615F0[] = {0xC8, 0x03, 0xE3, 0x44, 0x50, 0xF1, 0xE7, 0x2A, 0x6A, 0x0D, 0xC3, 0x61, 0xB6, 0x8E, 0x5F, 0x51}; +static const u8 key_D91616F0[] = {0x53, 0x03, 0xB8, 0x6A, 0x10, 0x19, 0x98, 0x49, 0x1C, 0xAF, 0x30, 0xE4, 0x25, 0x1B, 0x6B, 0x28}; +static const u8 key_D91617F0[] = {0x02, 0xFA, 0x48, 0x73, 0x75, 0xAF, 0xAE, 0x0A, 0x67, 0x89, 0x2B, 0x95, 0x4B, 0x09, 0x87, 0xA3}; +static const u8 key_D91618F0[] = {0x96, 0x96, 0x7C, 0xC3, 0xF7, 0x12, 0xDA, 0x62, 0x1B, 0xF6, 0x9A, 0x9A, 0x44, 0x44, 0xBC, 0x48}; +static const u8 key_D91619F0[] = {0xE0, 0x32, 0xA7, 0x08, 0x6B, 0x2B, 0x29, 0x2C, 0xD1, 0x4D, 0x5B, 0xEE, 0xA8, 0xC8, 0xB4, 0xE9}; +static const u8 key_D9161AF0[] = {0x27, 0xE5, 0xA7, 0x49, 0x52, 0xE1, 0x94, 0x67, 0x35, 0x66, 0x91, 0x0C, 0xE8, 0x9A, 0x25, 0x24}; +static const u8 key_D91620F0[] = {0x52, 0x1C, 0xB4, 0x5F, 0x40, 0x3B, 0x9A, 0xDD, 0xAC, 0xFC, 0xEA, 0x92, 0xFD, 0xDD, 0xF5, 0x90}; +static const u8 key_D91621F0[] = {0xD1, 0x91, 0x2E, 0xA6, 0x21, 0x14, 0x29, 0x62, 0xF6, 0xED, 0xAE, 0xCB, 0xDD, 0xA3, 0xBA, 0xFE}; +static const u8 key_D91622F0[] = {0x59, 0x5D, 0x78, 0x4D, 0x21, 0xB2, 0x01, 0x17, 0x6C, 0x9A, 0xB5, 0x1B, 0xDA, 0xB7, 0xF9, 0xE6}; +static const u8 key_D91623F0[] = {0xAA, 0x45, 0xEB, 0x4F, 0x62, 0xFB, 0xD1, 0x0D, 0x71, 0xD5, 0x62, 0xD2, 0xF5, 0xBF, 0xA5, 0x2F}; +static const u8 key_D91624F0[] = {0x61, 0xB7, 0x26, 0xAF, 0x8B, 0xF1, 0x41, 0x58, 0x83, 0x6A, 0xC4, 0x92, 0x12, 0xCB, 0xB1, 0xE9}; +static const u8 key_D91628F0[] = {0x49, 0xA4, 0xFC, 0x66, 0xDC, 0xE7, 0x62, 0x21, 0xDB, 0x18, 0xA7, 0x50, 0xD6, 0xA8, 0xC1, 0xB6}; +static const u8 key_D91680F0[] = {0x2C, 0x22, 0x9B, 0x12, 0x36, 0x74, 0x11, 0x67, 0x49, 0xD1, 0xD1, 0x88, 0x92, 0xF6, 0xA1, 0xD8}; +static const u8 key_D91681F0[] = {0x52, 0xB6, 0x36, 0x6C, 0x8C, 0x46, 0x7F, 0x7A, 0xCC, 0x11, 0x62, 0x99, 0xC1, 0x99, 0xBE, 0x98}; +static const u8 key_2E5E10F0[] = {0x9D, 0x5C, 0x5B, 0xAF, 0x8C, 0xD8, 0x69, 0x7E, 0x51, 0x9F, 0x70, 0x96, 0xE6, 0xD5, 0xC4, 0xE8}; +static const u8 key_2E5E12F0[] = {0x8A, 0x7B, 0xC9, 0xD6, 0x52, 0x58, 0x88, 0xEA, 0x51, 0x83, 0x60, 0xCA, 0x16, 0x79, 0xE2, 0x07}; +static const u8 key_2E5E13F0[] = {0xFF, 0xA4, 0x68, 0xC3, 0x31, 0xCA, 0xB7, 0x4C, 0xF1, 0x23, 0xFF, 0x01, 0x65, 0x3D, 0x26, 0x36}; +static const u8 key_2FD30BF0[] = {0xD8, 0x58, 0x79, 0xF9, 0xA4, 0x22, 0xAF, 0x86, 0x90, 0xAC, 0xDA, 0x45, 0xCE, 0x60, 0x40, 0x3F}; +static const u8 key_2FD311F0[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44}; +static const u8 key_2FD312F0[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE}; +static const u8 keys02G_E[] = {0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, 0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E}; +static const u8 keys03G_E[] = {0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, 0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA}; +static const u8 keys05G_E[] = {0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C, 0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54}; +static const u8 oneseg_310[] = {0xC7, 0x27, 0x72, 0x85, 0xAB, 0xA7, 0xF7, 0xF0, 0x4C, 0xC1, 0x86, 0xCC, 0xE3, 0x7F, 0x17, 0xCA}; +static const u8 oneseg_300[] = {0x76, 0x40, 0x9E, 0x08, 0xDB, 0x9B, 0x3B, 0xA1, 0x47, 0x8A, 0x96, 0x8E, 0xF3, 0xF7, 0x62, 0x92}; +static const u8 oneseg_280[] = {0x23, 0xDC, 0x3B, 0xB5, 0xA9, 0x82, 0xD6, 0xEA, 0x63, 0xA3, 0x6E, 0x2B, 0x2B, 0xE9, 0xE1, 0x54}; +static const u8 oneseg_260_271[] = {0x22, 0x43, 0x57, 0x68, 0x2F, 0x41, 0xCE, 0x65, 0x4C, 0xA3, 0x7C, 0xC6, 0xC4, 0xAC, 0xF3, 0x60}; +static const u8 oneseg_slim[] = {0x12, 0x57, 0x0D, 0x8A, 0x16, 0x6D, 0x87, 0x06, 0x03, 0x7D, 0xC8, 0x8B, 0x62, 0xA3, 0x32, 0xA9}; +static const u8 ms_app_main[] = {0x1E, 0x2E, 0x38, 0x49, 0xDA, 0xD4, 0x16, 0x08, 0x27, 0x2E, 0xF3, 0xBC, 0x37, 0x75, 0x80, 0x93}; +static const u8 demokeys_280[] = {0x12, 0x99, 0x70, 0x5E, 0x24, 0x07, 0x6C, 0xD0, 0x2D, 0x06, 0xFE, 0x7E, 0xB3, 0x0C, 0x11, 0x26}; +static const u8 demokeys_3XX_1[] = {0x47, 0x05, 0xD5, 0xE3, 0x56, 0x1E, 0x81, 0x9B, 0x09, 0x2F, 0x06, 0xDB, 0x6B, 0x12, 0x92, 0xE0}; +static const u8 demokeys_3XX_2[] = {0xF6, 0x62, 0x39, 0x6E, 0x26, 0x22, 0x4D, 0xCA, 0x02, 0x64, 0x16, 0x99, 0x7B, 0x9A, 0xE7, 0xB8}; +static const u8 ebootbin_271_new[] = {0xF4, 0xAE, 0xF4, 0xE1, 0x86, 0xDD, 0xD2, 0x9C, 0x7C, 0xC5, 0x42, 0xA6, 0x95, 0xA0, 0x83, 0x88}; +static const u8 ebootbin_280_new[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31}; +static const u8 ebootbin_300_new[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7}; +static const u8 ebootbin_310_new[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF}; +static const u8 gameshare_260_271[] = {0xF9, 0x48, 0x38, 0x0C, 0x96, 0x88, 0xA7, 0x74, 0x4F, 0x65, 0xA0, 0x54, 0xC2, 0x76, 0xD9, 0xB8}; +static const u8 gameshare_280[] = {0x2D, 0x86, 0x77, 0x3A, 0x56, 0xA4, 0x4F, 0xDD, 0x3C, 0x16, 0x71, 0x93, 0xAA, 0x8E, 0x11, 0x43}; +static const u8 gameshare_300[] = {0x78, 0x1A, 0xD2, 0x87, 0x24, 0xBD, 0xA2, 0x96, 0x18, 0x3F, 0x89, 0x36, 0x72, 0x90, 0x92, 0x85}; +static const u8 gameshare_310[] = {0xC9, 0x7D, 0x3E, 0x0A, 0x54, 0x81, 0x6E, 0xC7, 0x13, 0x74, 0x99, 0x74, 0x62, 0x18, 0xE7, 0xDD}; +static const u8 key_380210F0[] = {0x32, 0x2C, 0xFA, 0x75, 0xE4, 0x7E, 0x93, 0xEB, 0x9F, 0x22, 0x80, 0x85, 0x57, 0x08, 0x98, 0x48}; +static const u8 key_380280F0[] = {0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, 0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C}; +static const u8 key_380283F0[] = {0x34, 0x20, 0x0C, 0x8E, 0xA1, 0x86, 0x79, 0x84, 0xAF, 0x13, 0xAE, 0x34, 0x77, 0x6F, 0xEA, 0x89}; +static const u8 key_407810F0[] = {0xAF, 0xAD, 0xCA, 0xF1, 0x95, 0x59, 0x91, 0xEC, 0x1B, 0x27, 0xD0, 0x4E, 0x8A, 0xF3, 0x3D, 0xE7}; +static const u8 drmkeys_6XX_1[] = {0x36, 0xEF, 0x82, 0x4E, 0x74, 0xFB, 0x17, 0x5B, 0x14, 0x14, 0x05, 0xF3, 0xB3, 0x8A, 0x76, 0x18}; +static const u8 drmkeys_6XX_2[] = {0x21, 0x52, 0x5D, 0x76, 0xF6, 0x81, 0x0F, 0x15, 0x2F, 0x4A, 0x40, 0x89, 0x63, 0xA0, 0x10, 0x55}; // PRXDecrypter 144-byte tag keys. -u32 g_key0[] = { +static const u32 g_key0[] = { 0x7b21f3be, 0x299c5e1d, 0x1c9c5e71, 0x96cb4645, 0x3c9b1be0, 0xeb85de3d, 0x4a7f2022, 0xc2206eaa, 0xd50b3265, 0x55770567, 0x3c080840, 0x981d55f2, 0x5fd8f6f3, 0xee8eb0c5, 0x944d8152, 0xf8278651, 0x2705bafa, 0x8420e533, 0x27154ae9, 0x4819aa32, 0x59a3aa40, 0x2cb3cf65, 0xf274466d, 0x3a655605, 0x21b0f88f, 0xc5b18d26, 0x64c19051, 0xd669c94e, 0xe87035f2, 0x9d3a5909, 0x6f4e7102, 0xdca946ce, 0x8416881b, 0xbab097a5, 0x249125c6, 0xb34c0872}; -u32 g_key2[] = { +static const u32 g_key2[] = { 0xccfda932, 0x51c06f76, 0x046dcccf, 0x49e1821e, 0x7d3b024c, 0x9dda5865, 0xcc8c9825, 0xd1e97db5, 0x6874d8cb, 0x3471c987, 0x72edb3fc, 0x81c8365d, 0xe161e33a, 0xfc92db59, 0x2009b1ec, 0xb1a94ce4, 0x2f03696b, 0x87e236d8, 0x3b2b8ce9, 0x0305e784, 0xf9710883, 0xb039db39, 0x893bea37, 0xe74d6805, 0x2a5c38bd, 0xb08dc813, 0x15b32375, 0x46be4525, 0x0103fd90, 0xa90e87a2, 0x52aba66a, 0x85bf7b80, 0x45e8ce63, 0x4dd716d3, 0xf5e30d2d, 0xaf3ae456}; -u32 g_key3[] = { +static const u32 g_key3[] = { 0xa6c8f5ca, 0x6d67c080, 0x924f4d3a, 0x047ca06a, 0x08640297, 0x4fd4a758, 0xbd685a87, 0x9b2701c2, 0x83b62a35, 0x726b533c, 0xe522fa0c, 0xc24b06b4, 0x459d1cac, 0xa8c5417b, 0x4fea62a2, 0x0615d742, 0x30628d09, 0xc44fab14, 0x69ff715e, 0xd2d8837d, 0xbeed0b8b, 0x1e6e57ae, 0x61e8c402, 0xbe367a06, 0x543f2b5e, 0xdb3ec058, 0xbe852075, 0x1e7e4dcc, 0x1564ea55, 0xec7825b4, 0xc0538cad, 0x70f72c7f, 0x49e8c3d0, 0xeda97ec5, 0xf492b0a4, 0xe05eb02a}; -u32 g_key44[] = { +static const u32 g_key44[] = { 0xef80e005, 0x3a54689f, 0x43c99ccd, 0x1b7727be, 0x5cb80038, 0xdd2efe62, 0xf369f92c, 0x160f94c5, 0x29560019, 0xbf3c10c5, 0xf2ce5566, 0xcea2c626, 0xb601816f, 0x64e7481e, 0x0c34debd, 0x98f29cb0, 0x3fc504d7, 0xc8fb39f0, 0x0221b3d8, 0x63f936a2, 0x9a3a4800, 0x6ecc32e3, 0x8e120cfd, 0xb0361623, 0xaee1e689, 0x745502eb, 0xe4a6c61c, 0x74f23eb4, 0xd7fa5813, 0xb01916eb, 0x12328457, 0xd2bc97d2, 0x646425d8, 0x328380a5, 0x43da8ab1, 0x4b122ac9}; -u32 g_key20[] = { +static const u32 g_key20[] = { 0x33b50800, 0xf32f5fcd, 0x3c14881f, 0x6e8a2a95, 0x29feefd5, 0x1394eae3, 0xbd6bd443, 0x0821c083, 0xfab379d3, 0xe613e165, 0xf5a754d3, 0x108b2952, 0x0a4b1e15, 0x61eadeba, 0x557565df, 0x3b465301, 0xae54ecc3, 0x61423309, 0x70c9ff19, 0x5b0ae5ec, 0x989df126, 0x9d987a5f, 0x55bc750e, 0xc66eba27, 0x2de988e8, 0xf76600da, 0x0382dccb, 0x5569f5f2, 0x8e431262, 0x288fe3d3, 0x656f2187, 0x37d12e9c, 0x2f539eb4, 0xa492998e, 0xed3958f7, 0x39e96523}; -u32 g_key3A[] = { +static const u32 g_key3A[] = { 0x67877069, 0x3abd5617, 0xc23ab1dc, 0xab57507d, 0x066a7f40, 0x24def9b9, 0x06f759e4, 0xdcf524b1, 0x13793e5e, 0x0359022d, 0xaae7e1a2, 0x76b9b2fa, 0x9a160340, 0x87822fba, 0x19e28fbb, 0x9e338a02, 0xd8007e9a, 0xea317af1, 0x630671de, 0x0b67ca7c, 0x865192af, 0xea3c3526, 0x2b448c8e, 0x8b599254, 0x4602e9cb, 0x4de16cda, 0xe164d5bb, 0x07ecd88e, 0x99ffe5f8, 0x768800c1, 0x53b091ed, 0x84047434, 0xb426dbbc, 0x36f948bb, 0x46142158, 0x749bb492}; -u32 g_keyEBOOT1xx[] = { +static const u32 g_keyEBOOT1xx[] = { 0x18CB69EF, 0x158E8912, 0xDEF90EBB, 0x4CB0FB23, 0x3687EE18, 0x868D4A6E, 0x19B5C756, 0xEE16551D, 0xE7CB2D6C, 0x9747C660, 0xCE95143F, 0x2956F477, 0x03824ADE, 0x210C9DF1, 0x5029EB24, 0x81DFE69F, 0x39C89B00, 0xB00C8B91, 0xEF2DF9C2, 0xE13A93FC, 0x8B94A4A8, 0x491DD09D, 0x686A400D, 0xCED4C7E4, 0x96C8B7C9, 0x1EAADC28, 0xA4170B84, 0x505D5DDC, 0x5DA6C3CF, 0x0E5DFA2D, 0x6E7919B5, 0xCE5E29C7, 0xAAACDB94, 0x45F70CDD, 0x62A73725, 0xCCE6563D}; -u32 g_keyEBOOT2xx[] = { +static const u32 g_keyEBOOT2xx[] = { 0xDA8E36FA, 0x5DD97447, 0x76C19874, 0x97E57EAF, 0x1CAB09BD, 0x9835BAC6, 0x03D39281, 0x03B205CF, 0x2882E734, 0xE714F663, 0xB96E2775, 0xBD8AAFC7, 0x1DD3EC29, 0xECA4A16C, 0x5F69EC87, 0x85981E92, 0x7CFCAE21, 0xBAE9DD16, 0xE6A97804, 0x2EEE02FC, 0x61DF8A3D, 0xDD310564, 0x9697E149, 0xC2453F3B, 0xF91D8456, 0x39DA6BC8, 0xB3E5FEF5, 0x89C593A3, 0xFB5C8ABC, 0x6C0B7212, 0xE10DD3CB, 0x98D0B2A8, 0x5FD61847, 0xF0DC2357, 0x7701166A, 0x0F5C3B68}; -u32 g_keyUPDATER[] = { +static const u32 g_keyUPDATER[] = { 0xA5603CBF, 0xD7482441, 0xF65764CC, 0x1F90060B, 0x4EA73E45, 0xE551D192, 0xE7B75D8A, 0x465A506E, 0x40FB1022, 0x2C273350, 0x8096DA44, 0x9947198E, 0x278DEE77, 0x745D062E, 0xC148FA45, 0x832582AF, 0x5FDB86DA, 0xCB15C4CE, 0x2524C62F, 0x6C2EC3B1, 0x369BE39E, 0xF7EB1FC4, 0x1E51CE1A, 0xD70536F4, 0xC34D39D8, 0x7418FB13, 0xE3C84DE1, 0xB118F03C, 0xA2018D4E, 0xE6D8770D, 0x5720F390, 0x17F96341, 0x60A4A68F, 0x1327DD28, 0x05944C64, 0x0C2C4C12}; -u32 g_keyMEIMG250[] = { +static const u32 g_keyMEIMG250[] = { 0xA381FEBC, 0x99B9D5C9, 0x6C560A8D, 0x30309F95, 0x792646CC, 0x82B64E5E, 0x1A3951AD, 0x0A182EC4, 0xC46131B4, 0x77C50C8A, 0x325F16C6, 0x02D1942E, 0x0AA38AC4, 0x2A940AC6, 0x67034726, 0xE52DB133, 0xD2EF2107, 0x85C81E90, 0xC8D164BA, 0xC38DCE1D, 0x948BA275, 0x0DB84603, 0xE2473637, 0xCD74FCDA, 0x588E3D66, 0x6D28E822, 0x891E548B, 0xF53CF56D, 0x0BBDDB66, 0xC4B286AA, 0x2BEBBC4B, 0xFC261FF4, 0x92B8E705, 0xDCEE6952, 0x5E0442E5, 0x8BEB7F21}; -u32 g_keyMEIMG260[] = { +static const u32 g_keyMEIMG260[] = { 0x11BFD698, 0xD7F9B324, 0xDD524927, 0x16215B86, 0x504AC36D, 0x5843B217, 0xE5A0DA47, 0xBB73A1E7, 0x2915DB35, 0x375CFD3A, 0xBB70A905, 0x272BEFCA, 0x2E960791, 0xEA0799BB, 0xB85AE6C8, 0xC9CAF773, 0x250EE641, 0x06E74A9E, 0x5244895D, 0x466755A5, 0x9A84AF53, 0xE1024174, 0xEEBA031E, 0xED80B9CE, 0xBC315F72, 0x5821067F, 0xE8313058, 0xD2D0E706, 0xE6D8933E, 0xD7D17FB4, 0x505096C4, 0xFDA50B3B, 0x4635AE3D, 0xEB489C8A, 0x422D762D, 0x5A8B3231}; -u32 g_keyDEMOS27X[] = { +static const u32 g_keyDEMOS27X[] = { 0x1ABF102F, 0xD596D071, 0x6FC552B2, 0xD4F2531F, 0xF025CDD9, 0xAF9AAF03, 0xE0CF57CF, 0x255494C4, 0x7003675E, 0x907BC884, 0x002D4EE4, 0x0B687A0D, 0x9E3AA44F, 0xF58FDA81, 0xEC26AC8C, 0x3AC9B49D, 0x3471C037, 0xB0F3834D, 0x10DC4411, 0xA232EA31, 0xE2E5FA6B, 0x45594B03, 0xE43A1C87, 0x31DAD9D1, 0x08CD7003, 0xFA9C2FDF, 0x5A891D25, 0x9B5C1934, 0x22F366E5, 0x5F084A32, 0x695516D5, 0x2245BE9F, 0x4F6DD705, 0xC4B8B8A1, 0xBC13A600, 0x77B7FC3B}; -u32 g_keyUNK1[] = { +static const u32 g_keyUNK1[] = { 0x33B50800, 0xF32F5FCD, 0x3C14881F, 0x6E8A2A95, 0x29FEEFD5, 0x1394EAE3, 0xBD6BD443, 0x0821C083, 0xFAB379D3, 0xE613E165, 0xF5A754D3, 0x108B2952, 0x0A4B1E15, 0x61EADEBA, 0x557565DF, 0x3B465301, 0xAE54ECC3, 0x61423309, 0x70C9FF19, 0x5B0AE5EC, 0x989DF126, 0x9D987A5F, 0x55BC750E, 0xC66EBA27, 0x2DE988E8, 0xF76600DA, 0x0382DCCB, 0x5569F5F2, 0x8E431262, 0x288FE3D3, 0x656F2187, 0x37D12E9C, 0x2F539EB4, 0xA492998E, 0xED3958F7, 0x39E96523}; -u32 g_key_GAMESHARE1xx[] = { +static const u32 g_key_GAMESHARE1xx[] = { 0x721B53E8, 0xFC3E31C6, 0xF85BA2A2, 0x3CF0AC72, 0x54EEA7AB, 0x5959BFCB, 0x54B8836B, 0xBC431313, 0x989EF2CF, 0xF0CE36B2, 0x98BA4CF8, 0xE971C931, 0xA0375DC8, 0x08E52FA0, 0xAC0DD426, 0x57E4D601, 0xC56E61C7, 0xEF1AB98A, 0xD1D9F8F4, 0x5FE9A708, 0x3EF09D07, 0xFA0C1A8C, 0xA91EEA5C, 0x58F482C5, 0x2C800302, 0x7EE6F6C3, 0xFF6ABBBB, 0x2110D0D0, 0xD3297A88, 0x980012D3, 0xDC59C87B, 0x7FDC5792, 0xDB3F5DA6, 0xFC23B787, 0x22698ED3, 0xB680E812}; -u32 g_key_GAMESHARE2xx[] = { +static const u32 g_key_GAMESHARE2xx[] = { 0x94A757C7, 0x9FD39833, 0xF8508371, 0x328B0B29, 0x2CBCB9DA, 0x2918B9C6, 0x944C50BA, 0xF1DCE7D0, 0x640C3966, 0xC90B3D08, 0xF4AD17BA, 0x6CA0F84B, 0xF7767C67, 0xA4D3A55A, 0x4A085C6A, 0x6BB27071, 0xFA8B38FB, 0x3FDB31B8, 0x8B7196F2, 0xDB9BED4A, 0x51625B84, 0x4C1481B4, 0xF684F508, 0x30B44770, 0x93AA8E74, 0x90C579BC, 0x246EC88D, 0x2E051202, 0xC774842E, 0xA185D997, 0x7A2B3ADD, 0xFE835B6D, 0x508F184D, 0xEB4C4F13, 0x0E1993D3, 0xBA96DFD2}; -u32 g_key_INDEXDAT1xx[] = { +static const u32 g_key_INDEXDAT1xx[] = { 0x76CB00AF, 0x111CE62F, 0xB7B27E36, 0x6D8DE8F9, 0xD54BF16A, 0xD9E90373, 0x7599D982, 0x51F82B0E, 0x636103AD, 0x8E40BC35, 0x2F332C94, 0xF513AAE9, 0xD22AFEE9, 0x04343987, 0xFC5BB80C, 0x12349D89, 0x14A481BB, 0x25ED3AE8, @@ -259,13 +259,13 @@ u32 g_key_INDEXDAT1xx[] = { 0xA34D8C80, 0x962B235D, 0x3E420548, 0x09CF9FFE, 0xD4883F5C, 0xD90E9CB5, 0x00AEF4E9, 0xF0886DE9, 0x62A58A5B, 0x52A55546, 0x971941B5, 0xF5B79FAC}; -typedef struct +struct TAG_INFO { u32 tag; // 4 byte value at offset 0xD0 in the PRX file - u32* key; // "step1_result" use for XOR step + const u32 *key; // "step1_result" use for XOR step u8 code; u8 codeExtra; -} TAG_INFO; +}; static const TAG_INFO g_tagInfo[] = { @@ -287,7 +287,7 @@ static const TAG_INFO g_tagInfo[] = { 0xBB67C59F, g_key_GAMESHARE2xx, 0x5E, 0x5E } }; -static TAG_INFO const* GetTagInfo(u32 tagFind) +static const TAG_INFO *GetTagInfo(u32 tagFind) { for (u32 iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++) if (g_tagInfo[iTag].tag == tagFind) @@ -336,7 +336,7 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) int i, retsize; u8 bD0[0x80], b80[0x50], b00[0x80], bB0[0x20]; - TAG_INFO const* pti = GetTagInfo(tag); + const TAG_INFO *pti = GetTagInfo(tag); if (pti == NULL) { return -1; @@ -350,9 +350,15 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) break; } + // Scramble the key (!) + // + // NOTE: I can't make much sense out of this code. Scramble seems really odd, appears + // to write to stuff that should be before the actual key. + u8 key[0x90]; + memcpy(key, pti->key, 0x90); if (i == 0x14) { - Scramble(pti->key, 0x90, pti->code); + Scramble((u32 *)key, 0x90, pti->code); } // build conversion into pbOut @@ -387,7 +393,7 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) int ret; int iXOR; for (iXOR = 0; iXOR < 0x70; iXOR++) - pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ ((u8*)pti->key)[0x14+iXOR]; + pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ key[0x14+iXOR]; ret = sceUtilsBufferCopyWithRange(pbOut+0x2C, 20+0x70, pbOut+0x2C, 20+0x70, 7); if (ret != 0) @@ -396,7 +402,7 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) } for (iXOR = 0x6F; iXOR >= 0; iXOR--) - pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ ((u8*)pti->key)[0x20+iXOR]; + pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ key[0x20+iXOR]; memset(pbOut+0x80, 0, 0x30); // $40 bytes kept, clean up pbOut[0xA0] = 1; @@ -418,13 +424,13 @@ static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag) ////////// Decryption 2 ////////// -typedef struct +struct TAG_INFO2 { u32 tag; // 4 byte value at offset 0xD0 in the PRX file - u8 *key; // 16 bytes keys + const u8 *key; // 16 bytes keys u8 code; // code for scramble u8 type; -} TAG_INFO2; +}; static TAG_INFO2 g_tagInfo2[] = { @@ -575,11 +581,6 @@ static TAG_INFO2 *GetTagInfo2(u32 tagFind) return NULL; // not found } -// Moving these out here is a really ugly hack to avoid a stack corruption warning, warranted or not -//static u8 padding1[0x100]; -//static u8 tmp1[0x150], tmp2[0x90+0x14], tmp3[0x60+0x14], tmp4[0x20]; -//static u8 padding2[0x100]; - static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) { TAG_INFO2 * pti = GetTagInfo2(tag); @@ -620,10 +621,8 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) for (j = 0; j < 0x10; j++) { p[(i << 4) + j] = pti->key[j]; - } - - p[(i << 4)] = i; + p[(i << 4)] = i; // really? } if (Scramble((u32 *)tmp2, 0x90, pti->code) < 0) @@ -674,9 +673,7 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) return -8; } - int iXOR; - - for (iXOR = 0; iXOR < 0x40; iXOR++) + for (int iXOR = 0; iXOR < 0x40; iXOR++) { tmp3[iXOR+0x14] = outbuf[iXOR+0x80] ^ tmp2[iXOR+0x10]; } @@ -686,7 +683,7 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) return -9; } - for (iXOR = 0x3F; iXOR >= 0; iXOR--) + for (int iXOR = 0x3F; iXOR >= 0; iXOR--) { outbuf[iXOR+0x40] = tmp3[iXOR] ^ tmp2[iXOR+0x50]; // uns 8 } @@ -709,7 +706,7 @@ static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag) memcpy(outbuf+0xD0, outbuf+0xD0, 0x80); // The real decryption - if (sceUtilsBufferCopyWithRange(outbuf, size, outbuf+0x40, size-0x40, 0x1) != 0) + if (sceUtilsBufferCopyWithRange(outbuf, size, outbuf + 0x40, size - 0x40, 0x1) != 0) { return -1; } From d56bc40db45f9c191c9947fae778b41cab079bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 08:34:19 +0100 Subject: [PATCH 170/276] NativeApp: Load config before processing flags (duh) --- Core/Config.h | 17 ++++++++++++----- android/jni/NativeApp.cpp | 11 +++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Core/Config.h b/Core/Config.h index e70ca017d2..ae9ea5191a 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -32,30 +32,37 @@ public: CConfig(); ~CConfig(); - // Many of these are currently broken. - bool bEnableSound; - bool bAutoLoadLast; + // Whether to save the config on close. bool bSaveSettings; + + // These are broken + bool bAutoLoadLast; bool bFirstRun; bool bAutoRun; bool bSpeedLimit; bool bConfirmOnQuit; + + // Core bool bIgnoreBadMemAccess; bool bFastMemory; + int iCpuCore; // GFX bool bDisplayFramebuffer; bool bHardwareTransform; bool bBufferedRendering; bool bDrawWireframe; + int iWindowZoom; // for Windows + // Sound + bool bEnableSound; + + // UI bool bShowTouchControls; bool bShowDebuggerOnLoad; bool bShowAnalogStick; bool bShowFPSCounter; bool bShowDebugStats; - int iWindowZoom; // for Windows - int iCpuCore; std::string currentDirectory; std::string memCardDirectory; diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 251a98a534..1ed98fba39 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -169,6 +169,10 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co LogManager *logman = LogManager::GetInstance(); ILOG("Logman: %p", logman); + config_filename = user_data_path + "ppsspp.ini"; + + g_Config.Load(config_filename.c_str()); + bool gfxLog = false; // Parse command line LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO; @@ -184,12 +188,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co break; case 'j': g_Config.iCpuCore = CPU_JIT; + g_Config.bSaveSettings = false; break; case 'f': g_Config.iCpuCore = CPU_FASTINTERPRETER; + g_Config.bSaveSettings = false; break; case 'i': g_Config.iCpuCore = CPU_INTERPRETER; + g_Config.bSaveSettings = false; break; } } else { @@ -207,10 +214,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co } } - config_filename = user_data_path + "ppsspp.ini"; - - g_Config.Load(config_filename.c_str()); - if (g_Config.currentDirectory == "") { #if defined(ANDROID) || defined(BLACKBERRY) || defined(__SYMBIAN32__) g_Config.currentDirectory = external_directory; From d8da92befaac4142c59cccb6061a9891b55a51db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 09:01:17 +0100 Subject: [PATCH 171/276] Fix timing issue wiith JIT on non-Windows platforms --- Core/Core.h | 3 ++- Core/CoreTiming.cpp | 6 +++--- Core/MIPS/x86/Asm.cpp | 12 +++++++++--- Core/MIPS/x86/Asm.h | 1 + Core/MIPS/x86/Jit.cpp | 3 ++- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Core/Core.h b/Core/Core.h index 66a0a19be0..d9b07c7f6a 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -33,9 +33,10 @@ void Core_Halt(const char *msg); bool Core_IsStepping(); +// RUNNING must be at 0. enum CoreState { - CORE_RUNNING, + CORE_RUNNING = 0, CORE_STEPPING, CORE_POWERDOWN, CORE_ERROR, diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 74eb4f4c91..b5d40610dd 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -421,7 +421,7 @@ void ProcessFifoWaitEvents() { break; } - } + } } void MoveEvents() @@ -438,7 +438,7 @@ void MoveEvents() // Move free events to threadsafe pool while(allocatedTsEvents > 0 && eventPool) - { + { Event *ev = eventPool; eventPool = ev->next; ev->next = eventTsPool; @@ -455,7 +455,7 @@ void Advance() ProcessFifoWaitEvents(); - if (!first) + if (!first) { // WARN_LOG(CPU, "WARNING - no events in queue. Setting downcount to 10000"); downcount += 10000; diff --git a/Core/MIPS/x86/Asm.cpp b/Core/MIPS/x86/Asm.cpp index 8aca44f08e..67a6611e64 100644 --- a/Core/MIPS/x86/Asm.cpp +++ b/Core/MIPS/x86/Asm.cpp @@ -78,7 +78,12 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit) outerLoop = GetCodePtr(); ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time - + + dispatcherCheckCoreState = GetCodePtr(); + + CMP(32, M((void*)&coreState), Imm32(0)); + FixupBranch badCoreState = J_CC(CC_NZ, true); + dispatcher = GetCodePtr(); // The result of slice decrementation should be in flags if somebody jumped here // IMPORTANT - We jump on negative, not carry!!! @@ -144,10 +149,11 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit) JMP(dispatcherNoCheck); // Let's just dispatch again, we'll enter the block since we know it's there. SetJumpTarget(bail); - - CMP(32, M((void*)&coreState), Imm8(0)); + + CMP(32, M((void*)&coreState), Imm32(0)); J_CC(CC_Z, outerLoop, true); + SetJumpTarget(badCoreState); //Landing pad for drec space ABI_PopAllCalleeSavedRegsAndAdjustStack(); RET(); diff --git a/Core/MIPS/x86/Asm.h b/Core/MIPS/x86/Asm.h index 22b93e174e..226332c676 100644 --- a/Core/MIPS/x86/Asm.h +++ b/Core/MIPS/x86/Asm.h @@ -65,6 +65,7 @@ public: const u8 *outerLoop; const u8 *dispatcher; + const u8 *dispatcherCheckCoreState; const u8 *dispatcherNoCheck; const u8 *fpException; diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index f046de4453..e79e624e2d 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -76,6 +76,7 @@ void Jit::RunLoopUntil(u64 globalticks) { // TODO: copy globalticks somewhere ((void (*)())asm_.enterCode)(); + // NOTICE_LOG(HLE, "Exited jitted code at %i, corestate=%i, dc=%i", CoreTiming::GetTicks() / 1000, (int)coreState, CoreTiming::downcount); } const u8 *Jit::DoJit(u32 em_address, JitBlock *b) @@ -168,7 +169,7 @@ void Jit::WriteExitDestInEAX() void Jit::WriteSyscallExit() { SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); - JMP(asm_.dispatcher, true); + JMP(asm_.dispatcherCheckCoreState, true); } } // namespace From 8af48d6e54032a6c895d19af2533f14d652087c1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:00:05 -0800 Subject: [PATCH 172/276] Refactor some similar code together. No functionality changes, just moving around. --- Core/Dialog/SavedataParam.cpp | 181 ++++++++++++---------------------- Core/Dialog/SavedataParam.h | 3 +- 2 files changed, 66 insertions(+), 118 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 8f99e0d51f..493acb280f 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -16,7 +16,6 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "SavedataParam.h" -#include "../System.h" #include "image/png_load.h" #include "../HLE/sceKernelMemory.h" #include "../ELF/ParamSFO.h" @@ -430,64 +429,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - saveDataList[realCount].size = info.size; - saveDataList[realCount].saveName = saveNameListData[i]; - saveDataList[realCount].idx = i; - saveDataList[realCount].modif_time = info.mtime; - - // Search save image icon0 - // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound - std::string fileDataPath2 = savePath+GetGameName(param)+saveNameListData[i]+"/"+icon0Name; - PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if (info2.exists) - { - u8 *textureDataPNG = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); - pspFileSystem.CloseFile(handle); - unsigned char* textureData; - int w,h; - pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); - delete[] textureDataPNG; - u32 texSize = w*h*4; - u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); - saveDataList[realCount].textureData = atlasPtr; - Memory::Memcpy(atlasPtr, textureData, texSize); - free(textureData); - saveDataList[realCount].textureWidth = w; - saveDataList[realCount].textureHeight = h; - } - else - { - saveDataList[realCount].textureData = 0; - } - - // Load info in PARAM.SFO - fileDataPath2 = savePath+GetGameName(param)+saveNameListData[i]+"/"+sfoName; - info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if (info2.exists) - { - u8 *sfoParam = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,sfoParam,info2.size); - pspFileSystem.CloseFile(handle); - ParamSFOData sfoFile; - if (sfoFile.ReadSFO(sfoParam, (size_t)info2.size)) - { - std::string title = sfoFile.GetValueString("TITLE"); - memcpy(saveDataList[realCount].title,title.c_str(),title.size()); - saveDataList[realCount].title[title.size()] = 0; - - std::string savetitle = sfoFile.GetValueString("SAVEDATA_TITLE"); - memcpy(saveDataList[realCount].saveTitle,savetitle.c_str(),savetitle.size()); - saveDataList[realCount].saveTitle[savetitle.size()] = 0; - - std::string savedetail = sfoFile.GetValueString("SAVEDATA_DETAIL"); - memcpy(saveDataList[realCount].saveDetail,savedetail.c_str(),savedetail.size()); - saveDataList[realCount].saveDetail[savedetail.size()] = 0; - } - delete [] sfoParam; - } + LoadFileInfo(realCount, info); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); realCount++; @@ -521,64 +463,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - saveDataList[0].size = info.size; - saveDataList[0].saveName = GetSaveName(param); - saveDataList[0].idx = 0; - saveDataList[0].modif_time = info.mtime; - - // Search save image icon0 - // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound - std::string fileDataPath2 = savePath+GetGameName(param)+GetSaveName(param)+"/"+icon0Name; - PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if (info2.exists) - { - u8 *textureDataPNG = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); - pspFileSystem.CloseFile(handle); - unsigned char *textureData; - int w,h; - pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); - delete[] textureDataPNG; - u32 texSize = w*h*4; - u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); - saveDataList[0].textureData = atlasPtr; - Memory::Memcpy(atlasPtr, textureData, texSize); - free(textureData); - saveDataList[0].textureWidth = w; - saveDataList[0].textureHeight = h; - } - else - { - saveDataList[0].textureData = 0; - } - - // Load info in PARAM.SFO - fileDataPath2 = savePath+GetGameName(param)+GetSaveName(param)+"/"+sfoName; - info2 = pspFileSystem.GetFileInfo(fileDataPath2); - if (info2.exists) - { - u8 *sfoParam = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,sfoParam,info2.size); - pspFileSystem.CloseFile(handle); - ParamSFOData sfoFile; - if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) - { - std::string title = sfoFile.GetValueString("TITLE"); - memcpy(saveDataList[0].title,title.c_str(),title.size()); - saveDataList[0].title[title.size()] = 0; - - std::string savetitle = sfoFile.GetValueString("SAVEDATA_TITLE"); - memcpy(saveDataList[0].saveTitle,savetitle.c_str(),savetitle.size()); - saveDataList[0].saveTitle[savetitle.size()] = 0; - - std::string savedetail = sfoFile.GetValueString("SAVEDATA_DETAIL"); - memcpy(saveDataList[0].saveDetail,savedetail.c_str(),savedetail.size()); - saveDataList[0].saveDetail[savedetail.size()] = 0; - } - delete [] sfoParam; - } + LoadFileInfo(0, info); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); saveNameListDataCount = 1; @@ -600,6 +485,68 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) return 0; } +void SavedataParam::LoadFileInfo(int idx, PSPFileInfo &info) +{ + saveDataList[idx].size = info.size; + saveDataList[idx].saveName = GetSaveName(pspParam); + saveDataList[idx].idx = 0; + saveDataList[idx].modif_time = info.mtime; + + // Search save image icon0 + // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound + std::string fileDataPath2 = savePath+GetGameName(pspParam)+GetSaveName(pspParam)+"/"+icon0Name; + PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); + if (info2.exists) + { + u8 *textureDataPNG = new u8[(size_t)info2.size]; + int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); + pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); + pspFileSystem.CloseFile(handle); + unsigned char *textureData; + int w,h; + pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); + delete[] textureDataPNG; + u32 texSize = w*h*4; + u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); + saveDataList[idx].textureData = atlasPtr; + Memory::Memcpy(atlasPtr, textureData, texSize); + free(textureData); + saveDataList[idx].textureWidth = w; + saveDataList[idx].textureHeight = h; + } + else + { + saveDataList[idx].textureData = 0; + } + + // Load info in PARAM.SFO + fileDataPath2 = savePath+GetGameName(pspParam)+GetSaveName(pspParam)+"/"+sfoName; + info2 = pspFileSystem.GetFileInfo(fileDataPath2); + if (info2.exists) + { + u8 *sfoParam = new u8[(size_t)info2.size]; + int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); + pspFileSystem.ReadFile(handle,sfoParam,info2.size); + pspFileSystem.CloseFile(handle); + ParamSFOData sfoFile; + if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) + { + std::string title = sfoFile.GetValueString("TITLE"); + memcpy(saveDataList[idx].title,title.c_str(),title.size()); + saveDataList[idx].title[title.size()] = 0; + + std::string savetitle = sfoFile.GetValueString("SAVEDATA_TITLE"); + memcpy(saveDataList[idx].saveTitle,savetitle.c_str(),savetitle.size()); + saveDataList[idx].saveTitle[savetitle.size()] = 0; + + std::string savedetail = sfoFile.GetValueString("SAVEDATA_DETAIL"); + memcpy(saveDataList[idx].saveDetail,savedetail.c_str(),savedetail.size()); + saveDataList[idx].saveDetail[savedetail.size()] = 0; + } + delete [] sfoParam; + } +} + SceUtilitySavedataParam* SavedataParam::GetPspParam() { return pspParam; diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 841f0cf811..d5be3a30d6 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -18,7 +18,7 @@ #pragma once #include "../HLE/sceKernel.h" - +#include "../System.h" enum SceUtilitySavedataType { @@ -168,6 +168,7 @@ public: private: void Clear(); + void LoadFileInfo(int idx, PSPFileInfo &info); SceUtilitySavedataParam* pspParam; int selectedSave; From cb544261b55ad077b114c130e71ce9db9b4d1092 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:04:49 -0800 Subject: [PATCH 173/276] Fix crash loading bad png file in savedata. --- Core/Dialog/SavedataParam.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 493acb280f..c4b4f29cc0 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -504,15 +504,22 @@ void SavedataParam::LoadFileInfo(int idx, PSPFileInfo &info) pspFileSystem.CloseFile(handle); unsigned char *textureData; int w,h; - pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); + + int success = pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); delete[] textureDataPNG; - u32 texSize = w*h*4; - u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); - saveDataList[idx].textureData = atlasPtr; - Memory::Memcpy(atlasPtr, textureData, texSize); - free(textureData); - saveDataList[idx].textureWidth = w; - saveDataList[idx].textureHeight = h; + + if (success) + { + u32 texSize = w*h*4; + u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); + saveDataList[idx].textureData = atlasPtr; + Memory::Memcpy(atlasPtr, textureData, texSize); + free(textureData); + saveDataList[idx].textureWidth = w; + saveDataList[idx].textureHeight = h; + } + else + saveDataList[idx].textureData = 0; } else { From efefa80ab9548dd51509909923ab3e63f9d3235c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:05:54 -0800 Subject: [PATCH 174/276] Fix a couple warnings on 32 bit in savedata. --- Core/Dialog/SavedataParam.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index c4b4f29cc0..6f53cfd3f1 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -34,7 +34,7 @@ namespace { int getSizeNormalized(int size) { - int sizeCluster = MemoryStick_SectorSize(); + int sizeCluster = (int)MemoryStick_SectorSize(); return ((int)((size + sizeCluster - 1) / sizeCluster)) * sizeCluster; } } @@ -309,7 +309,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) Memory::Write_U32((u32)MemoryStick_SectorSize(),param->msFree); // cluster Size Memory::Write_U32((u32)(MemoryStick_FreeSpace() / MemoryStick_SectorSize()),param->msFree+4); // Free cluster Memory::Write_U32((u32)(MemoryStick_FreeSpace() / 0x400),param->msFree+8); // Free space (in KB) - std::string spaceTxt = SavedataParam::GetSpaceText(MemoryStick_FreeSpace()); + std::string spaceTxt = SavedataParam::GetSpaceText((int)MemoryStick_FreeSpace()); Memory::Memset(param->msFree+12,0,spaceTxt.size()+1); Memory::Memcpy(param->msFree+12,spaceTxt.c_str(),spaceTxt.size()); // Text representing free space } @@ -346,7 +346,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) total_size += getSizeNormalized(param->pic1FileData.size); total_size += getSizeNormalized(param->snd0FileData.size); - Memory::Write_U32(total_size / MemoryStick_SectorSize(),param->utilityData); // num cluster + Memory::Write_U32(total_size / (u32)MemoryStick_SectorSize(),param->utilityData); // num cluster Memory::Write_U32(total_size / 0x400,param->utilityData+4); // save size in KB std::string spaceTxt = SavedataParam::GetSpaceText(total_size); Memory::Memset(param->utilityData+8,0,spaceTxt.size()+1); From ca22e38752a75f8cb628a7e9e3193257b471edba Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:07:00 -0800 Subject: [PATCH 175/276] Fix another potential png load failure. Also, rename func for consistency. --- Core/Dialog/SavedataParam.cpp | 15 ++++++++++----- Core/Dialog/SavedataParam.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 6f53cfd3f1..19584711a9 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -429,7 +429,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - LoadFileInfo(realCount, info); + SetFileInfo(realCount, info); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); realCount++; @@ -463,7 +463,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - LoadFileInfo(0, info); + SetFileInfo(0, info); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); saveNameListDataCount = 1; @@ -485,7 +485,7 @@ u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) return 0; } -void SavedataParam::LoadFileInfo(int idx, PSPFileInfo &info) +void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) { saveDataList[idx].size = info.size; saveDataList[idx].saveName = GetSaveName(pspParam); @@ -508,10 +508,12 @@ void SavedataParam::LoadFileInfo(int idx, PSPFileInfo &info) int success = pngLoadPtr(textureDataPNG, (int)info2.size, &w, &h, &textureData, false); delete[] textureDataPNG; + u32 texSize = w*h*4; + u32 atlasPtr; if (success) + atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); + if (success && atlasPtr > 0) { - u32 texSize = w*h*4; - u32 atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon"); saveDataList[idx].textureData = atlasPtr; Memory::Memcpy(atlasPtr, textureData, texSize); free(textureData); @@ -519,7 +521,10 @@ void SavedataParam::LoadFileInfo(int idx, PSPFileInfo &info) saveDataList[idx].textureHeight = h; } else + { + WARN_LOG(HLE, "Unable to load PNG data for savedata."); saveDataList[idx].textureData = 0; + } } else { diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index d5be3a30d6..616e26d48d 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -168,7 +168,7 @@ public: private: void Clear(); - void LoadFileInfo(int idx, PSPFileInfo &info); + void SetFileInfo(int idx, PSPFileInfo &info); SceUtilitySavedataParam* pspParam; int selectedSave; From f983c8af5cf4f3bde878c4ed4dc33536c63a95e9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:18:59 -0800 Subject: [PATCH 176/276] Protect against an unlikely buffer overflow. --- Core/Dialog/SavedataParam.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 19584711a9..32b4dadd11 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -37,6 +37,13 @@ namespace int sizeCluster = (int)MemoryStick_SectorSize(); return ((int)((size + sizeCluster - 1) / sizeCluster)) * sizeCluster; } + + void SetStringFromSFO(ParamSFOData &sfoFile, const char *name, char *str, int strLength) + { + std::string value = sfoFile.GetValueString(name); + strncpy(str, value.c_str(), strLength - 1); + str[strLength - 1] = 0; + } } SavedataParam::SavedataParam() @@ -543,17 +550,9 @@ void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) ParamSFOData sfoFile; if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) { - std::string title = sfoFile.GetValueString("TITLE"); - memcpy(saveDataList[idx].title,title.c_str(),title.size()); - saveDataList[idx].title[title.size()] = 0; - - std::string savetitle = sfoFile.GetValueString("SAVEDATA_TITLE"); - memcpy(saveDataList[idx].saveTitle,savetitle.c_str(),savetitle.size()); - saveDataList[idx].saveTitle[savetitle.size()] = 0; - - std::string savedetail = sfoFile.GetValueString("SAVEDATA_DETAIL"); - memcpy(saveDataList[idx].saveDetail,savedetail.c_str(),savedetail.size()); - saveDataList[idx].saveDetail[savedetail.size()] = 0; + SetStringFromSFO(sfoFile, "TITLE", saveDataList[idx].title, sizeof(saveDataList[idx].title)); + SetStringFromSFO(sfoFile, "SAVEDATA_TITLE", saveDataList[idx].saveTitle, sizeof(saveDataList[idx].saveTitle)); + SetStringFromSFO(sfoFile, "SAVEDATA_DETAIL", saveDataList[idx].saveDetail, sizeof(saveDataList[idx].saveDetail)); } delete [] sfoParam; } From db6ef8ce642c21c70e2bc6912d27740e8eb537a9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 17:32:14 -0800 Subject: [PATCH 177/276] Simplify reading/writing in one shot. --- Core/Dialog/SavedataParam.cpp | 88 +++++++++++++---------------------- 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 32b4dadd11..5385acb652 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -44,6 +44,30 @@ namespace strncpy(str, value.c_str(), strLength - 1); str[strLength - 1] = 0; } + + bool ReadPSPFile(std::string filename, u8 *data, s64 dataSize) + { + u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ); + if (handle == 0) + return false; + + int result = pspFileSystem.ReadFile(handle, data, dataSize); + pspFileSystem.CloseFile(handle); + + return result != 0; + } + + bool WritePSPFile(std::string filename, u8 *data, int dataSize) + { + u32 handle = pspFileSystem.OpenFile(filename, (FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); + if (handle == 0) + return false; + + int result = pspFileSystem.WriteFile(handle, data, dataSize); + pspFileSystem.CloseFile(handle); + + return result != 0; + } } SavedataParam::SavedataParam() @@ -145,22 +169,13 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) std::string filePath = dirPath+"/"+GetFileName(param); INFO_LOG(HLE,"Saving file with size %u in %s",param->dataBufSize,filePath.c_str()); - unsigned int handle = pspFileSystem.OpenFile(filePath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle == 0) + if (!WritePSPFile(filePath, data_, param->dataBufSize)) { - ERROR_LOG(HLE,"Error opening file %s",filePath.c_str()); - return false; - } - if (!pspFileSystem.WriteFile(handle, data_, param->dataBufSize)) - { - pspFileSystem.CloseFile(handle); ERROR_LOG(HLE,"Error writing file %s",filePath.c_str()); return false; } else { - pspFileSystem.CloseFile(handle); - // SAVE PARAM.SFO ParamSFOData sfoFile; sfoFile.SetValue("TITLE",param->sfoParam.title,128); @@ -175,12 +190,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) size_t sfoSize; sfoFile.WriteSFO(&sfoData,&sfoSize); std::string sfopath = dirPath+"/"+sfoName; - handle = pspFileSystem.OpenFile(sfopath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, sfoData, sfoSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(sfopath, sfoData, sfoSize); delete[] sfoData; // SAVE ICON0 @@ -188,36 +198,21 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon0FileData.buf)); std::string icon0path = dirPath+"/"+icon0Name; - handle = pspFileSystem.OpenFile(icon0path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, data_, param->icon0FileData.bufSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(icon0path, data_, param->icon0FileData.bufSize); } // SAVE ICON1 if (param->icon1FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon1FileData.buf)); std::string icon1path = dirPath+"/"+icon1Name; - handle = pspFileSystem.OpenFile(icon1path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, data_, param->icon1FileData.bufSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(icon1path, data_, param->icon1FileData.bufSize); } // SAVE PIC1 if (param->pic1FileData.buf) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->pic1FileData.buf)); std::string pic1path = dirPath+"/"+pic1Name; - handle = pspFileSystem.OpenFile(pic1path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, data_, param->pic1FileData.bufSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(pic1path, data_, param->pic1FileData.bufSize); } // Save SND @@ -225,12 +220,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) { data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->snd0FileData.buf)); std::string snd0path = dirPath+"/"+snd0Name; - handle = pspFileSystem.OpenFile(snd0path,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, data_, param->snd0FileData.bufSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); } } return true; @@ -255,19 +245,11 @@ bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) std::string filePath = dirPath+"/"+GetFileName(param); INFO_LOG(HLE,"Loading file with size %u in %s",param->dataBufSize,filePath.c_str()); - u32 handle = pspFileSystem.OpenFile(filePath,FILEACCESS_READ); - if (!handle) + if (!ReadPSPFile(filePath, data_, param->dataBufSize)) { - ERROR_LOG(HLE,"Error opening file %s",filePath.c_str()); - return false; - } - if (!pspFileSystem.ReadFile(handle, data_, param->dataBufSize)) - { - pspFileSystem.CloseFile(handle); ERROR_LOG(HLE,"Error reading file %s",filePath.c_str()); return false; } - pspFileSystem.CloseFile(handle); return true; } @@ -506,9 +488,7 @@ void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) if (info2.exists) { u8 *textureDataPNG = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,textureDataPNG,info2.size); - pspFileSystem.CloseFile(handle); + ReadPSPFile(fileDataPath2, textureDataPNG, info2.size); unsigned char *textureData; int w,h; @@ -544,9 +524,7 @@ void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) if (info2.exists) { u8 *sfoParam = new u8[(size_t)info2.size]; - int handle = pspFileSystem.OpenFile(fileDataPath2,FILEACCESS_READ); - pspFileSystem.ReadFile(handle,sfoParam,info2.size); - pspFileSystem.CloseFile(handle); + ReadPSPFile(fileDataPath2, sfoParam, info2.size); ParamSFOData sfoFile; if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size)) { From f8f581794ffb90a0a2c2b0db0ec581c1410cb429 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 18:37:28 -0800 Subject: [PATCH 178/276] Make sure sceUtility funcs all return error codes. Right now, everything is 0, but before it wasn't returning anything. Returning 0 actually made some games start working right. --- Core/Dialog/PSPDialog.cpp | 7 +-- Core/Dialog/PSPDialog.h | 4 +- Core/Dialog/PSPMsgDialog.cpp | 19 +++---- Core/Dialog/PSPMsgDialog.h | 6 +-- Core/Dialog/PSPOskDialog.cpp | 4 +- Core/Dialog/PSPOskDialog.h | 2 +- Core/Dialog/PSPPlaceholderDialog.cpp | 6 ++- Core/Dialog/PSPPlaceholderDialog.h | 4 +- Core/Dialog/PSPSaveDialog.cpp | 13 +++-- Core/Dialog/PSPSaveDialog.h | 6 +-- Core/Dialog/SavedataParam.cpp | 2 +- Core/Dialog/SavedataParam.h | 2 +- Core/HLE/sceUtility.cpp | 74 +++++++++++++--------------- 13 files changed, 77 insertions(+), 72 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 0f0e469543..daf9c967ce 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -53,14 +53,15 @@ void PSPDialog::DisplayMessage(std::string text) PPGeDrawText(text.c_str(), 480/2, 100, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); } -void PSPDialog::Shutdown() +int PSPDialog::Shutdown() { status = SCE_UTILITY_STATUS_SHUTDOWN; + return 0; } -void PSPDialog::Update() +int PSPDialog::Update() { - + return 0; } bool PSPDialog::IsButtonPressed(int checkButton) diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index efab28f823..c9c06120c8 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -45,8 +45,8 @@ public: PSPDialog(); virtual ~PSPDialog(); - virtual void Update(); - virtual void Shutdown(); + virtual int Update(); + virtual int Shutdown(); enum DialogStatus { diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 1ca3fe7d94..5d0fa4a06b 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -29,18 +29,18 @@ PSPMsgDialog::PSPMsgDialog() PSPMsgDialog::~PSPMsgDialog() { } -void PSPMsgDialog::Init(unsigned int paramAddr) +int PSPMsgDialog::Init(unsigned int paramAddr) { // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { - return; + return 0; } messageDialogAddr = paramAddr; if (!Memory::IsValidAddress(messageDialogAddr)) { - return; + return 0; } Memory::ReadStruct(messageDialogAddr, &messageDialog); @@ -63,7 +63,7 @@ void PSPMsgDialog::Init(unsigned int paramAddr) status = SCE_UTILITY_STATUS_INITIALIZE; lastButtons = __CtrlPeekButtons(); - + return 0; } void PSPMsgDialog::DisplayBack() @@ -95,7 +95,7 @@ void PSPMsgDialog::DisplayEnterBack() PPGeDrawText("Back", 320, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); } -void PSPMsgDialog::Update() +int PSPMsgDialog::Update() { switch (status) { case SCE_UTILITY_STATUS_FINISHED: @@ -105,7 +105,7 @@ void PSPMsgDialog::Update() if (status != SCE_UTILITY_STATUS_RUNNING) { - return; + return 0; } const char *text; @@ -191,17 +191,18 @@ void PSPMsgDialog::Update() break; default: status = SCE_UTILITY_STATUS_FINISHED; - return; + return 0; break; } lastButtons = buttons; Memory::WriteStruct(messageDialogAddr, &messageDialog); + return 0; } -void PSPMsgDialog::Shutdown() +int PSPMsgDialog::Shutdown() { - PSPDialog::Shutdown(); + return PSPDialog::Shutdown(); } diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index e3c1af1699..80b1f24e9f 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -41,9 +41,9 @@ public: PSPMsgDialog(); virtual ~PSPMsgDialog(); - virtual void Init(unsigned int paramAddr); - virtual void Update(); - void Shutdown(); + virtual int Init(unsigned int paramAddr); + virtual int Update(); + int Shutdown(); private : void DisplayBack(); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index f2d186c5a5..a1c6e8fe7b 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -143,7 +143,7 @@ void PSPOskDialog::RenderKeyboard() } -void PSPOskDialog::Update() +int PSPOskDialog::Update() { buttons = __CtrlReadLatch(); int selectedRow = selectedChar / KEYSPERROW; @@ -230,4 +230,6 @@ void PSPOskDialog::Update() oskData.result = PSP_UTILITY_OSK_RESULT_CHANGED; Memory::WriteStruct(oskParams.SceUtilityOskDataPtr, &oskData); Memory::WriteStruct(oskParamsAddr, &oskParams); + + return 0; } diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h index 9939923499..387abc32b9 100644 --- a/Core/Dialog/PSPOskDialog.h +++ b/Core/Dialog/PSPOskDialog.h @@ -145,7 +145,7 @@ public: virtual ~PSPOskDialog(); virtual int Init(u32 oskPtr); - virtual void Update(); + virtual int Update(); private: void HackyGetStringWide(std::string& _string, const u32 em_address); void RenderKeyboard(); diff --git a/Core/Dialog/PSPPlaceholderDialog.cpp b/Core/Dialog/PSPPlaceholderDialog.cpp index ccd26ed8b6..72e8670316 100644 --- a/Core/Dialog/PSPPlaceholderDialog.cpp +++ b/Core/Dialog/PSPPlaceholderDialog.cpp @@ -25,12 +25,13 @@ PSPPlaceholderDialog::~PSPPlaceholderDialog() { } -void PSPPlaceholderDialog::Init() +int PSPPlaceholderDialog::Init() { status = SCE_UTILITY_STATUS_INITIALIZE; + return 0; } -void PSPPlaceholderDialog::Update() +int PSPPlaceholderDialog::Update() { //__UtilityUpdate(); if (status == SCE_UTILITY_STATUS_INITIALIZE) @@ -45,4 +46,5 @@ void PSPPlaceholderDialog::Update() { status = SCE_UTILITY_STATUS_SHUTDOWN; } + return 0; } diff --git a/Core/Dialog/PSPPlaceholderDialog.h b/Core/Dialog/PSPPlaceholderDialog.h index 7854b07dc2..7ba4a989de 100644 --- a/Core/Dialog/PSPPlaceholderDialog.h +++ b/Core/Dialog/PSPPlaceholderDialog.h @@ -24,7 +24,7 @@ public: PSPPlaceholderDialog(); virtual ~PSPPlaceholderDialog(); - virtual void Init(); - virtual void Update(); + virtual int Init(); + virtual int Update(); }; diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 0e4f27beb3..e89a427c9c 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -31,7 +31,7 @@ PSPSaveDialog::PSPSaveDialog() PSPSaveDialog::~PSPSaveDialog() { } -u32 PSPSaveDialog::Init(int paramAddr) +int PSPSaveDialog::Init(int paramAddr) { // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) @@ -315,7 +315,7 @@ void PSPSaveDialog::DisplayBack() PPGeDrawText("Back", 270, 220, PPGE_ALIGN_LEFT, 0.5f, 0xFFFFFFFF); } -void PSPSaveDialog::Update() +int PSPSaveDialog::Update() { switch (status) { case SCE_UTILITY_STATUS_FINISHED: @@ -327,12 +327,12 @@ void PSPSaveDialog::Update() if (status != SCE_UTILITY_STATUS_RUNNING) { - return; + return 0; } if (!param.GetPspParam()) { status = SCE_UTILITY_STATUS_SHUTDOWN; - return; + return 0; } buttons = __CtrlPeekButtons(); @@ -684,11 +684,14 @@ void PSPSaveDialog::Update() Memory::Memcpy(requestAddr,&request,request.size); } + return 0; } -void PSPSaveDialog::Shutdown() +int PSPSaveDialog::Shutdown() { PSPDialog::Shutdown(); param.SetPspParam(0); + + return 0; } diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index 6ee98f59f3..14034e6fa2 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -62,9 +62,9 @@ public: PSPSaveDialog(); virtual ~PSPSaveDialog(); - virtual u32 Init(int paramAddr); - virtual void Update(); - void Shutdown(); + virtual int Init(int paramAddr); + virtual int Update(); + int Shutdown(); private : diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 5385acb652..6c28c53485 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -378,7 +378,7 @@ void SavedataParam::Clear() } } -u32 SavedataParam::SetPspParam(SceUtilitySavedataParam *param) +int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) { pspParam = param; if (!pspParam) diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 616e26d48d..fb248e43d5 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -156,7 +156,7 @@ public: SavedataParam(); - u32 SetPspParam(SceUtilitySavedataParam* param); + int SetPspParam(SceUtilitySavedataParam* param); SceUtilitySavedataParam* GetPspParam(); int GetFilenameCount(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index b66f705066..0d2340e0da 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -50,14 +50,13 @@ void __UtilityShutdown() int sceUtilitySavedataInitStart(u32 paramAddr) { DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); - return (u32)saveDialog.Init(paramAddr); + return saveDialog.Init(paramAddr); } int sceUtilitySavedataShutdownStart() { DEBUG_LOG(HLE,"sceUtilitySavedataShutdownStart()"); - saveDialog.Shutdown(); - return 0; + return saveDialog.Shutdown(); } int sceUtilitySavedataGetStatus() @@ -65,13 +64,10 @@ int sceUtilitySavedataGetStatus() return saveDialog.GetStatus(); } -void sceUtilitySavedataUpdate(u32 unknown) +int sceUtilitySavedataUpdate(int animSpeed) { - DEBUG_LOG(HLE,"sceUtilitySavedataUpdate()"); - - saveDialog.Update(); - - return; + DEBUG_LOG(HLE,"sceUtilitySavedataUpdate(%d)", animSpeed); + return saveDialog.Update(); } #define PSP_AV_MODULE_AVCODEC 0 @@ -99,26 +95,27 @@ void sceUtilityLoadModule(u32 module) __KernelReSchedule("utilityloadmodule"); } -void sceUtilityMsgDialogInitStart(u32 structAddr) +int sceUtilityMsgDialogInitStart(u32 structAddr) { DEBUG_LOG(HLE,"sceUtilityMsgDialogInitStart(%i)", structAddr); - msgDialog.Init(structAddr); + return msgDialog.Init(structAddr); } -void sceUtilityMsgDialogShutdownStart(u32 unknown) +int sceUtilityMsgDialogShutdownStart(u32 unknown) { DEBUG_LOG(HLE,"FAKE sceUtilityMsgDialogShutdownStart(%i)", unknown); - msgDialog.Shutdown(); + return msgDialog.Shutdown(); } -void sceUtilityMsgDialogUpdate(int animSpeed) +int sceUtilityMsgDialogUpdate(int animSpeed) { DEBUG_LOG(HLE,"sceUtilityMsgDialogUpdate(%i)", animSpeed); - msgDialog.Update(); + return msgDialog.Update(); } -u32 sceUtilityMsgDialogGetStatus() +int sceUtilityMsgDialogGetStatus() { + DEBUG_LOG(HLE,"sceUtilityMsgDialogGetStatus()"); return msgDialog.GetStatus(); } @@ -134,14 +131,13 @@ int sceUtilityOskInitStart(u32 oskPtr) int sceUtilityOskShutdownStart() { ERROR_LOG(HLE,"FAKE sceUtilityOskShutdownStart(%i)", PARAM(0)); - oskDialog.Shutdown(); - return 0; + return oskDialog.Shutdown(); } -void sceUtilityOskUpdate(unsigned int unknown) +int sceUtilityOskUpdate(unsigned int unknown) { ERROR_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); - oskDialog.Update(); + return oskDialog.Update(); } int sceUtilityOskGetStatus() @@ -156,25 +152,25 @@ int sceUtilityOskGetStatus() } -void sceUtilityNetconfInitStart(unsigned int unknown) +int sceUtilityNetconfInitStart(u32 structAddr) { - DEBUG_LOG(HLE,"FAKE sceUtilityNetconfInitStart(%i)", unknown); - netDialog.Init(); + DEBUG_LOG(HLE,"FAKE sceUtilityNetconfInitStart(%08x)", structAddr); + return netDialog.Init(); } -void sceUtilityNetconfShutdownStart(unsigned int unknown) +int sceUtilityNetconfShutdownStart(unsigned int unknown) { DEBUG_LOG(HLE,"FAKE sceUtilityNetconfShutdownStart(%i)", unknown); - netDialog.Shutdown(); + return netDialog.Shutdown(); } -void sceUtilityNetconfUpdate(int unknown) +int sceUtilityNetconfUpdate(int animSpeed) { - DEBUG_LOG(HLE,"FAKE sceUtilityNetconfUpdate(%i)", unknown); - netDialog.Update(); + DEBUG_LOG(HLE,"FAKE sceUtilityNetconfUpdate(%i)", animSpeed); + return netDialog.Update(); } -unsigned int sceUtilityNetconfGetStatus() +int sceUtilityNetconfGetStatus() { DEBUG_LOG(HLE,"sceUtilityNetconfGetStatus()"); return netDialog.GetStatus(); @@ -356,28 +352,28 @@ const HLEFunction sceUtility[] = {0x64d50c56, &WrapU_U, "sceUtilityUnloadNetModule"}, - {0xf88155f6, &WrapV_U, "sceUtilityNetconfShutdownStart"}, - {0x4db1e739, &WrapV_U, "sceUtilityNetconfInitStart"}, - {0x91e70e35, &WrapV_I, "sceUtilityNetconfUpdate"}, - {0x6332aa39, &WrapU_V, "sceUtilityNetconfGetStatus"}, + {0xf88155f6, &WrapI_U, "sceUtilityNetconfShutdownStart"}, + {0x4db1e739, &WrapI_U, "sceUtilityNetconfInitStart"}, + {0x91e70e35, &WrapI_I, "sceUtilityNetconfUpdate"}, + {0x6332aa39, &WrapI_V, "sceUtilityNetconfGetStatus"}, {0x5eee6548, 0, "sceUtilityCheckNetParam"}, {0x434d4b3a, 0, "sceUtilityGetNetParam"}, {0x4FED24D8, 0, "sceUtilityGetNetParamLatestID"}, - {0x67af3428, &WrapV_U, "sceUtilityMsgDialogShutdownStart"}, - {0x2ad8e239, &WrapV_U, "sceUtilityMsgDialogInitStart"}, - {0x95fc253b, &WrapV_I, "sceUtilityMsgDialogUpdate"}, - {0x9a1c91d7, &WrapU_V, "sceUtilityMsgDialogGetStatus"}, + {0x67af3428, &WrapI_U, "sceUtilityMsgDialogShutdownStart"}, + {0x2ad8e239, &WrapI_U, "sceUtilityMsgDialogInitStart"}, + {0x95fc253b, &WrapI_I, "sceUtilityMsgDialogUpdate"}, + {0x9a1c91d7, &WrapI_V, "sceUtilityMsgDialogGetStatus"}, {0x4928bd96, 0, "sceUtilityMsgDialogAbort"}, {0x9790b33c, &WrapI_V, "sceUtilitySavedataShutdownStart"}, {0x50c4cd57, &WrapI_U, "sceUtilitySavedataInitStart"}, - {0xd4b95ffb, &WrapV_U, "sceUtilitySavedataUpdate"}, + {0xd4b95ffb, &WrapI_I, "sceUtilitySavedataUpdate"}, {0x8874dbe0, &WrapI_V, "sceUtilitySavedataGetStatus"}, {0x3dfaeba9, &WrapI_V, "sceUtilityOskShutdownStart"}, {0xf6269b82, &WrapI_U, "sceUtilityOskInitStart"}, - {0x4b85c861, &WrapV_U, "sceUtilityOskUpdate"}, + {0x4b85c861, &WrapI_U, "sceUtilityOskUpdate"}, {0xf3f76017, &WrapI_V, "sceUtilityOskGetStatus"}, {0x41e30674, &WrapU_UU, "sceUtilitySetSystemParamString"}, From 0fa0d3f6db2289e4b3644f84c68b48b11f1620e3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Dec 2012 19:14:09 -0800 Subject: [PATCH 179/276] Oops, need to use saveNameList when specified. Mistake from 6f165cfbe46ead77e3b4e99fe18ee1609188cf9c... --- Core/Dialog/SavedataParam.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 6c28c53485..0b69bf5c51 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -419,6 +419,7 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) if (info.exists) { SetFileInfo(realCount, info); + saveDataList[realCount].saveName = saveNameListData[i]; DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); realCount++; @@ -453,6 +454,7 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) if (info.exists) { SetFileInfo(0, info); + saveDataList[0].saveName = GetSaveName(pspParam); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); saveNameListDataCount = 1; @@ -477,7 +479,6 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) { saveDataList[idx].size = info.size; - saveDataList[idx].saveName = GetSaveName(pspParam); saveDataList[idx].idx = 0; saveDataList[idx].modif_time = info.mtime; From 38a7059bdd234df8e5189b688f4b09f58d158c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 10:08:57 +0100 Subject: [PATCH 180/276] Initialize some stuff in SasAudio, fixes some audio issues on my mac --- Core/HW/SasAudio.cpp | 20 ++++++++++++++++---- Core/HW/SasAudio.h | 21 ++++++++++----------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 6b56144d31..90b4894adb 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -20,7 +20,7 @@ #include "../MemMap.h" #include "SasAudio.h" -static const double f[5][2] = +static const double f[5][2] = { { 0.0, 0.0 }, { 60.0 / 64.0, 0.0 }, { 115.0 / 64.0, -52.0 / 64.0 }, @@ -58,7 +58,7 @@ bool VagDecoder::DecodeBlock() else if (flags == 3 && loopEnabled_) { loopAtNextBlock_ = true; } - for (int i = 0; i < 28; i += 2) + for (int i = 0; i < 28; i += 2) { int d = GetByte(); int s = (short)((d & 0xf) << 12); @@ -168,8 +168,14 @@ void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) { sustainLevel = getSustainLevel(ADSREnv1); } -SasInstance::SasInstance() - : mixBuffer(0), sendBuffer(0), resampleBuffer(0), grainSize(0) { +SasInstance::SasInstance() + : maxVoices(PSP_SAS_VOICES_MAX), + sampleRate(44100), + outputMode(0), + mixBuffer(0), + sendBuffer(0), + resampleBuffer(0), + grainSize(0) { } SasInstance::~SasInstance() { @@ -409,6 +415,12 @@ static int getExpCurveAt(int index, int duration) { return (short)(sample); } +ADSREnvelope::ADSREnvelope() + : steps_(0), + state_(STATE_OFF), + height_(0) { +} + void ADSREnvelope::WalkCurve(int rate, int type) { short expFactor; int duration; diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 3b776f5c6d..d913a03366 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -111,6 +111,7 @@ private: class ADSREnvelope { public: + ADSREnvelope(); void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2); void WalkCurve(int rate, int type); @@ -121,7 +122,7 @@ public: void Step(); int GetHeight() const { - return height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX ? PSP_SAS_ENVELOPE_HEIGHT_MAX : height_; + return height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX ? PSP_SAS_ENVELOPE_HEIGHT_MAX : height_; } bool HasEnded() const { return state_ == STATE_OFF; @@ -158,7 +159,7 @@ struct SasVoice { SasVoice() : playing(false), paused(false), on(false), - type(VOICETYPE_OFF), + type(VOICETYPE_OFF), vagAddr(0), vagSize(0), pcmAddr(0), @@ -171,7 +172,13 @@ struct SasVoice volumeLeft(0), volumeRight(0), volumeLeftSend(0), - volumeRightSend(0) {} + volumeRightSend(0) { + } + + void Reset(); + void KeyOn(); + void KeyOff(); + void ChangedParams(bool changedVag); bool playing; bool paused; // a voice can be playing AND paused. In that case, it won't play. @@ -195,14 +202,6 @@ struct SasVoice int volumeRight; int volumeLeftSend; // volume to "Send" (audio-lingo) to the effects processing engine, like reverb int volumeRightSend; - - void Reset(); - - void KeyOn(); - void KeyOff(); - - void ChangedParams(bool changedVag); - s16 resampleHist[2]; ADSREnvelope envelope; From 1a71bf3aafd3cd3235dbd44ad6411c4da29b329d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 01:36:21 -0800 Subject: [PATCH 181/276] Fix potential buffer overflow. Detail can be 1024 already, I guess. --- Core/Dialog/PSPSaveDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index e89a427c9c..5fad54b585 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -238,7 +238,9 @@ void PSPSaveDialog::DisplaySaveDataInfo1() } else { - char txt[1024]; + char txt[2048]; + _dbg_assert_msg_(HLE, sizeof(txt) > sizeof(SaveFileInfo), "Local buffer is too small."); + sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %lld KB\n%s\n%s" , param.GetFileInfo(currentSelectedSave).title , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday From b0295664e809b503b5ca7544ff283d5d4e445672 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 01:36:51 -0800 Subject: [PATCH 182/276] Correctly fix incorrect save directory being used. Darn, should've caught this before when I refactored wrong. --- Core/Dialog/SavedataParam.cpp | 26 ++++++++++++-------------- Core/Dialog/SavedataParam.h | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 0b69bf5c51..af3cb111be 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -418,8 +418,7 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - SetFileInfo(realCount, info); - saveDataList[realCount].saveName = saveNameListData[i]; + SetFileInfo(realCount, info, saveNameListData[i]); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); realCount++; @@ -453,8 +452,7 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) PSPFileInfo info = pspFileSystem.GetFileInfo(fileDataPath); if (info.exists) { - SetFileInfo(0, info); - saveDataList[0].saveName = GetSaveName(pspParam); + SetFileInfo(0, info, GetSaveName(pspParam)); DEBUG_LOG(HLE,"%s Exist",fileDataPath.c_str()); saveNameListDataCount = 1; @@ -476,15 +474,22 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) return 0; } -void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) +void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info, std::string saveName) { saveDataList[idx].size = info.size; + saveDataList[idx].saveName = saveName; saveDataList[idx].idx = 0; saveDataList[idx].modif_time = info.mtime; + // Start with a blank slate. + saveDataList[idx].textureData = 0; + saveDataList[idx].title[0] = 0; + saveDataList[idx].saveTitle[0] = 0; + saveDataList[idx].saveDetail[0] = 0; + // Search save image icon0 // TODO : If icon0 don't exist, need to use icon1 which is a moving icon. Also play sound - std::string fileDataPath2 = savePath+GetGameName(pspParam)+GetSaveName(pspParam)+"/"+icon0Name; + std::string fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + icon0Name; PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2); if (info2.exists) { @@ -509,18 +514,11 @@ void SavedataParam::SetFileInfo(int idx, PSPFileInfo &info) saveDataList[idx].textureHeight = h; } else - { WARN_LOG(HLE, "Unable to load PNG data for savedata."); - saveDataList[idx].textureData = 0; - } - } - else - { - saveDataList[idx].textureData = 0; } // Load info in PARAM.SFO - fileDataPath2 = savePath+GetGameName(pspParam)+GetSaveName(pspParam)+"/"+sfoName; + fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + sfoName; info2 = pspFileSystem.GetFileInfo(fileDataPath2); if (info2.exists) { diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index fb248e43d5..78b6d8fec0 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -168,7 +168,7 @@ public: private: void Clear(); - void SetFileInfo(int idx, PSPFileInfo &info); + void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName); SceUtilitySavedataParam* pspParam; int selectedSave; From b5b13256b6899d8c5b4b7bd18d980ff92035de02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 10:25:14 +0100 Subject: [PATCH 183/276] CMake build: enable optimization --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index adaf9dc6fb..51caab7186 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ endif() if(NOT MSVC) # Disable some warnings + add_definitions(-O2) add_definitions(-Wno-multichar) add_definitions(-fno-strict-aliasing) if(NOT APPLE) From d21647bbb929806c463b387f3858da38e6e688a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 13:47:59 +0100 Subject: [PATCH 184/276] Split code from GLES_GPU to TransformDrawEngine, cleanup --- GPU/GLES/DisplayListInterpreter.cpp | 210 ++++++++++------------------ GPU/GLES/DisplayListInterpreter.h | 19 +-- GPU/GLES/StateMapping.cpp | 26 ++-- GPU/GLES/StateMapping.h | 5 + GPU/GLES/TransformPipeline.cpp | 58 +++++--- GPU/GLES/TransformPipeline.h | 54 ++++--- GPU/GPUInterface.h | 2 +- GPU/GPUState.cpp | 7 +- 8 files changed, 180 insertions(+), 201 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d05fced423..226e091540 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -33,17 +33,11 @@ #include "../../Core/HLE/sceKernelThread.h" #include "../../Core/HLE/sceKernelInterrupt.h" -inline void glEnDis(GLuint cmd, int value) -{ - (value ? glEnable : glDisable)(cmd); -} - ShaderManager shaderManager; extern u32 curTextureWidth; extern u32 curTextureHeight; -bool *flushBeforeCommand = 0; const int flushBeforeCommandList[] = { GE_CMD_BEZIER, GE_CMD_SPLINE, @@ -54,10 +48,10 @@ const int flushBeforeCommandList[] = { GE_CMD_OFFSETADDR, GE_CMD_REGION1, GE_CMD_REGION2, - GE_CMD_CULLFACEENABLE, - GE_CMD_TEXTUREMAPENABLE, + GE_CMD_CULLFACEENABLE, + GE_CMD_TEXTUREMAPENABLE, GE_CMD_LIGHTINGENABLE, - GE_CMD_FOGENABLE, + GE_CMD_FOGENABLE, GE_CMD_TEXSCALEU, GE_CMD_TEXSCALEV, GE_CMD_TEXOFFSETU, @@ -163,43 +157,38 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1) -{ + dlIdGenerator(1), + transformDraw_(&shaderManager) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; shaderManager_ = &shaderManager; TextureCache_Init(); - InitTransform(); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - flushBeforeCommand = new bool[256]; - memset(flushBeforeCommand, 0, 256 * sizeof(bool)); + flushBeforeCommand_ = new bool[256]; + memset(flushBeforeCommand_, 0, 256 * sizeof(bool)); for (int i = 0; i < ARRAY_SIZE(flushBeforeCommandList); i++) { - flushBeforeCommand[flushBeforeCommandList[i]] = true; + flushBeforeCommand_[flushBeforeCommandList[i]] = true; } - flushBeforeCommand[1] = false; + flushBeforeCommand_[1] = false; } -GLES_GPU::~GLES_GPU() -{ +GLES_GPU::~GLES_GPU() { TextureCache_Shutdown(); - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) - { + for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { fbo_destroy((*iter)->fbo); delete (*iter); } vfbs_.clear(); - delete flushBeforeCommand; + delete [] flushBeforeCommand_; } -void GLES_GPU::InitClear() -{ - if (!g_Config.bBufferedRendering) - { +void GLES_GPU::InitClear() { + if (!g_Config.bBufferedRendering) { glClearColor(0,0,0,1); // glClearColor(1,0,1,1); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); @@ -207,13 +196,11 @@ void GLES_GPU::InitClear() glViewport(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); } -void GLES_GPU::BeginFrame() -{ +void GLES_GPU::BeginFrame() { TextureCache_Decimate(); // NOTE - this is all wrong. At the beginning of the frame is a TERRIBLE time to draw the fb. - if (g_Config.bDisplayFramebuffer && displayFramebufPtr_) - { + if (g_Config.bDisplayFramebuffer && displayFramebufPtr_) { INFO_LOG(HLE, "Drawing the framebuffer"); const u8 *pspframebuf = Memory::GetPointer((0x44000000) | (displayFramebufPtr_ & 0x1FFFFF)); // TODO - check glstate.cullFace.disable(); @@ -225,8 +212,7 @@ void GLES_GPU::BeginFrame() currentRenderVfb_ = 0; } -void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) -{ +void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) { if (framebuf & 0x04000000) { DEBUG_LOG(G3D, "Switch display framebuffer %08x", framebuf); displayFramebufPtr_ = framebuf; @@ -237,9 +223,8 @@ void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) } } -void GLES_GPU::CopyDisplayToOutput() -{ - Flush(); +void GLES_GPU::CopyDisplayToOutput() { + transformDraw_.Flush(); if (!g_Config.bBufferedRendering) return; @@ -271,17 +256,15 @@ void GLES_GPU::CopyDisplayToOutput() // These are in the output display coordinates framebufferManager.DrawActiveTexture(480, 272, true); - shaderManager.DirtyShader(); - shaderManager.DirtyUniform(DIRTY_ALL); + shaderManager_->DirtyShader(); + shaderManager_->DirtyUniform(DIRTY_ALL); gstate_c.textureChanged = true; BeginDebugDraw(); } -GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() -{ - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) - { +GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() { + for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { if (((*iter)->fb_address & 0x3FFFFFF) == (displayFramebufPtr_ & 0x3FFFFFF)) { // Could check w to but whatever return *iter; @@ -291,8 +274,7 @@ GLES_GPU::VirtualFramebuffer *GLES_GPU::GetDisplayFBO() return 0; } -void GLES_GPU::SetRenderFrameBuffer() -{ +void GLES_GPU::SetRenderFrameBuffer() { if (!g_Config.bBufferedRendering) return; // Get parameters @@ -301,7 +283,7 @@ void GLES_GPU::SetRenderFrameBuffer() u32 z_address = (gstate.zbptr & 0xFFE000) | ((gstate.zbwidth & 0xFF0000) << 8); int z_stride = gstate.zbwidth & 0x3C0; - + // Yeah this is not completely right. but it'll do for now. int drawing_width = ((gstate.region2) & 0x3FF) + 1; int drawing_height = ((gstate.region2 >> 10) & 0x3FF) + 1; @@ -310,8 +292,7 @@ void GLES_GPU::SetRenderFrameBuffer() // Find a matching framebuffer VirtualFramebuffer *vfb = 0; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) - { + for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { VirtualFramebuffer *v = *iter; if (v->fb_address == fb_address) { // Let's not be so picky for now. Let's say this is the one. @@ -324,7 +305,7 @@ void GLES_GPU::SetRenderFrameBuffer() // None found? Create one. if (!vfb) { - Flush(); + transformDraw_.Flush(); gstate_c.textureChanged = true; vfb = new VirtualFramebuffer; vfb->fb_address = fb_address; @@ -344,9 +325,8 @@ void GLES_GPU::SetRenderFrameBuffer() return; } - if (vfb != currentRenderVfb_) - { - Flush(); + if (vfb != currentRenderVfb_) { + transformDraw_.Flush(); // Use it as a render target. DEBUG_LOG(HLE, "Switching render target to FBO for %08x", vfb->fb_address); gstate_c.textureChanged = true; @@ -356,8 +336,7 @@ void GLES_GPU::SetRenderFrameBuffer() } } -void GLES_GPU::BeginDebugDraw() -{ +void GLES_GPU::BeginDebugDraw() { if (g_Config.bDrawWireframe) { #ifndef USING_GLES2 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -373,23 +352,18 @@ void GLES_GPU::EndDebugDraw() { // Render queue -bool GLES_GPU::ProcessDLQueue() -{ +bool GLES_GPU::ProcessDLQueue() { std::vector::iterator iter = dlQueue.begin(); - while (!(iter == dlQueue.end())) - { + while (!(iter == dlQueue.end())) { DisplayList &l = *iter; dcontext.pc = l.listpc; dcontext.stallAddr = l.stall; // DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr); - if (!InterpretList()) - { + if (!InterpretList()) { l.listpc = dcontext.pc; l.stall = dcontext.stallAddr; return false; - } - else - { + } else { //At the end, we can remove it from the queue and continue dlQueue.erase(iter); //this invalidated the iterator, let's fix it @@ -399,8 +373,7 @@ bool GLES_GPU::ProcessDLQueue() return true; //no more lists! } -u32 GLES_GPU::EnqueueList(u32 listpc, u32 stall) -{ +u32 GLES_GPU::EnqueueList(u32 listpc, u32 stall) { DisplayList dl; dl.id = dlIdGenerator++; dl.listpc = listpc & 0xFFFFFFF; @@ -412,8 +385,7 @@ u32 GLES_GPU::EnqueueList(u32 listpc, u32 stall) return 0; } -void GLES_GPU::UpdateStall(int listid, u32 newstall) -{ +void GLES_GPU::UpdateStall(int listid, u32 newstall) { // this needs improvement.... for (std::vector::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++) { @@ -423,55 +395,23 @@ void GLES_GPU::UpdateStall(int listid, u32 newstall) l.stall = newstall & 0xFFFFFFF; } } - ProcessDLQueue(); } -void GLES_GPU::DrawSync(int mode) -{ - Flush(); +void GLES_GPU::DrawSync(int mode) { + transformDraw_.Flush(); } -void GLES_GPU::Continue() -{ +void GLES_GPU::Continue() { } -void GLES_GPU::Break() -{ +void GLES_GPU::Break() { } -// Just to get something on the screen, we'll just not subdivide correctly. -void GLES_GPU::DrawBezier(int ucount, int vcount) -{ - u16 indices[3 * 3 * 6]; - float customUV[32]; - int c = 0; - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 3; x++) { - indices[c++] = y * 4 + x; - indices[c++] = y * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x; - indices[c++] = y * 4 + x; - } - } - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - customUV[(y * 4 + x) * 2 + 0] = (float)x/3.0f; - customUV[(y * 4 + x) * 2 + 1] = (float)y/3.0f; - } - } - - TransformAndDrawPrim(Memory::GetPointer(gstate_c.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, 3 * 3 * 6, customUV, GE_VTYPE_IDX_16BIT); -} - - -void EnterClearMode(u32 data) -{ +static void EnterClearMode(u32 data) { bool colMask = (data >> 8) & 1; bool alphaMask = (data >> 9) & 1; bool updateZ = (data >> 10) & 1; @@ -479,8 +419,7 @@ void EnterClearMode(u32 data) glstate.depthWrite.set(updateZ ? GL_TRUE : GL_FALSE); } -void LeaveClearMode() -{ +static void LeaveClearMode() { // We have to reset the following state as per the state of the command registers: // Back face culling // Texture map enable (meh) @@ -492,8 +431,7 @@ void LeaveClearMode() // dirtyshader? } -void GLES_GPU::ExecuteOp(u32 op, u32 diff) -{ +void GLES_GPU::ExecuteOp(u32 op, u32 diff) { u32 cmd = op >> 24; u32 data = op & 0xFFFFFF; @@ -553,7 +491,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // Seems we have to advance the vertex addr, at least in some cases. // Question: Should we also advance the index addr? int bytesRead; - TransformAndDrawPrim(verts, inds, type, count, 0, -1, &bytesRead); + transformDraw_.SubmitPrim(verts, inds, type, count, 0, -1, &bytesRead); gstate_c.vertexAddr += bytesRead; } break; @@ -563,7 +501,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; - DrawBezier(bz_ucount, bz_vcount); + transformDraw_.DrawBezier(bz_ucount, bz_vcount); DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); } break; @@ -690,7 +628,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); if (diff & GE_VTYPE_THROUGH) { // Throughmode changed, let's make the proj matrix dirty. - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); + shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); } // This sets through-mode or not, as well. break; @@ -755,25 +693,25 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXSCALEU: gstate_c.uScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); - shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: gstate_c.vScale = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); - shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: gstate_c.uOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); - shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: gstate_c.vOff = getFloat24(data); DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); - shaderManager.DirtyUniform(DIRTY_UVSCALEOFFSET); + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_SCISSOR1: @@ -985,37 +923,37 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_MATERIALAMBIENT: DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); + shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_MATDIFFUSE); + shaderManager_->DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_MATEMISSIVE); + shaderManager_->DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_MATSPECULAR); + shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_MATAMBIENTALPHA); + shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); if (diff) - shaderManager.DirtyUniform(DIRTY_MATSPECULAR); + shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_LIGHTTYPE0: @@ -1037,7 +975,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); gstate_c.lightpos[l][c] = val; if (diff) - shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); + shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -1053,7 +991,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); gstate_c.lightdir[l][c] = val; if (diff) - shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); + shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -1069,7 +1007,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); gstate_c.lightatt[l][c] = val; if (diff) - shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); + shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -1089,7 +1027,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) gstate_c.lightColor[t][l][1] = g; gstate_c.lightColor[t][l][2] = b; if (diff) - shaderManager.DirtyUniform(DIRTY_LIGHT0 << l); + shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } break; @@ -1171,7 +1109,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_ALPHATEST: DEBUG_LOG(G3D,"DL Alpha test settings"); - shaderManager.DirtyUniform(DIRTY_ALPHACOLORREF); + shaderManager_->DirtyUniform(DIRTY_ALPHACOLORREF); break; case GE_CMD_TEXFUNC: @@ -1211,7 +1149,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_TEXENVCOLOR: DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); if (diff) - shaderManager.DirtyUniform(DIRTY_TEXENV); + shaderManager_->DirtyUniform(DIRTY_TEXENV); break; case GE_CMD_TEXMODE: DEBUG_LOG(G3D,"DL TexMode %08x", data); @@ -1278,7 +1216,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) if (num < 12) gstate.worldMatrix[num++] = getFloat24(data); gstate.worldmtxnum = (gstate.worldmtxnum & 0xFF000000) | (num & 0xF); - shaderManager.DirtyUniform(DIRTY_WORLDMATRIX); + shaderManager_->DirtyUniform(DIRTY_WORLDMATRIX); } break; @@ -1294,7 +1232,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) if (num < 12) gstate.viewMatrix[num++] = getFloat24(data); gstate.viewmtxnum = (gstate.viewmtxnum & 0xFF000000) | (num & 0xF); - shaderManager.DirtyUniform(DIRTY_VIEWMATRIX); + shaderManager_->DirtyUniform(DIRTY_VIEWMATRIX); } break; @@ -1310,7 +1248,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) gstate.projMatrix[num++] = getFloat24(data); gstate.projmtxnum = (gstate.projmtxnum & 0xFF000000) | (num & 0xF); } - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); + shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); break; case GE_CMD_TGENMATRIXNUMBER: @@ -1326,7 +1264,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) gstate.tgenMatrix[num++] = getFloat24(data); gstate.texmtxnum = (gstate.texmtxnum & 0xFF000000) | (num & 0xF); } - shaderManager.DirtyUniform(DIRTY_TEXMATRIX); + shaderManager_->DirtyUniform(DIRTY_TEXMATRIX); break; case GE_CMD_BONEMATRIXNUMBER: @@ -1338,7 +1276,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); { int num = gstate.boneMatrixNumber & 0x7F; - shaderManager.DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); + shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); if (num < 96) { gstate.boneMatrix[num++] = getFloat24(data); } @@ -1373,8 +1311,8 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; u32 diff = op ^ gstate.cmdmem[cmd]; - if (flushBeforeCommand[cmd]) - Flush(); + if (flushBeforeCommand_[cmd]) + transformDraw_.Flush(); gstate.cmdmem[cmd] = op; ExecuteOp(op, diff); @@ -1387,9 +1325,9 @@ bool GLES_GPU::InterpretList() void GLES_GPU::UpdateStats() { - gpuStats.numVertexShaders = shaderManager.NumVertexShaders(); - gpuStats.numFragmentShaders = shaderManager.NumFragmentShaders(); - gpuStats.numShaders = shaderManager.NumPrograms(); + gpuStats.numVertexShaders = shaderManager_->NumVertexShaders(); + gpuStats.numFragmentShaders = shaderManager_->NumFragmentShaders(); + gpuStats.numShaders = shaderManager_->NumPrograms(); gpuStats.numTextures = TextureCache_NumLoadedTextures(); } @@ -1443,3 +1381,7 @@ void GLES_GPU::InvalidateCache(u32 addr, int size) else TextureCache_Clear(true); } + +void GLES_GPU::Flush() { + transformDraw_.Flush(); +} diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 425bc999a3..18b75f8d1d 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -23,6 +23,7 @@ #include "../GPUInterface.h" #include "Framebuffer.h" #include "VertexDecoder.h" +#include "TransformPipeline.h" #include "gfx_es2/fbo.h" class ShaderManager; @@ -51,15 +52,8 @@ public: virtual void UpdateStats(); virtual void InvalidateCache(u32 addr, int size); + virtual void Flush(); private: - // TransformPipeline.cpp - void InitTransform(); - void TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead = 0); - //void SoftwareTransformAndDraw(int prim, LinkedShader *program, int forceIndexType, int vertexCount, void *inds, const DecVtxFormat &decVtxFormat, int indexLowerBound, int indexUpperBound, float *customUV); - void ApplyDrawState(); - void Flush(); - void UpdateViewportAndProjection(); - void DrawBezier(int ucount, int vcount); void DoBlockTransfer(); bool ProcessDLQueue(); @@ -68,8 +62,9 @@ private: void EndDebugDraw(); FramebufferManager framebufferManager; - + TransformDrawEngine transformDraw_; ShaderManager *shaderManager_; + bool *flushBeforeCommand_; bool interruptsEnabled_; u32 displayFramebufPtr_; @@ -82,8 +77,7 @@ private: float renderWidthFactor_; float renderHeightFactor_; - struct CmdProcessorState - { + struct CmdProcessorState { u32 pc; u32 stallAddr; }; @@ -92,8 +86,7 @@ private: int dlIdGenerator; - struct DisplayList - { + struct DisplayList { int id; u32 listpc; u32 stall; diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 7b6dcd32b2..1ea3b7cc26 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -3,6 +3,7 @@ #include "../Math3D.h" #include "../GPUState.h" +#include "../../Core/System.h" #include "../ge_constants.h" #include "DisplayListInterpreter.h" #include "ShaderManager.h" @@ -59,7 +60,7 @@ const GLuint ztests[] = GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL, }; -void GLES_GPU::ApplyDrawState() +void ApplyDrawState() { // TODO: All this setup is soon so expensive that we'll need dirty flags, or simply do it in the command writes where we detect dirty by xoring. Silly to do all this work on every drawcall. @@ -71,7 +72,7 @@ void GLES_GPU::ApplyDrawState() bool wantCull = !gstate.isModeClear() && !gstate.isModeThrough() && gstate.isCullEnabled(); glstate.cullFace.set(wantCull); - if(wantCull) { + if (wantCull) { u8 cullMode = gstate.getCullMode(); glstate.cullFaceMode.set(cullingMode[cullMode]); } @@ -162,8 +163,11 @@ void GLES_GPU::ApplyDrawState() glstate.depthRange.set(depthRangeMin, depthRangeMax); } -void GLES_GPU::UpdateViewportAndProjection() -{ +void UpdateViewportAndProjection() { + int renderWidth = PSP_CoreParameter().renderWidth; + int renderHeight = PSP_CoreParameter().renderHeight; + float renderWidthFactor = (float)renderWidth / 480.0f; + float renderHeightFactor = (float)renderHeight / 272.0f; bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; // We can probably use these to simply set scissors? Maybe we need to offset by regionX1/Y1 @@ -178,7 +182,7 @@ void GLES_GPU::UpdateViewportAndProjection() if (throughmode) { // No viewport transform here. Let's experiment with using region. return; - glViewport((0 + regionX1) * renderWidthFactor_, (0 - regionY1) * renderHeightFactor_, (regionX2 - regionX1) * renderWidthFactor_, (regionY2 - regionY1) * renderHeightFactor_); + glViewport((0 + regionX1) * renderWidthFactor, (0 - regionY1) * renderHeightFactor, (regionX2 - regionX1) * renderWidthFactor, (regionY2 - regionY1) * renderHeightFactor); } else { // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. float vpXa = getFloat24(gstate.viewportx1); @@ -208,15 +212,15 @@ void GLES_GPU::UpdateViewportAndProjection() float vpZ0 = (vpZb - vpZa) / 65536.0f; float vpZ1 = (vpZa * 2) / 65536.0f; - vpX0 *= renderWidthFactor_; - vpY0 *= renderHeightFactor_; - vpWidth *= renderWidthFactor_; - vpHeight *= renderHeightFactor_; + vpX0 *= renderWidthFactor; + vpY0 *= renderHeightFactor; + vpWidth *= renderWidthFactor; + vpHeight *= renderHeightFactor; // Flip vpY0 to match the OpenGL coordinate system. - vpY0 = renderHeight_ - (vpY0 + vpHeight); + vpY0 = renderHeight - (vpY0 + vpHeight); glViewport(vpX0, vpY0, vpWidth, vpHeight); // Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh. - shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); + // shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); } } diff --git a/GPU/GLES/StateMapping.h b/GPU/GLES/StateMapping.h index f6251f5b53..7532a3f3d4 100644 --- a/GPU/GLES/StateMapping.h +++ b/GPU/GLES/StateMapping.h @@ -5,3 +5,8 @@ extern const GLint bLookup[]; extern const GLint eqLookup[]; extern const GLint cullingMode[]; extern const GLuint ztests[]; + + +void ApplyDrawState(); +void UpdateViewportAndProjection(); + diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index bece8c27e8..7605e4a417 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -30,7 +30,6 @@ #include "VertexDecoder.h" #include "ShaderManager.h" #include "DisplayListInterpreter.h" -#include "IndexGenerator.h" const GLuint glprim[8] = { GL_POINTS, @@ -45,15 +44,44 @@ const GLuint glprim[8] = { u8 decoded[65536 * 32]; VertexDecoder dec; uint16_t decIndex[65536]; -int numVerts; - -IndexGenerator indexGen; TransformedVertex transformed[65536]; TransformedVertex transformedExpanded[65536]; +TransformDrawEngine::TransformDrawEngine(ShaderManager *shaderManager) + : numVerts(0), + shaderManager_(shaderManager) { + indexGen.Setup(decIndex); +} -// TODO: This should really return 2 colors, one for specular and one for diffuse. +TransformDrawEngine::~TransformDrawEngine() { +} + +// Just to get something on the screen, we'll just not subdivide correctly. +void TransformDrawEngine::DrawBezier(int ucount, int vcount) { + u16 indices[3 * 3 * 6]; + float customUV[32]; + int c = 0; + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + indices[c++] = y * 4 + x; + indices[c++] = y * 4 + x + 1; + indices[c++] = (y + 1) * 4 + x + 1; + indices[c++] = (y + 1) * 4 + x + 1; + indices[c++] = (y + 1) * 4 + x; + indices[c++] = y * 4 + x; + } + } + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + customUV[(y * 4 + x) * 2 + 0] = (float)x/3.0f; + customUV[(y * 4 + x) * 2 + 1] = (float)y/3.0f; + } + } + + SubmitPrim(Memory::GetPointer(gstate_c.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, 3 * 3 * 6, customUV, GE_VTYPE_IDX_16BIT, 0); +} // Convenient way to do precomputation to save the parts of the lighting calculation // that's common between the many vertices of a draw call. @@ -295,7 +323,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, VertexReader reader(decoded, decVtxFormat); for (int index = 0; index < maxIndex; index++) - { + { reader.Goto(index); float v[3] = {0, 0, 0}; @@ -365,7 +393,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, } } } - + // Yes, we really must multiply by the world matrix too. Vec3ByMatrix43(out, psum.v, gstate.worldMatrix); if (reader.hasNormal()) { @@ -574,12 +602,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } -void GLES_GPU::InitTransform() { - indexGen.Setup(decIndex); - numVerts = 0; -} - -void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) +void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { // For the future if (!indexGen.PrimCompatible(prim)) @@ -642,8 +665,7 @@ void GLES_GPU::TransformAndDrawPrim(void *verts, void *inds, int prim, int verte } } -void GLES_GPU::Flush() -{ +void TransformDrawEngine::Flush() { if (indexGen.Empty()) return; // From here on out, the index type is ALWAYS 16-bit. Deal with it. @@ -660,10 +682,8 @@ void GLES_GPU::Flush() } #endif // Check if anything needs updating - if (gstate_c.textureChanged) - { - if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) - { + if (gstate_c.textureChanged) { + if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) { PSPSetTexture(); } gstate_c.textureChanged = false; diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 4c89dfcda3..acc0dd307f 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -17,52 +17,68 @@ #pragma once +#include "IndexGenerator.h" + class LinkedShader; +class ShaderManager; struct DecVtxFormat; +// Handles transform, lighting and drawing. +class TransformDrawEngine { +public: + TransformDrawEngine(ShaderManager *shaderManager); + ~TransformDrawEngine(); + void SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead); + void DrawBezier(int ucount, int vcount); + void Flush(); + +private: + // Vertex collector state + IndexGenerator indexGen; + int numVerts; + + // Vertex collector buffers + + // Other + ShaderManager *shaderManager_; +}; + +// void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV); + // Only used by SW transform -struct Color4 -{ - float r,g,b,a; +struct Color4 { + float r, g, b, a; + Color4() : r(0), g(0), b(0), a(0) { } Color4(float _r, float _g, float _b, float _a=1.0f) - { - r=_r; g=_g; b=_b; a=_a; + : r(_r), g(_g), b(_b), a(_a) { } Color4(const float in[4]) {r=in[0];g=in[1];b=in[2];a=in[3];} Color4(const float in[3], float alpha) {r=in[0];g=in[1];b=in[2];a=alpha;} const float &operator [](int i) const {return *(&r + i);} - Color4 operator *(float f) const - { + Color4 operator *(float f) const { return Color4(f*r,f*g,f*b,f*a); } - Color4 operator *(const Color4 &c) const - { + Color4 operator *(const Color4 &c) const { return Color4(r*c.r,g*c.g,b*c.b,a*c.a); } - Color4 operator +(const Color4 &c) const - { + Color4 operator +(const Color4 &c) const { return Color4(r+c.r,g+c.g,b+c.b,a+c.a); } - void operator +=(const Color4 &c) - { + void operator +=(const Color4 &c) { r+=c.r; g+=c.g; b+=c.b; a+=c.a; } - void GetFromRGB(u32 col) - { + void GetFromRGB(u32 col) { r = ((col>>16) & 0xff)/255.0f; g = ((col>>8) & 0xff)/255.0f; b = ((col>>0) & 0xff)/255.0f; } - void GetFromA(u32 col) - { + void GetFromA(u32 col) { a = (col&0xff)/255.0f; } }; - -// void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 09773f7cf2..2198b782ab 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -33,7 +33,7 @@ public: virtual void UpdateStall(int listid, u32 newstall) = 0; virtual void DrawSync(int mode) = 0; virtual void Continue() = 0; - + virtual void ExecuteOp(u32 op, u32 diff) = 0; virtual bool InterpretList() = 0; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 2f60deb5d6..6540620a36 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -37,7 +37,7 @@ void InitGfxState() gstate.lightingEnable = 0x17000001; - static const float identity4x3[12] = + static const float identity4x3[12] = {1,0,0, 0,1,0, 0,0,1, @@ -78,7 +78,6 @@ void ReapplyGfxState() { if (!gpu) return; - gpu->Flush(); // ShaderManager_DirtyShader(); // The commands are embedded in the command memory so we can just reexecute the words. Convenient. // To be safe we pass 0xFFFFFFF as the diff. @@ -96,9 +95,9 @@ void ReapplyGfxState() for (int i = GE_CMD_VERTEXTYPE; i < GE_CMD_BONEMATRIXNUMBER; i++) { - gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); + gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); } - + // Can't write to bonematrixnumber here for (int i = GE_CMD_MORPHWEIGHT0; i < GE_CMD_PATCHFACING; i++) From 9dce8b09a4ac410c78aceef7cd38e1dec65f9b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 13:56:30 +0100 Subject: [PATCH 185/276] Move vertex arrays from globals to heap. --- GPU/GLES/TransformPipeline.cpp | 24 +++++++++++++----------- GPU/GLES/TransformPipeline.h | 9 +++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 7605e4a417..4fd4f42905 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -41,20 +41,22 @@ const GLuint glprim[8] = { GL_TRIANGLES, // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? }; -u8 decoded[65536 * 32]; -VertexDecoder dec; -uint16_t decIndex[65536]; - -TransformedVertex transformed[65536]; -TransformedVertex transformedExpanded[65536]; - TransformDrawEngine::TransformDrawEngine(ShaderManager *shaderManager) : numVerts(0), shaderManager_(shaderManager) { + decoded = new u8[65536 * 48]; + decIndex = new u16[65536]; + transformed = new TransformedVertex[65536]; + transformedExpanded = new TransformedVertex[65536 * 3]; + indexGen.Setup(decIndex); } TransformDrawEngine::~TransformDrawEngine() { + delete [] decoded; + delete [] decIndex; + delete [] transformed; + delete [] transformedExpanded; } // Just to get something on the screen, we'll just not subdivide correctly. @@ -295,7 +297,8 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. -void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) +void TransformDrawEngine::SoftwareTransformAndDraw( + int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { /* DEBUG_LOG(G3D, "View matrix:"); @@ -322,8 +325,7 @@ void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, Lighter lighter; VertexReader reader(decoded, decVtxFormat); - for (int index = 0; index < maxIndex; index++) - { + for (int index = 0; index < maxIndex; index++) { reader.Goto(index); float v[3] = {0, 0, 0}; @@ -707,7 +709,7 @@ void TransformDrawEngine::Flush() { glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { - SoftwareTransformAndDraw(prim, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), + SoftwareTransformAndDraw(prim, decoded, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), indexGen.MaxIndex()); } diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index acc0dd307f..e353fd0d66 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -18,6 +18,7 @@ #pragma once #include "IndexGenerator.h" +#include "VertexDecoder.h" class LinkedShader; class ShaderManager; @@ -33,11 +34,19 @@ public: void Flush(); private: + void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); + // Vertex collector state IndexGenerator indexGen; int numVerts; // Vertex collector buffers + VertexDecoder dec; + u8 *decoded; + u16 *decIndex; + + TransformedVertex *transformed; + TransformedVertex *transformedExpanded; // Other ShaderManager *shaderManager_; From 7c64f9c61e213ca37113917b67cfecb345690035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 14:09:22 +0100 Subject: [PATCH 186/276] Tiny optimization - only init the vertex decoder on vertex type change --- GPU/GLES/TransformPipeline.cpp | 10 ++++++++-- GPU/GLES/TransformPipeline.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 4fd4f42905..5c0178dfa7 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -43,6 +43,7 @@ const GLuint glprim[8] = { TransformDrawEngine::TransformDrawEngine(ShaderManager *shaderManager) : numVerts(0), + lastVType(-1), shaderManager_(shaderManager) { decoded = new u8[65536 * 48]; decIndex = new u16[65536]; @@ -618,8 +619,13 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert indexGen.SetIndex(numVerts); int indexLowerBound, indexUpperBound; - // First, decode the verts and apply morphing - dec.SetVertexType(gstate.vertType); + // If vtype has changed, setup the vertex decoder. + // TODO: Simply cache the setup decoders instead. + if (gstate.vertType != lastVType) { + dec.SetVertexType(gstate.vertType); + lastVType = gstate.vertType; + } + // Decode the verts and apply morphing dec.DecodeVerts(decoded + numVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); numVerts += indexUpperBound - indexLowerBound + 1; diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index e353fd0d66..9e95457c7e 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -42,12 +42,13 @@ private: // Vertex collector buffers VertexDecoder dec; + u32 lastVType; u8 *decoded; u16 *decIndex; TransformedVertex *transformed; TransformedVertex *transformedExpanded; - + // Other ShaderManager *shaderManager_; }; From d95dbca9bef2b7b919bd5cfa68499b5906ab5dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 15:28:34 +0100 Subject: [PATCH 187/276] Cleanup GPU init/shutdown a bit --- CMakeLists.txt | 2 - Core/HLE/sceDisplay.cpp | 122 +-- Core/HLE/sceDisplay.h | 1 + Core/HLE/sceKernel.cpp | 1 + Core/HLE/sceUtility.cpp | 14 +- Core/System.cpp | 5 - GPU/GLES/DisplayListInterpreter.cpp | 23 +- GPU/GLES/DisplayListInterpreter.h | 1 + GPU/GLES/TransformPipeline.cpp | 4 +- GPU/GLES/TransformPipeline.h | 5 +- GPU/GPUInterface.h | 1 + GPU/GPUState.cpp | 4 +- GPU/Null/NullDisplayListInterpreter.cpp | 997 ------------------------ GPU/Null/NullDisplayListInterpreter.h | 31 - GPU/Null/NullGpu.h | 2 + android/jni/EmuScreen.cpp | 8 +- 16 files changed, 80 insertions(+), 1141 deletions(-) delete mode 100644 GPU/Null/NullDisplayListInterpreter.cpp delete mode 100644 GPU/Null/NullDisplayListInterpreter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 51caab7186..d5ce06a75f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -806,8 +806,6 @@ add_library(GPU OBJECT GPU/GPUState.h GPU/Math3D.cpp GPU/Math3D.h -# GPU/Null/NullDisplayListInterpreter.cpp -# GPU/Null/NullDisplayListInterpreter.h GPU/Null/NullGpu.cpp GPU/Null/NullGpu.h GPU/ge_constants.h) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index cf28865a48..d8d323cc58 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -46,10 +46,7 @@ // Internal drawing library #include "../Util/PPGeDraw.h" -extern ShaderManager shaderManager; - -struct FrameBufferState -{ +struct FrameBufferState { u32 topaddr; PspDisplayPixelFormat pspFramebufFormat; int pspFramebufLinesize; @@ -95,8 +92,7 @@ std::vector vblankWaitingThreads; void hleEnterVblank(u64 userdata, int cyclesLate); void hleLeaveVblank(u64 userdata, int cyclesLate); -void __DisplayInit() -{ +void __DisplayInit() { gpuStats.reset(); hasSetMode = false; framebufIsLatched = false; @@ -118,29 +114,24 @@ void __DisplayInit() InitGfxState(); } -void __DisplayShutdown() -{ +void __DisplayShutdown() { vblankListeners.clear(); vblankWaitingThreads.clear(); ShutdownGfxState(); } -void __DisplayListenVblank(VblankCallback callback) -{ +void __DisplayListenVblank(VblankCallback callback) { vblankListeners.push_back(callback); } -void __DisplayFireVblank() -{ - for (std::vector::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) - { +void __DisplayFireVblank() { + for (std::vector::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) { VblankCallback cb = *iter; cb(); } } -void hleEnterVblank(u64 userdata, int cyclesLate) -{ +void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(HLE, "Enter VBlank %i", vbCount); @@ -162,8 +153,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); // TODO: Should this be done here or in hleLeaveVblank? - if (framebufIsLatched) - { + if (framebufIsLatched) { DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; @@ -181,8 +171,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. // Here we will be drawing to the non buffered front surface. - if (g_Config.bShowDebugStats) - { + if (g_Config.bShowDebugStats) { gpu->UpdateStats(); char stats[512]; sprintf(stats, @@ -205,12 +194,12 @@ void hleEnterVblank(u64 userdata, int cyclesLate) gpuStats.numFragmentShaders, gpuStats.numShaders ); - + float zoom = 0.7f; /// g_Config.iWindowZoom; PPGeBegin(); PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFc0c0c0); PPGeEnd(); - + gpuStats.resetFrame(); } @@ -240,9 +229,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) 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. #ifndef _WIN32 @@ -250,9 +236,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) #endif } - -void hleLeaveVblank(u64 userdata, int cyclesLate) -{ +void hleLeaveVblank(u64 userdata, int cyclesLate) { isVblank = 0; DEBUG_LOG(HLE,"Leave VBlank %i", (int)userdata - 1); vCount++; @@ -260,19 +244,16 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata); } -void sceDisplayIsVblank() -{ +void sceDisplayIsVblank() { DEBUG_LOG(HLE,"%i=sceDisplayIsVblank()",isVblank); RETURN(isVblank); } -u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) -{ +u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) { DEBUG_LOG(HLE,"sceDisplaySetMode(%d,%d,%d)",unknown,xres,yres); host->BeginFrame(); - if (!hasSetMode) - { + if (!hasSetMode) { gpu->InitClear(); hasSetMode = true; } @@ -280,9 +261,7 @@ u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) return 0; } -u32 sceDisplaySetFramebuf() -{ - //host->EndFrame(); +u32 sceDisplaySetFramebuf() { u32 topaddr = PARAM(0); int linesize = PARAM(1); int pixelformat = PARAM(2); @@ -290,19 +269,15 @@ u32 sceDisplaySetFramebuf() FrameBufferState fbstate; DEBUG_LOG(HLE,"sceDisplaySetFramebuf(topaddr=%08x,linesize=%d,pixelsize=%d,sync=%d)",topaddr,linesize,pixelformat,sync); - if (topaddr == 0) - { + if (topaddr == 0) { DEBUG_LOG(HLE,"- screen off"); - } - else - { + } else { fbstate.topaddr = topaddr; fbstate.pspFramebufFormat = (PspDisplayPixelFormat)pixelformat; fbstate.pspFramebufLinesize = linesize; } - if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) - { + if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { // Write immediately to the current framebuffer parameters if (topaddr != 0) { @@ -311,9 +286,7 @@ u32 sceDisplaySetFramebuf() } else WARN_LOG(HLE, "%s: PSP_DISPLAY_SETBUF_IMMEDIATE without topaddr?", __FUNCTION__); - } - else if (topaddr != 0) - { + } else if (topaddr != 0) { // Delay the write until vblank latchedFramebuf = fbstate; framebufIsLatched = true; @@ -321,12 +294,11 @@ u32 sceDisplaySetFramebuf() return 0; } -u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) -{ +u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) { const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf; DEBUG_LOG(HLE,"sceDisplayGetFramebuf(*%08x = %08x, *%08x = %08x, *%08x = %08x, %i)", topaddrPtr, fbState.topaddr, linesizePtr, fbState.pspFramebufLinesize, pixelFormatPtr, fbState.pspFramebufFormat, mode); - + if (Memory::IsValidAddress(topaddrPtr)) Memory::Write_U32(fbState.topaddr, topaddrPtr); if (Memory::IsValidAddress(linesizePtr)) @@ -337,52 +309,45 @@ u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, i return 0; } -void sceDisplayWaitVblankStart() -{ +void sceDisplayWaitVblankStart() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStart()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblank() -{ +void sceDisplayWaitVblank() { DEBUG_LOG(HLE,"sceDisplayWaitVblank()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblankStartMulti() -{ +void sceDisplayWaitVblankStartMulti() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMulti()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblankCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); +void sceDisplayWaitVblankCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -void sceDisplayWaitVblankStartCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()"); +void sceDisplayWaitVblankStartCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -void sceDisplayWaitVblankStartMultiCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()"); +void sceDisplayWaitVblankStartMultiCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -u32 sceDisplayGetVcount() -{ +u32 sceDisplayGetVcount() { // Too spammy - // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); + // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); // Puyo Puyo Fever polls this as a substitute for waiting for vblank. // As a result, the game never gets to reschedule so it doesn't mix audio and things break. @@ -393,29 +358,24 @@ u32 sceDisplayGetVcount() return vCount; } -void sceDisplayGetCurrentHcount() -{ +void sceDisplayGetCurrentHcount() { RETURN(hCount++); } - -void sceDisplayGetAccumulatedHcount() -{ +void sceDisplayGetAccumulatedHcount() { // Just do an estimate u32 accumHCount = CoreTiming::GetTicks() / (222000000 / 60 / 272); - DEBUG_LOG(HLE,"%i=sceDisplayGetAccumulatedHcount()", accumHCount); + DEBUG_LOG(HLE,"%i=sceDisplayGetAccumulatedHcount()", accumHCount); RETURN(accumHCount); } -float sceDisplayGetFramePerSec() -{ +float sceDisplayGetFramePerSec() { float fps = 59.9400599f; DEBUG_LOG(HLE,"%f=sceDisplayGetFramePerSec()", fps); - return fps; // (9MHz * 1)/(525 * 286) + return fps; // (9MHz * 1)/(525 * 286) } -const HLEFunction sceDisplay[] = -{ +const HLEFunction sceDisplay[] = { {0x0E20F177,WrapU_UUU, "sceDisplaySetMode"}, {0x289D82FE,WrapU_V, "sceDisplaySetFramebuf"}, {0xEEDA2E54,WrapU_UUUI,"sceDisplayGetFrameBuf"}, @@ -435,10 +395,8 @@ const HLEFunction sceDisplay[] = {0xB4F378FA,0,"sceDisplayIsForeground"}, {0x31C4BAA8,0,"sceDisplayGetBrightness"}, {0x4D4E10EC,sceDisplayIsVblank,"sceDisplayIsVblank"}, - }; -void Register_sceDisplay() -{ +void Register_sceDisplay() { RegisterModule("sceDisplay", ARRAY_SIZE(sceDisplay), sceDisplay); } diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index 003b3164b9..c7b1afc8ff 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -18,6 +18,7 @@ #pragma once void __DisplayInit(); +void __DisplayShutdown(); void Register_sceDisplay(); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 3197c11107..27d8464fb4 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -122,6 +122,7 @@ void __KernelShutdown() __UtilityShutdown(); __GeShutdown(); __SasShutdown(); + __DisplayShutdown(); __AudioShutdown(); __IoShutdown(); __InterruptsShutdown(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 0d2340e0da..bebd56436d 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -103,7 +103,7 @@ int sceUtilityMsgDialogInitStart(u32 structAddr) int sceUtilityMsgDialogShutdownStart(u32 unknown) { - DEBUG_LOG(HLE,"FAKE sceUtilityMsgDialogShutdownStart(%i)", unknown); + DEBUG_LOG(HLE,"sceUtilityMsgDialogShutdownStart(%i)", unknown); return msgDialog.Shutdown(); } @@ -124,25 +124,25 @@ int sceUtilityMsgDialogGetStatus() int sceUtilityOskInitStart(u32 oskPtr) { - ERROR_LOG(HLE,"FAKE sceUtilityOskInitStart(%i)", PARAM(0)); + DEBUG_LOG(HLE,"sceUtilityOskInitStart(%i)", PARAM(0)); return oskDialog.Init(oskPtr); } int sceUtilityOskShutdownStart() { - ERROR_LOG(HLE,"FAKE sceUtilityOskShutdownStart(%i)", PARAM(0)); + DEBUG_LOG(HLE,"sceUtilityOskShutdownStart(%i)", PARAM(0)); return oskDialog.Shutdown(); } int sceUtilityOskUpdate(unsigned int unknown) { - ERROR_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); + DEBUG_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); return oskDialog.Update(); } int sceUtilityOskGetStatus() { - int status = oskDialog.GetStatus(); + int status = oskDialog.GetStatus(); // Seems that 4 is the cancelled status for OSK? if (status == 4) { @@ -185,13 +185,13 @@ int sceUtilityScreenshotGetStatus() void sceUtilityGamedataInstallInitStart(u32 unkown) { - DEBUG_LOG(HLE,"FAKE sceUtilityGamedataInstallInitStart(%i)", unkown); + DEBUG_LOG(HLE,"UNIMPL sceUtilityGamedataInstallInitStart(%i)", unkown); } int sceUtilityGamedataInstallGetStatus() { u32 retval = 0;//__UtilityGetStatus(); - DEBUG_LOG(HLE,"%i=sceUtilityGamedataInstallGetStatus()", retval); + DEBUG_LOG(HLE,"UNIMPL %i=sceUtilityGamedataInstallGetStatus()", retval); return retval; } diff --git a/Core/System.cpp b/Core/System.cpp index 18c2b94687..9110dcc245 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -42,7 +42,6 @@ MetaFileSystem pspFileSystem; static CoreParameter coreParameter; -extern ShaderManager shaderManager; bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { @@ -76,9 +75,6 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) return false; } - shaderManager.DirtyShader(); - shaderManager.DirtyUniform(DIRTY_ALL); - // Setup JIT here. if (coreParameter.startPaused) coreState = CORE_STEPPING; @@ -97,7 +93,6 @@ void PSP_Shutdown() pspFileSystem.UnmountAll(); TextureCache_Clear(true); - shaderManager.ClearCache(true); CoreTiming::ClearPendingEvents(); CoreTiming::UnregisterAllEvents(); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 226e091540..bf70ae40e2 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -33,8 +33,6 @@ #include "../../Core/HLE/sceKernelThread.h" #include "../../Core/HLE/sceKernelInterrupt.h" -ShaderManager shaderManager; - extern u32 curTextureWidth; extern u32 curTextureHeight; @@ -157,11 +155,11 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1), - transformDraw_(&shaderManager) { + dlIdGenerator(1) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; - shaderManager_ = &shaderManager; + shaderManager_ = new ShaderManager(); + transformDraw_.SetShaderManager(shaderManager_); TextureCache_Init(); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -183,10 +181,18 @@ GLES_GPU::~GLES_GPU() { delete (*iter); } vfbs_.clear(); - + shaderManager_->ClearCache(true); + delete shaderManager_; delete [] flushBeforeCommand_; } +void GLES_GPU::DeviceLost() { + // Simply drop all caches and textures. + // FBO:s appear to survive? Or no? + shaderManager_->ClearCache(false); + TextureCache_Clear(false); +} + void GLES_GPU::InitClear() { if (!g_Config.bBufferedRendering) { glClearColor(0,0,0,1); @@ -199,6 +205,11 @@ void GLES_GPU::InitClear() { void GLES_GPU::BeginFrame() { TextureCache_Decimate(); + shaderManager_->DirtyShader(); + + // Not sure if this is really needed. + shaderManager_->DirtyUniform(DIRTY_ALL); + // NOTE - this is all wrong. At the beginning of the frame is a TERRIBLE time to draw the fb. if (g_Config.bDisplayFramebuffer && displayFramebufPtr_) { INFO_LOG(HLE, "Drawing the framebuffer"); diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 18b75f8d1d..9d9a7f8733 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -51,6 +51,7 @@ public: virtual void BeginFrame(); virtual void UpdateStats(); virtual void InvalidateCache(u32 addr, int size); + virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders. virtual void Flush(); private: diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 5c0178dfa7..63df7e64b6 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -41,10 +41,10 @@ const GLuint glprim[8] = { GL_TRIANGLES, // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? }; -TransformDrawEngine::TransformDrawEngine(ShaderManager *shaderManager) +TransformDrawEngine::TransformDrawEngine() : numVerts(0), lastVType(-1), - shaderManager_(shaderManager) { + shaderManager_(0) { decoded = new u8[65536 * 48]; decIndex = new u16[65536]; transformed = new TransformedVertex[65536]; diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 9e95457c7e..393f0dce12 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -27,11 +27,14 @@ struct DecVtxFormat; // Handles transform, lighting and drawing. class TransformDrawEngine { public: - TransformDrawEngine(ShaderManager *shaderManager); + TransformDrawEngine(); ~TransformDrawEngine(); void SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead); void DrawBezier(int ucount, int vcount); void Flush(); + void SetShaderManager(ShaderManager *shaderManager) { + shaderManager_ = shaderManager; + } private: void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 2198b782ab..cad06fe3bf 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -52,5 +52,6 @@ public: // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; + virtual void DeviceLost() = 0; virtual void Flush() = 0; }; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 6540620a36..c45d65ae88 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -102,14 +102,14 @@ void ReapplyGfxState() for (int i = GE_CMD_MORPHWEIGHT0; i < GE_CMD_PATCHFACING; i++) { - gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); + gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); } // There are a few here in the middle that we shouldn't execute... for (int i = GE_CMD_VIEWPORTX1; i < GE_CMD_TRANSFERSTART; i++) { - gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); + gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); } // TODO: there's more... diff --git a/GPU/Null/NullDisplayListInterpreter.cpp b/GPU/Null/NullDisplayListInterpreter.cpp deleted file mode 100644 index ef00c7a373..0000000000 --- a/GPU/Null/NullDisplayListInterpreter.cpp +++ /dev/null @@ -1,997 +0,0 @@ -// 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 "../../Core/MemMap.h" -#include "../../Core/Host.h" - -#include "../GPUState.h" -#include "../ge_constants.h" - -#include "ShaderManager.h" -#include "DisplayListInterpreter.h" -#include "TransformPipeline.h" - -#include "../../Core/HLE/sceKernelThread.h" -#include "../../Core/HLE/sceKernelInterrupt.h" - -inline void glEnDis(GLuint cmd, int value) -{ - (value ? glEnable : glDisable)(cmd); -} - -struct DisplayState -{ - u32 pc; - u32 stallAddr; -}; - -static DisplayState dcontext; -ShaderManager shaderManager; - -extern u32 curTextureWidth; -extern u32 curTextureHeight; - -int dlIdGenerator = 1; - -struct DisplayList -{ - int id; - u32 listpc; - u32 stall; -}; - -std::vector dlQueue; - -static u32 prev; -u32 stack[2]; -u32 stackptr = 0; -bool finished; - -u8 bezierBuf[16000]; - -bool ProcessDLQueue() -{ - std::vector::iterator iter = dlQueue.begin(); - while (!(iter == dlQueue.end())) - { - DisplayList &l = *iter; - dcontext.pc = l.listpc; - dcontext.stallAddr = l.stall; -// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr); - if (!GPU::InterpretList()) - { - l.listpc = dcontext.pc; - l.stall = dcontext.stallAddr; - return false; - } - else - { - //At the end, we can remove it from the queue and continue - dlQueue.erase(iter); - //this invalidated the iterator, let's fix it - iter = dlQueue.begin(); - } - } - return true; //no more lists! -} - -u32 GPU::EnqueueList(u32 listpc, u32 stall) -{ - DisplayList dl; - dl.id = dlIdGenerator++; - dl.listpc = listpc&0xFFFFFFF; - dl.stall = stall&0xFFFFFFF; - dlQueue.push_back(dl); - if (!ProcessDLQueue()) - return dl.id; - else - return 0; -} - -void GPU::UpdateStall(int listid, u32 newstall) -{ - // this needs improvement.... - for (std::vector::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++) - { - DisplayList &l = *iter; - if (l.id == listid) - { - l.stall = newstall & 0xFFFFFFF; - } - } - - ProcessDLQueue(); -} - -// Just to get something on the screen, we'll just not subdivide correctly. -void drawBezier(int ucount, int vcount) -{ - u16 indices[3 * 3 * 6]; - float customUV[32]; - int c = 0; - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 3; x++) { - indices[c++] = y * 4 + x; - indices[c++] = y * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x; - indices[c++] = y * 4 + x; - } - } - - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - customUV[(y * 4 + x) * 2 + 0] = (float)x/3.0f; - customUV[(y * 4 + x) * 2 + 1] = (float)y/3.0f; - } - } - - LinkedShader *linkedShader = shaderManager.ApplyShader(); - TransformAndDrawPrim(Memory::GetPointer(gstate.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, 3 * 3 * 6, linkedShader, customUV, GE_VTYPE_IDX_16BIT); -} - - -void EnterClearMode(u32 data) -{ - bool colMask = (data >> 8) & 1; - bool alphaMask = (data >> 9) & 1; - bool updateZ = (data >> 10) & 1; - glColorMask(colMask, colMask, colMask, alphaMask); - glDepthMask(updateZ); // Update Z or not - // Note that depth test must be enabled for depth writes to go through! So we use GL_ALWAYS - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glDisable(GL_CULL_FACE); // ?? -} - -void LeaveClearMode() -{ - // We have to reset the following state as per the state of the command registers: - // Back face culling - // Texture map enable (meh) - // Fogging - // Antialiasing - // Alpha test - glDepthMask(1); - glColorMask(1,1,1,1); - glEnDis(GL_DEPTH_TEST, gstate.zTestEnable & 1); - glDepthFunc(GL_LEQUAL); // TODO - - // dirtyshader? -} - -void SetBlendModePSP(u32 data) -{ - // This can't be done exactly as there are several PSP blend modes that are impossible to do on OpenGL ES 2.0, and some even on regular OpenGL for desktop. - - // HOWEVER - we should be able to approximate the 2x modes in the shader, although they will clip wrongly. - - const GLint aLookup[] = { - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_SRC_ALPHA, // should be 2x - GL_ONE_MINUS_SRC_ALPHA, // should be 2x - GL_DST_ALPHA, // should be 2x - GL_ONE_MINUS_DST_ALPHA, // should be 2x - and COLOR? - GL_SRC_ALPHA, // should be FIXA - }; - const GLint bLookup[] = { - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_SRC_ALPHA, // should be 2x - GL_ONE_MINUS_SRC_ALPHA, // should be 2x - GL_DST_ALPHA, // should be 2x - GL_ONE_MINUS_DST_ALPHA, // should be 2x - GL_SRC_ALPHA, // should be FIXB - }; - const GLint eqLookup[] = { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, -#if defined(USING_GLES2) - GL_FUNC_ADD, - GL_FUNC_ADD, -#else - GL_MIN, - GL_MAX, -#endif - GL_FUNC_ADD, // should be abs(diff) - }; - int a = data & 0xF; - int b = (data >> 4) & 0xF; - int eq = (data >> 8) & 0x7; - glBlendFunc(aLookup[a], bLookup[b]); - glBlendEquation(eqLookup[eq]); -} - - -void GPU::ExecuteOp(u32 op, u32 diff) -{ - u32 cmd = op >> 24; - u32 data = op & 0xFFFFFF; - - // Handle control and drawing commands here directly. The others we delegate. - switch (cmd) - { - case GE_CMD_BASE: - DEBUG_LOG(G3D,"DL BASE: %06x", data); - break; - - case GE_CMD_VADDR: /// <<8???? - gstate.vertexAddr = (gstate.base<<8)|data; - DEBUG_LOG(G3D,"DL VADDR: %06x", gstate.vertexAddr); - break; - - case GE_CMD_IADDR: - gstate.indexAddr = (gstate.base<<8)|data; - DEBUG_LOG(G3D,"DL IADDR: %06x", gstate.indexAddr); - break; - - case GE_CMD_PRIM: - { - u32 count = data & 0xFFFF; - u32 type = data >> 16; - static const char* types[7] = { - "POINTS=0,", - "LINES=1,", - "LINE_STRIP=2,", - "TRIANGLES=3,", - "TRIANGLE_STRIP=4,", - "TRIANGLE_FAN=5,", - "RECTANGLES=6,", - }; - DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate.vertexAddr, gstate.indexAddr); - - LinkedShader *linkedShader = shaderManager.ApplyShader(); - // TODO: Split this so that we can collect sequences of primitives, can greatly speed things up - // on platforms where draw calls are expensive like mobile and D3D - void *verts = Memory::GetPointer(gstate.vertexAddr); - void *inds = 0; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) - inds = Memory::GetPointer(gstate.indexAddr); - TransformAndDrawPrim(verts, inds, type, count, linkedShader); - } - break; - - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. - case GE_CMD_BEZIER: - { - int bz_ucount = data & 0xFF; - int bz_vcount = (data >> 8) & 0xFF; - drawBezier(bz_ucount, bz_vcount); - DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); - } - break; - - case GE_CMD_SPLINE: - { - int sp_ucount = data & 0xFF; - int sp_vcount = (data >> 8) & 0xFF; - int sp_utype = (data >> 16) & 0x3; - int sp_vtype = (data >> 18) & 0x3; - //drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); - DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); - } - break; - - case GE_CMD_JUMP: - { - u32 target = ((gstate.base << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; - DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target); - dcontext.pc = target - 4; // pc will be increased after we return, counteract that - } - break; - - case GE_CMD_CALL: - { - u32 retval = dcontext.pc + 4; - stack[stackptr++] = retval; - u32 target = ((gstate.base << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF; - DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval); - dcontext.pc = target - 4; // pc will be increased after we return, counteract that - } - break; - - case GE_CMD_RET: - //TODO : debug! - { - u32 target = stack[--stackptr] & 0xFFFFFFF; - DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target); - dcontext.pc = target - 4; - } - break; - - case GE_CMD_SIGNAL: - ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); - { - // int behaviour = (data >> 16) & 0xFF; - // int signal = data & 0xFFFF; - } - - // This should generate a GE Interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - // Apparently, these callbacks should be done in a special interrupt way. - //for (size_t i = 0; i < signalCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, signalCallbacks[i].first, signal); - //} - - break; - - case GE_CMD_BJUMP: - // bounding box jump. Let's just not jump, for now. - DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); - break; - - case GE_CMD_BOUNDINGBOX: - // bounding box test. Let's do nothing. - DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); - break; - - case GE_CMD_ORIGIN: - gstate.offsetAddr = dcontext.pc & 0xFFFFFF; - break; - - case GE_CMD_VERTEXTYPE: - DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); - if (diff & GE_VTYPE_THROUGH) { - // Throughmode changed, let's make the proj matrix dirty. - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); - } - if (data & GE_VTYPE_THROUGH) { - glDisable(GL_CULL_FACE); - } - // This sets through-mode or not, as well. - break; - - case GE_CMD_OFFSETADDR: - // offsetAddr = data<<8; - break; - - - case GE_CMD_FINISH: - DEBUG_LOG(G3D,"DL CMD FINISH"); - // Trigger the finish callbacks - { - // Apparently, these callbacks should be done in a special interrupt way. - - //for (size_t i = 0; i < finishCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, finishCallbacks[i].first, 0); - //} - } - break; - - case GE_CMD_END: - DEBUG_LOG(G3D,"DL CMD END"); - { - switch (prev >> 24) - { - case GE_CMD_FINISH: - finished = true; - break; - default: - DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); - break; - } - } - - // This should generate a Reading Ended interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - break; - - case GE_CMD_REGION1: - { - int x1 = data & 0x3ff; - int y1 = data >> 10; - //topleft - DEBUG_LOG(G3D,"DL Region TL: %d %d", x1, y1); - } - break; - - case GE_CMD_REGION2: - { - int x2 = data & 0x3ff; - int y2 = data >> 10; - DEBUG_LOG(G3D,"DL Region BR: %d %d", x2, y2); - } - break; - - case GE_CMD_CLIPENABLE: - DEBUG_LOG(G3D, "DL Clip Enable: %i (ignoring)", data); - //we always clip, this is opengl - break; - - case GE_CMD_CULLFACEENABLE: - DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); - glEnDis(GL_CULL_FACE, data&1); - break; - - case GE_CMD_TEXTUREMAPENABLE: - DEBUG_LOG(G3D, "DL Texture map enable: %i", data); - glEnDis(GL_TEXTURE_2D, data&1); - break; - - case GE_CMD_LIGHTINGENABLE: - DEBUG_LOG(G3D, "DL Lighting enable: %i", data); - data += 1; - //We don't use OpenGL lighting - break; - - case GE_CMD_FOGENABLE: - DEBUG_LOG(G3D, "DL Fog Enable: %i", gstate.fogEnable); - break; - - case GE_CMD_DITHERENABLE: - DEBUG_LOG(G3D, "DL Dither Enable: %i", gstate.ditherEnable); - break; - - case GE_CMD_OFFSETX: - DEBUG_LOG(G3D, "DL Offset X: %i", gstate.offsetx); - break; - - case GE_CMD_OFFSETY: - DEBUG_LOG(G3D, "DL Offset Y: %i", gstate.offsety); - break; - - case GE_CMD_TEXSCALEU: - gstate.uScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate.uScale); - break; - - case GE_CMD_TEXSCALEV: - gstate.vScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate.vScale); - break; - - case GE_CMD_TEXOFFSETU: - gstate.uOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate.uOff); - break; - - case GE_CMD_TEXOFFSETV: - gstate.vOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate.vOff); - break; - - case GE_CMD_SCISSOR1: - { - int x1 = data & 0x3ff; - int y1 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); - } - break; - case GE_CMD_SCISSOR2: - { - int x2 = data & 0x3ff; - int y2 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); - } - break; - - case GE_CMD_MINZ: - DEBUG_LOG(G3D, "DL MinZ: %i", data); - break; - - case GE_CMD_MAXZ: - DEBUG_LOG(G3D, "DL MaxZ: %i", data); - break; - - case GE_CMD_FRAMEBUFPTR: - { - u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); - } - break; - - case GE_CMD_FRAMEBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); - } - break; - - case GE_CMD_FRAMEBUFPIXFORMAT: - break; - - case GE_CMD_TEXADDR0: - gstate.textureChanged=true; - case GE_CMD_TEXADDR1: - case GE_CMD_TEXADDR2: - case GE_CMD_TEXADDR3: - case GE_CMD_TEXADDR4: - case GE_CMD_TEXADDR5: - case GE_CMD_TEXADDR6: - case GE_CMD_TEXADDR7: - DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); - break; - - case GE_CMD_TEXBUFWIDTH0: - gstate.textureChanged=true; - case GE_CMD_TEXBUFWIDTH1: - case GE_CMD_TEXBUFWIDTH2: - case GE_CMD_TEXBUFWIDTH3: - case GE_CMD_TEXBUFWIDTH4: - case GE_CMD_TEXBUFWIDTH5: - case GE_CMD_TEXBUFWIDTH6: - case GE_CMD_TEXBUFWIDTH7: - DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); - break; - - case GE_CMD_CLUTADDR: - //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); - break; - - case GE_CMD_CLUTADDRUPPER: - DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); - break; - - case GE_CMD_LOADCLUT: - { - u32 clutAttr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); - if (clutAttr) - { - u16 *clut = (u16*)Memory::GetPointer(clutAttr); - if (clut) { - int numColors = 16 * (data&0x3F); - memcpy(&gstate.paletteMem[0], clut, numColors * 2); - } - DEBUG_LOG(G3D,"DL Clut load: %i palettes", data); - } - else - { - DEBUG_LOG(G3D,"DL Empty Clut load"); - } - // Should hash and invalidate all paletted textures on use - } - break; - -// case GE_CMD_TRANSFERSRC: - - case GE_CMD_TRANSFERSRCW: - { - u32 xferSrc = gstate.transfersrc | ((data&0xFF0000)<<8); - u32 xferSrcW = gstate.transfersrcw & 1023; - DEBUG_LOG(G3D,"Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); - break; - } -// case GE_CMD_TRANSFERDST: - - case GE_CMD_TRANSFERDSTW: - { - u32 xferDst= gstate.transferdst | ((data&0xFF0000)<<8); - u32 xferDstW = gstate.transferdstw & 1023; - DEBUG_LOG(G3D,"Block Transfer Dest: %08x W: %i", xferDst, xferDstW); - break; - } - - case GE_CMD_TRANSFERSRCPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Src Rect TL: %i, %i", x, y); - break; - } - - case GE_CMD_TRANSFERDSTPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Dest Rect TL: %i, %i", x, y); - break; - } - - case GE_CMD_TRANSFERSIZE: - { - u32 w = (data & 1023)+1; - u32 h = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Rect Size: %i x %i", w, h); - break; - } - - case GE_CMD_TRANSFERSTART: - { - DEBUG_LOG(G3D, "DL Texture Transfer Start: PixFormat %i", data); - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, - // and take appropriate action. If not, this should just be a block transfer within - // GPU memory which could be implemented by a copy loop. - break; - } - - case GE_CMD_TEXSIZE0: - gstate.textureChanged=true; - gstate.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); - gstate.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); - //fall thru - ignoring the mipmap sizes for now - case GE_CMD_TEXSIZE1: - case GE_CMD_TEXSIZE2: - case GE_CMD_TEXSIZE3: - case GE_CMD_TEXSIZE4: - case GE_CMD_TEXSIZE5: - case GE_CMD_TEXSIZE6: - case GE_CMD_TEXSIZE7: - DEBUG_LOG(G3D,"DL Texture Size: %06x", data); - break; - - case GE_CMD_ZBUFPTR: - { - u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); - } - break; - - case GE_CMD_ZBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D,"Zbuf Width: %i", w); - } - break; - - case GE_CMD_AMBIENTCOLOR: - DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); - break; - - case GE_CMD_AMBIENTALPHA: - DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); - break; - - case GE_CMD_MATERIALAMBIENT: - DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); - break; - - case GE_CMD_MATERIALDIFFUSE: - DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); - break; - - case GE_CMD_MATERIALEMISSIVE: - DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); - break; - - case GE_CMD_MATERIALSPECULAR: - DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); - break; - - case GE_CMD_MATERIALALPHA: - DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); - break; - - case GE_CMD_MATERIALSPECULARCOEF: - DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); - break; - - case GE_CMD_LIGHTTYPE0: - case GE_CMD_LIGHTTYPE1: - case GE_CMD_LIGHTTYPE2: - case GE_CMD_LIGHTTYPE3: - DEBUG_LOG(G3D,"DL Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); - break; - - case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: - case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1: - case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: - case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: - { - int n = cmd - GE_CMD_LX0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); - gstate.lightpos[l][c] = val; - } - break; - - case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0: - case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1: - case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: - case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: - { - int n = cmd - GE_CMD_LDX0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); - gstate.lightdir[l][c] = val; - } - break; - - case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0: - case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1: - case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: - case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: - { - int n = cmd - GE_CMD_LKA0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); - gstate.lightatt[l][c] = val; - } - break; - - - case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3: - case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: - case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: - { - float r = (float)(data>>16)/255.0f; - float g = (float)((data>>8) & 0xff)/255.0f; - float b = (float)(data & 0xff)/255.0f; - - int l = (cmd - GE_CMD_LAC0) / 3; - int t = (cmd - GE_CMD_LAC0) % 3; - gstate.lightColor[t][l].r = r; - gstate.lightColor[t][l].g = g; - gstate.lightColor[t][l].b = b; - } - break; - - case GE_CMD_VIEWPORTX1: - case GE_CMD_VIEWPORTY1: - case GE_CMD_VIEWPORTZ1: - case GE_CMD_VIEWPORTX2: - case GE_CMD_VIEWPORTY2: - case GE_CMD_VIEWPORTZ2: - DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); - break; - case GE_CMD_LIGHTENABLE0: - case GE_CMD_LIGHTENABLE1: - case GE_CMD_LIGHTENABLE2: - case GE_CMD_LIGHTENABLE3: - DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); - break; - case GE_CMD_CULL: - DEBUG_LOG(G3D,"DL cull: %06x", data); - glCullFace(data ? GL_BACK : GL_FRONT); - break; - - case GE_CMD_LMODE: - DEBUG_LOG(G3D,"DL Shade mode: %06x", data); - break; - - case GE_CMD_PATCHDIVISION: - gstate.patch_div_s = data & 0xFF; - gstate.patch_div_t = (data >> 8) & 0xFF; - DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate.patch_div_s, gstate.patch_div_t); - break; - - case GE_CMD_MATERIALUPDATE: - DEBUG_LOG(G3D,"DL Material Update: %d", data); - break; - - - ////////////////////////////////////////////////////////////////// - // CLEARING - ////////////////////////////////////////////////////////////////// - case GE_CMD_CLEARMODE: - // If it becomes a performance problem, check diff&1 - if (data & 1) - EnterClearMode(data); - else - LeaveClearMode(); - DEBUG_LOG(G3D,"DL Clear mode: %06x", data); - break; - - - ////////////////////////////////////////////////////////////////// - // ALPHA BLENDING - ////////////////////////////////////////////////////////////////// - case GE_CMD_ALPHABLENDENABLE: - DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); - glEnDis(GL_BLEND, data); - break; - - case GE_CMD_BLENDMODE: - DEBUG_LOG(G3D,"DL Blend mode: %06x", data); - SetBlendModePSP(data); - break; - - case GE_CMD_BLENDFIXEDA: - DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); - break; - - case GE_CMD_BLENDFIXEDB: - DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); - break; - - case GE_CMD_ALPHATESTENABLE: - DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); - // This is done in the shader. - break; - - case GE_CMD_ALPHATEST: - DEBUG_LOG(G3D,"DL Alpha test settings"); - shaderManager.DirtyUniform(DIRTY_ALPHAREF); - break; - - case GE_CMD_TEXFUNC: - { - DEBUG_LOG(G3D,"DL TexFunc %i", data&7); - /* - int m=GL_MODULATE; - switch (data & 7) - { - case 0: m=GL_MODULATE; break; - case 1: m=GL_DECAL; break; - case 2: m=GL_BLEND; break; - case 3: m=GL_REPLACE; break; - case 4: m=GL_ADD; break; - }*/ - - /* - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);*/ - break; - } - case GE_CMD_TEXFILTER: - { - int min = data & 7; - int mag = (data >> 8) & 1; - DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); - } - - break; - ////////////////////////////////////////////////////////////////// - // Z/STENCIL TESTING - ////////////////////////////////////////////////////////////////// - - case GE_CMD_ZTESTENABLE: - glEnDis(GL_DEPTH_TEST, data & 1); - DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); - break; - - case GE_CMD_STENCILTESTENABLE: - DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); - break; - - case GE_CMD_ZTEST: - { - static const GLuint ztests[8] = - { - GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, - GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL - }; - //glDepthFunc(ztests[data&7]); - glDepthFunc(GL_LEQUAL); - DEBUG_LOG(G3D,"DL Z test mode: %i", data); - } - break; - - case GE_CMD_MORPHWEIGHT0: - case GE_CMD_MORPHWEIGHT1: - case GE_CMD_MORPHWEIGHT2: - case GE_CMD_MORPHWEIGHT3: - case GE_CMD_MORPHWEIGHT4: - case GE_CMD_MORPHWEIGHT5: - case GE_CMD_MORPHWEIGHT6: - case GE_CMD_MORPHWEIGHT7: - { - int index = cmd - GE_CMD_MORPHWEIGHT0; - float weight = getFloat24(data); - DEBUG_LOG(G3D,"DL MorphWeight %i = %f", index, weight); - gstate.morphWeights[index] = weight; - } - break; - - case GE_CMD_DITH0: - case GE_CMD_DITH1: - case GE_CMD_DITH2: - case GE_CMD_DITH3: - DEBUG_LOG(G3D,"DL DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); - break; - - case GE_CMD_WORLDMATRIXNUMBER: - DEBUG_LOG(G3D,"DL World matrix # %i", data); - gstate.worldmtxnum = data&0xF; - break; - - case GE_CMD_WORLDMATRIXDATA: - DEBUG_LOG(G3D,"DL World matrix data # %f", getFloat24(data)); - gstate.worldMatrix[gstate.worldmtxnum++] = getFloat24(data); - break; - - case GE_CMD_VIEWMATRIXNUMBER: - DEBUG_LOG(G3D,"DL VIEW matrix # %i", data); - gstate.viewmtxnum = data&0xF; - break; - - case GE_CMD_VIEWMATRIXDATA: - DEBUG_LOG(G3D,"DL VIEW matrix data # %f", getFloat24(data)); - gstate.viewMatrix[gstate.viewmtxnum++] = getFloat24(data); - break; - - case GE_CMD_PROJMATRIXNUMBER: - DEBUG_LOG(G3D,"DL PROJECTION matrix # %i", data); - gstate.projmtxnum = data&0xF; - break; - - case GE_CMD_PROJMATRIXDATA: - DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data)); - gstate.projMatrix[gstate.projmtxnum++] = getFloat24(data); - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); - break; - - case GE_CMD_TGENMATRIXNUMBER: - DEBUG_LOG(G3D,"DL TGEN matrix # %i", data); - gstate.texmtxnum = data&0xF; - break; - - case GE_CMD_TGENMATRIXDATA: - DEBUG_LOG(G3D,"DL TGEN matrix data # %f", getFloat24(data)); - gstate.tgenMatrix[gstate.texmtxnum++] = getFloat24(data); - break; - - case GE_CMD_BONEMATRIXNUMBER: - DEBUG_LOG(G3D,"DL BONE matrix #%i", data); - gstate.boneMatrixNumber = data; - break; - - case GE_CMD_BONEMATRIXDATA: - DEBUG_LOG(G3D,"DL BONE matrix data #%i %f", gstate.boneMatrixNumber, getFloat24(data)); - gstate.boneMatrix[gstate.boneMatrixNumber++] = getFloat24(data); - break; - - default: - DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); - break; - - //ETC... - } -} - -bool GPU::InterpretList() -{ - // Reset stackptr for safety - stackptr = 0; - u32 op = 0; - prev = 0; - finished = false; - while (!finished) - { - if (dcontext.pc == dcontext.stallAddr) - return false; - - op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory - u32 cmd = op >> 24; - u32 diff = op ^ gstate.cmdmem[cmd]; - gstate.cmdmem[cmd] = op; // crashes if I try to put the whole op there?? - - ExecuteOp(op, diff); - - dcontext.pc += 4; - prev = op; - } - return true; -} diff --git a/GPU/Null/NullDisplayListInterpreter.h b/GPU/Null/NullDisplayListInterpreter.h deleted file mode 100644 index dc83dacb59..0000000000 --- a/GPU/Null/NullDisplayListInterpreter.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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 - -#include "../../Globals.h" - -class ShaderManager; - -class GPU -{ -public: - static u32 EnqueueList(u32 listpc, u32 stall); - static void UpdateStall(int listid, u32 newstall); - static void ExecuteOp(u32 op, u32 diff); - static bool InterpretList(); -}; diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 199ad07e04..05b98aa851 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -44,6 +44,8 @@ public: virtual void InvalidateCache(u32 addr, int size); virtual void Flush() {} + virtual void DeviceLost() {} + private: bool ProcessDLQueue(); bool interruptsEnabled_; diff --git a/android/jni/EmuScreen.cpp b/android/jni/EmuScreen.cpp index 62db3b03f1..da9d1a8fa6 100644 --- a/android/jni/EmuScreen.cpp +++ b/android/jni/EmuScreen.cpp @@ -29,9 +29,8 @@ #include "../../Core/Host.h" #include "../../Core/System.h" #include "../../Core/MIPS/MIPS.h" -#include "../../GPU/GLES/TextureCache.h" -#include "../../GPU/GLES/ShaderManager.h" #include "../../GPU/GPUState.h" +#include "../../GPU/GPUInterface.h" #include "../../Core/HLE/sceCtrl.h" #include "GamepadEmu.h" @@ -40,8 +39,6 @@ #include "MenuScreens.h" #include "EmuScreen.h" -extern ShaderManager shaderManager; - EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { std::string fileToStart = filename; @@ -200,6 +197,5 @@ void EmuScreen::render() void EmuScreen::deviceLost() { - TextureCache_Clear(false); // This doesn't seem to help? - shaderManager.ClearCache(false); + gpu->DeviceLost(); } From 1328413dfc5a95a5dbafcbb706fc0787a5234f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:24:19 +0100 Subject: [PATCH 188/276] Filesystems: add host0: hack, proper shutdown of DirectoryFileSystem --- Core/FileSystems/BlockDevices.cpp | 8 +- Core/FileSystems/DirectoryFileSystem.cpp | 151 +++++++++-------------- Core/FileSystems/DirectoryFileSystem.h | 43 ++++--- Core/FileSystems/MetaFileSystem.cpp | 15 ++- 4 files changed, 96 insertions(+), 121 deletions(-) diff --git a/Core/FileSystems/BlockDevices.cpp b/Core/FileSystems/BlockDevices.cpp index cd743741f5..025e3427ea 100644 --- a/Core/FileSystems/BlockDevices.cpp +++ b/Core/FileSystems/BlockDevices.cpp @@ -122,11 +122,11 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr) { u32 idx = index[blockNumber]; u32 idx2 = index[blockNumber+1]; - u8 inbuffer[4096]; //too big - z_stream z; - + u8 inbuffer[4096]; //too big + z_stream z; + int plain = idx & 0x80000000; - + idx = (idx & 0x7FFFFFFF) << indexShift; idx2 = (idx2 & 0x7FFFFFFF) << indexShift; diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 3302c266d2..aa7185f07c 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -25,23 +25,33 @@ #include "FileUtil.h" #include "DirectoryFileSystem.h" -DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) -{ +// TODO: Simulate case insensitivity on Unix. +// NOTE: MacOSX is already case insensitive. + +DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { File::CreateFullPath(basePath); hAlloc = _hAlloc; } -std::string DirectoryFileSystem::GetLocalPath(std::string localpath) -{ +DirectoryFileSystem::~DirectoryFileSystem() { + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { +#ifdef _WIN32 + CloseHandle((*iter).second.hFile); +#else + fclose((*iter).second.hFile); +#endif + } +} + +std::string DirectoryFileSystem::GetLocalPath(std::string localpath) { if (localpath.empty()) return basePath; if (localpath[0] == '/') localpath.erase(0,1); - //Convert slashes + //Convert slashes #ifdef _WIN32 - for (size_t i = 0; i < localpath.size(); i++) - { + for (size_t i = 0; i < localpath.size(); i++) { if (localpath[i] == '/') localpath[i] = '\\'; } @@ -49,17 +59,11 @@ std::string DirectoryFileSystem::GetLocalPath(std::string localpath) return basePath + localpath; } - -bool DirectoryFileSystem::MkDir(const std::string &dirname) -{ - std::string fullName = GetLocalPath(dirname); - - return File::CreateFullPath(fullName); - +bool DirectoryFileSystem::MkDir(const std::string &dirname) { + return File::CreateFullPath(GetLocalPath(dirname)); } -bool DirectoryFileSystem::RmDir(const std::string &dirname) -{ +bool DirectoryFileSystem::RmDir(const std::string &dirname) { std::string fullName = GetLocalPath(dirname); /*#ifdef _WIN32 return RemoveDirectory(fullName.c_str()) == TRUE; @@ -69,8 +73,7 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) return File::DeleteDirRecursively(fullName); } -bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string &to) -{ +bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string &to) { std::string fullFrom = GetLocalPath(from); std::string fullTo = to; // TO filename may not include path. Intention is that it uses FROM's path @@ -88,8 +91,7 @@ bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string #endif } -bool DirectoryFileSystem::DeleteFile(const std::string &filename) -{ +bool DirectoryFileSystem::DeleteFile(const std::string &filename) { std::string fullName = GetLocalPath(filename); #ifdef _WIN32 return ::DeleteFile(fullName.c_str()) == TRUE; @@ -98,8 +100,7 @@ bool DirectoryFileSystem::DeleteFile(const std::string &filename) #endif } -u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) -{ +u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { std::string fullName = GetLocalPath(filename); INFO_LOG(HLE,"Actually opening %s (%s)", fullName.c_str(), filename.c_str()); @@ -110,23 +111,19 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) DWORD desired = 0; DWORD sharemode = 0; DWORD openmode = 0; - if (access & FILEACCESS_READ) - { + if (access & FILEACCESS_READ) { desired |= GENERIC_READ; sharemode |= FILE_SHARE_READ; } - if (access & FILEACCESS_WRITE) - { + if (access & FILEACCESS_WRITE) { desired |= GENERIC_WRITE; sharemode |= FILE_SHARE_WRITE; } - if (access & FILEACCESS_CREATE) - { + if (access & FILEACCESS_CREATE) { openmode = OPEN_ALWAYS; - } - else + } else { openmode = OPEN_EXISTING; - + } //Let's do it! entry.hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0); bool success = entry.hFile != INVALID_HANDLE_VALUE; @@ -135,16 +132,13 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) bool success = entry.hFile != 0; #endif - if (!success) - { + if (!success) { #ifdef _WIN32 - ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", GetLastError(), (int)access); + ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", GetLastError(), (int)access); #endif //wwwwaaaaahh!! return 0; - } - else - { + } else { u32 newHandle = hAlloc->GetNewHandle(); entries[newHandle] = entry; @@ -152,34 +146,28 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) } } -void DirectoryFileSystem::CloseFile(u32 handle) -{ +void DirectoryFileSystem::CloseFile(u32 handle) { EntryMap::iterator iter = entries.find(handle); - if (iter != entries.end()) - { + if (iter != entries.end()) { hAlloc->FreeHandle(handle); #ifdef _WIN32 CloseHandle((*iter).second.hFile); #else - fclose((*iter).second.hFile); + fclose((*iter).second.hFile); #endif entries.erase(iter); - } - else - { + } else { //This shouldn't happen... ERROR_LOG(HLE,"Cannot close file that hasn't been opened: %08x", handle); } } -bool DirectoryFileSystem::OwnsHandle(u32 handle) -{ +bool DirectoryFileSystem::OwnsHandle(u32 handle) { EntryMap::iterator iter = entries.find(handle); return (iter != entries.end()); } -size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) -{ +size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) { EntryMap::iterator iter = entries.find(handle); if (iter != entries.end()) { @@ -190,17 +178,14 @@ size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) bytesRead = fread(pointer, 1, size, iter->second.hFile); #endif return bytesRead; - } - else - { + } else { //This shouldn't happen... ERROR_LOG(HLE,"Cannot read file that hasn't been opened: %08x", handle); return 0; } } -size_t DirectoryFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size) -{ +size_t DirectoryFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size) { EntryMap::iterator iter = entries.find(handle); if (iter != entries.end()) { @@ -208,57 +193,48 @@ size_t DirectoryFileSystem::WriteFile(u32 handle, const u8 *pointer, s64 size) #ifdef _WIN32 ::WriteFile(iter->second.hFile, (LPVOID)pointer, (DWORD)size, (LPDWORD)&bytesWritten, 0); #else - bytesWritten = fwrite(pointer, 1, size, iter->second.hFile); + bytesWritten = fwrite(pointer, 1, size, iter->second.hFile); #endif return bytesWritten; - } - else - { + } else { //This shouldn't happen... ERROR_LOG(HLE,"Cannot write to file that hasn't been opened: %08x", handle); return 0; } } -size_t DirectoryFileSystem::SeekFile(u32 handle, s32 position, FileMove type) -{ +size_t DirectoryFileSystem::SeekFile(u32 handle, s32 position, FileMove type) { EntryMap::iterator iter = entries.find(handle); - if (iter != entries.end()) - { + if (iter != entries.end()) { #ifdef _WIN32 DWORD moveMethod = 0; - switch (type) - { + switch (type) { case FILEMOVE_BEGIN: moveMethod = FILE_BEGIN; break; case FILEMOVE_CURRENT: moveMethod = FILE_CURRENT; break; case FILEMOVE_END: moveMethod = FILE_END; break; } DWORD newPos = SetFilePointer((*iter).second.hFile, (LONG)position, 0, moveMethod); - return newPos; + return newPos; #else - int moveMethod = 0; - switch (type) { - case FILEMOVE_BEGIN: moveMethod = SEEK_SET; break; - case FILEMOVE_CURRENT: moveMethod = SEEK_CUR; break; - case FILEMOVE_END: moveMethod = SEEK_END; break; - } - fseek(iter->second.hFile, position, moveMethod); + int moveMethod = 0; + switch (type) { + case FILEMOVE_BEGIN: moveMethod = SEEK_SET; break; + case FILEMOVE_CURRENT: moveMethod = SEEK_CUR; break; + case FILEMOVE_END: moveMethod = SEEK_END; break; + } + fseek(iter->second.hFile, position, moveMethod); return ftell(iter->second.hFile); #endif - } - else - { + } else { //This shouldn't happen... ERROR_LOG(HLE,"Cannot seek in file that hasn't been opened: %08x", handle); return 0; } } -PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) -{ - PSPFileInfo x; +PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { + PSPFileInfo x; x.name = filename; - std::string fullName = GetLocalPath(filename); if (!File::Exists(fullName)) { @@ -268,7 +244,6 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) x.exists = true; #ifdef _WIN32 - WIN32_FILE_ATTRIBUTE_DATA data; GetFileAttributesEx(fullName.c_str(), GetFileExInfoStandard, &data); @@ -282,8 +257,7 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) return x; } -std::vector DirectoryFileSystem::GetDirListing(std::string path) -{ +std::vector DirectoryFileSystem::GetDirListing(std::string path) { std::vector myVector; #ifdef _WIN32 WIN32_FIND_DATA findData; @@ -293,26 +267,23 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) hFind = FindFirstFile(w32path.c_str(), &findData); - if (hFind == INVALID_HANDLE_VALUE) - { + if (hFind == INVALID_HANDLE_VALUE) { return myVector; //the empty list } - while (true) - { + while (true) { PSPFileInfo entry; - if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) entry.type = FILETYPE_DIRECTORY; else entry.type = FILETYPE_NORMAL; - - if (!strcmp(findData.cFileName, "..") )// TODO: is this just for .. or all sub directories? Need to add a directory to the test to find out. Also why so different than the old test results? + // TODO: is this just for .. or all subdirectories? Need to add a directory to the test + // to find out. Also why so different than the old test results? + if (!strcmp(findData.cFileName, "..") ) entry.size = 4096; else entry.size = findData.nFileSizeLow | ((u64)findData.nFileSizeHigh<<32); entry.name = findData.cFileName; - myVector.push_back(entry); int retval = FindNextFile(hFind, &findData); diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index df81ccab34..6b87c3f784 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -28,29 +28,11 @@ typedef void * HANDLE; #endif - -class DirectoryFileSystem : public IFileSystem -{ - struct OpenFileEntry - { -#ifdef _WIN32 - HANDLE hFile; -#else - FILE *hFile; -#endif - }; - - typedef std::map EntryMap; - EntryMap entries; - std::string basePath; - IHandleAllocator *hAlloc; - - - // In case of Windows: Translate slashes, etc. - std::string GetLocalPath(std::string localpath); - +class DirectoryFileSystem : public IFileSystem { public: DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath); + ~DirectoryFileSystem(); + std::vector GetDirListing(std::string path); u32 OpenFile(std::string filename, FileAccess access); void CloseFile(u32 handle); @@ -59,9 +41,26 @@ public: size_t SeekFile(u32 handle, s32 position, FileMove type); PSPFileInfo GetFileInfo(std::string filename); bool OwnsHandle(u32 handle); + bool MkDir(const std::string &dirname); bool RmDir(const std::string &dirname); bool RenameFile(const std::string &from, const std::string &to); bool DeleteFile(const std::string &filename); + +private: + struct OpenFileEntry { +#ifdef _WIN32 + HANDLE hFile; +#else + FILE *hFile; +#endif + }; + + typedef std::map EntryMap; + EntryMap entries; + std::string basePath; + IHandleAllocator *hAlloc; + + // In case of Windows: Translate slashes, etc. + std::string GetLocalPath(std::string localpath); }; - diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index c3c1eef198..b239a7657e 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -160,13 +160,19 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) return 0; } -bool MetaFileSystem::MapFilePath(const std::string &inpath, std::string &outpath, IFileSystem **system) +bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpath, IFileSystem **system) { //TODO: implement current directory per thread (NOT per drive) - - //DEBUG_LOG(HLE, "MapFilePath: starting with \"%s\"", inpath.c_str()); - std::string realpath; + + // Special handling: host0:command.txt (as seen in Super Monkey Ball Adventures, for example) + // appears to mean the current directory on the UMD. Let's just assume the current directory. + std::string inpath = _inpath; + if (inpath.substr(0, 6) == "host0:") { + INFO_LOG(HLE, "Host0 path detected, stripping: %s", inpath.c_str()); + inpath = inpath.substr(6); + } + if ( RealPath(currentDirectory, inpath, realpath) ) { for (size_t i = 0; i < fileSystems.size(); i++) @@ -185,7 +191,6 @@ bool MetaFileSystem::MapFilePath(const std::string &inpath, std::string &outpath } DEBUG_LOG(HLE, "MapFilePath: failed mapping \"%s\", returning false", inpath.c_str()); - return false; } From ed68dea0d5834d6520c612eb712a9c598053cb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:37:53 +0100 Subject: [PATCH 189/276] JIT: Ignore branches in delay slots. Not sure if this is 100% correct. --- Core/MIPS/x86/CompBranch.cpp | 26 +++++++++++++++++++++++++- Core/MIPS/x86/RegCache.cpp | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 85a47125e5..a3cd04f889 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -61,6 +61,10 @@ static u64 saved_flags; void Jit::BranchRSRTComp(u32 op, Gen::CCFlags cc, bool likely) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } int offset = (signed short)(op&0xFFFF)<<2; int rt = _RT; int rs = _RS; @@ -119,6 +123,10 @@ void Jit::BranchRSRTComp(u32 op, Gen::CCFlags cc, bool likely) void Jit::BranchRSZeroComp(u32 op, Gen::CCFlags cc, bool likely) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } int offset = (signed short)(op&0xFFFF)<<2; int rs = _RS; u32 targetAddr = js.compilerPC + offset + 4; @@ -208,6 +216,10 @@ void Jit::Comp_RelBranchRI(u32 op) // If likely is set, discard the branch slot if NOT taken. void Jit::BranchFPFlag(u32 op, Gen::CCFlags cc, bool likely) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } int offset = (signed short)(op & 0xFFFF) << 2; u32 targetAddr = js.compilerPC + offset + 4; @@ -273,6 +285,10 @@ void Jit::Comp_FPUBranch(u32 op) // If likely is set, discard the branch slot if NOT taken. void Jit::BranchVFPUFlag(u32 op, Gen::CCFlags cc, bool likely) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } int offset = (signed short)(op & 0xFFFF) << 2; u32 targetAddr = js.compilerPC + offset + 4; @@ -346,10 +362,14 @@ void Jit::Comp_VBranch(u32 op) void Jit::Comp_Jump(u32 op) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } u32 off = ((op & 0x3FFFFFF) << 2); u32 targetAddr = (js.compilerPC & 0xF0000000) | off; //Delay slot - CompileAt(js.compilerPC + 4); + CompileAt(js.compilerPC + 4); FlushAll(); switch (op >> 26) @@ -374,6 +394,10 @@ static u32 savedPC; void Jit::Comp_JumpReg(u32 op) { + if (js.inDelaySlot) { + ERROR_LOG(JIT, "Branch in delay slot at %08x", js.compilerPC); + return; + } int rs = _RS; u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4); diff --git a/Core/MIPS/x86/RegCache.cpp b/Core/MIPS/x86/RegCache.cpp index 2cc65533da..2f0b99100f 100644 --- a/Core/MIPS/x86/RegCache.cpp +++ b/Core/MIPS/x86/RegCache.cpp @@ -287,6 +287,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { if (i != j && regs[j].location.IsSimpleReg() && regs[j].location.GetSimpleReg() == xr) { + ERROR_LOG(JIT, "BindToRegister: Strange condition"); Crash(); } } From 9fe6dcb863d1511f1afda80fe0126c864656d068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:51:03 +0100 Subject: [PATCH 190/276] Non-windows button mapping tweaks --- android/jni/EmuScreen.cpp | 14 +++++++++----- android/jni/NativeApp.cpp | 1 + native | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/android/jni/EmuScreen.cpp b/android/jni/EmuScreen.cpp index da9d1a8fa6..69a3696b09 100644 --- a/android/jni/EmuScreen.cpp +++ b/android/jni/EmuScreen.cpp @@ -109,6 +109,7 @@ void EmuScreen::update(InputState &input) if (invalid_) return; + // First translate touches into pad input. UpdateGamepad(input); UpdateInputState(&input); @@ -117,8 +118,8 @@ void EmuScreen::update(InputState &input) static const int mapping[12][2] = { {PAD_BUTTON_A, CTRL_CROSS}, - {PAD_BUTTON_B, CTRL_SQUARE}, - {PAD_BUTTON_X, CTRL_CIRCLE}, + {PAD_BUTTON_B, CTRL_CIRCLE}, + {PAD_BUTTON_X, CTRL_SQUARE}, {PAD_BUTTON_Y, CTRL_TRIANGLE}, {PAD_BUTTON_UP, CTRL_UP}, {PAD_BUTTON_DOWN, CTRL_DOWN}, @@ -127,15 +128,18 @@ void EmuScreen::update(InputState &input) {PAD_BUTTON_LBUMPER, CTRL_LTRIGGER}, {PAD_BUTTON_RBUMPER, CTRL_RTRIGGER}, {PAD_BUTTON_START, CTRL_START}, - {PAD_BUTTON_BACK, CTRL_SELECT}, + {PAD_BUTTON_SELECT, CTRL_SELECT}, }; for (int i = 0; i < 12; i++) { - if (input.pad_buttons_down & mapping[i][0]) + if (input.pad_buttons_down & mapping[i][0]) { __CtrlButtonDown(mapping[i][1]); - if (input.pad_buttons_up & mapping[i][0]) + } + if (input.pad_buttons_up & mapping[i][0]) { __CtrlButtonUp(mapping[i][1]); + } } + __CtrlSetAnalog(input.pad_lstick_x, input.pad_lstick_y); if (input.pad_buttons_down & (PAD_BUTTON_MENU | PAD_BUTTON_BACK)) { fbo_unbind(); diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 1ed98fba39..1a9fb6e7b4 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -40,6 +40,7 @@ #include "../../Core/PSPMixer.h" #include "../../Core/CPU.h" #include "../../Core/Config.h" +#include "../../Core/HLE/sceCtrl.h" #include "../../Core/Host.h" #include "../../Common/MemArena.h" diff --git a/native b/native index 8fd4f592ad..1556328129 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 8fd4f592ad44655031e3111a8594a6dfc1b195a4 +Subproject commit 15563281297adb62c8e690fc063a9bf4442fcfc7 From b2f29992a367c19c9a356bce4841354feecdd4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:52:40 +0100 Subject: [PATCH 191/276] Wrap some functions, clean some stuff --- Core/Core.cpp | 6 +-- Core/HLE/FunctionWrappers.h | 5 +++ Core/HLE/sceImpose.cpp | 38 +++++++++++----- Core/HLE/sceKernelMemory.cpp | 77 +++++++++++++++++---------------- Core/HLE/sceKernelModule.cpp | 11 ++--- Core/HLE/sceKernelMutex.cpp | 2 +- Core/HLE/sceKernelSemaphore.cpp | 11 +---- 7 files changed, 79 insertions(+), 71 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index e1c553eff2..33124240f6 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -81,7 +81,7 @@ void Core_SingleStep() // Some platforms, like Android, do not call this function but handle things on their own. void Core_Run() { -#if _DEBUG +#if defined(_DEBUG) host->UpdateDisassembly(); #endif @@ -129,14 +129,14 @@ void Core_EnableStepping(bool step) //PowerPC::Pause(); // Sleep(1); sleep_ms(1); -#if _DEBUG +#if defined(_DEBUG) host->SetDebugMode(true); #endif coreState=CORE_STEPPING; } else { -#if _DEBUG +#if defined(_DEBUG) host->SetDebugMode(false); #endif coreState = CORE_RUNNING; diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 0a511e71ae..4185bdcdae 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -182,6 +182,11 @@ template void WrapU_UU() { RETURN(retval); } +template void WrapU_CUUU() { + u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapV_UIUII() { func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); } diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 4122d1e40b..8e098f3d70 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -33,13 +33,15 @@ const int PSP_LANGUAGE_KOREAN = 9; const int PSP_LANGUAGE_TRADITIONAL_CHINESE = 10; const int PSP_LANGUAGE_SIMPLIFIED_CHINESE = 11; -static u32 iLanguage = PSP_LANGUAGE_ENGLISH; -static u32 iButtonValue = 0; +static u32 language = PSP_LANGUAGE_ENGLISH; +static u32 buttonValue = 0; +static u32 umdPopup = 0; void __ImposeInit() { - iLanguage = PSP_LANGUAGE_ENGLISH; - iButtonValue = 0; + language = PSP_LANGUAGE_ENGLISH; + buttonValue = 0; + umdPopup = 0; } u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) @@ -55,8 +57,8 @@ u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) u32 sceImposeSetLanguageMode(u32 languageVal, u32 buttonVal) { DEBUG_LOG(HLE, "sceImposeSetLanguageMode(%08x, %08x)", languageVal, buttonVal); - iLanguage = languageVal; - iButtonValue = buttonVal; + language = languageVal; + buttonValue = buttonVal; return 0; } @@ -64,20 +66,32 @@ u32 sceImposeGetLanguageMode(u32 languagePtr, u32 btnPtr) { DEBUG_LOG(HLE, "sceImposeGetLanguageMode(%08x, %08x)", languagePtr, btnPtr); if (Memory::IsValidAddress(languagePtr)) - Memory::Write_U32(iLanguage, languagePtr); + Memory::Write_U32(language, languagePtr); if (Memory::IsValidAddress(btnPtr)) - Memory::Write_U32(iButtonValue, btnPtr); + Memory::Write_U32(buttonValue, btnPtr); return 0; } +u32 sceImposeSetUMDPopup(int value) { + DEBUG_LOG(HLE, "sceImposeSetUMDPopup(%i)", value); + umdPopup = value; + return 0; +} + +u32 sceImposeGetUMDPopup() { + DEBUG_LOG(HLE, "sceImposeGetUMDPopup()"); + return umdPopup; +} + //OSD stuff? home button? const HLEFunction sceImpose[] = { - {0x36aa6e91, &WrapU_UU, "sceImposeSetLanguageMode"}, // Seen + {0x36aa6e91, WrapU_UU, "sceImposeSetLanguageMode"}, // Seen {0x381bd9e7, 0, "sceImposeHomeButton"}, - {0x24fd7bcf, &WrapU_UU, "sceImposeGetLanguageMode"}, - {0x8c943191, &WrapU_UU, "sceImposeGetBatteryIconStatus"}, - {0x72189C48, 0, "sceImposeSetUMDPopup"}, + {0x24fd7bcf, WrapU_UU, "sceImposeGetLanguageMode"}, + {0x8c943191, WrapU_UU, "sceImposeGetBatteryIconStatus"}, + {0x72189C48, WrapU_I, "sceImposeSetUMDPopup"}, + {0xE0887BC8, WrapU_V, "sceImposeGetUMDPopup"}, }; void Register_sceImpose() diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 452196087b..4034b096dd 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -439,18 +439,6 @@ void sceKernelPrintf() RETURN(0); } -void sceKernelSetCompiledSdkVersion() -{ - //pretty sure this only takes one arg - ERROR_LOG(HLE,"UNIMPL sceKernelSetCompiledSdkVersion(%08x)", PARAM(0)); - RETURN(0); -} - -void sceKernelSetCompilerVersion() -{ - ERROR_LOG(HLE,"UNIMPL sceKernelSetCompilerVersion(%08x, %08x, %08x, %08x)", PARAM(0),PARAM(1),PARAM(2),PARAM(3)); - RETURN(0); -} // VPL = variable length memory pool @@ -642,13 +630,11 @@ void sceKernelReferVplStatus() RETURN(0); } -void AllocMemoryBlock() { - const char *pname = Memory::GetCharPointer(PARAM(0)); - int type = PARAM(1); - u32 size = PARAM(2); - int paramsAddr = PARAM(3); - - DEBUG_LOG(HLE,"AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %i, %08x)", pname, type, size, paramsAddr); + +// TODO: Make proper kernel objects for these instead of using the UID as a pointer. + +u32 AllocMemoryBlock(const char *pname, u32 type, u32 size, u32 paramsAddr) { + INFO_LOG(HLE,"AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %i, %08x)", pname, type, size, paramsAddr); // Just support allocating a block in the user region. @@ -656,44 +642,59 @@ void AllocMemoryBlock() { // Create a UID object??? Nah, let's just us the UID itself (hack!) - RETURN(blockPtr); + return blockPtr; } -void FreeMemoryBlock() { - SceUID uid = PARAM(0); - DEBUG_LOG(HLE, "FreeMemoryBlock(%i)", uid); +u32 FreeMemoryBlock(u32 uid) { + INFO_LOG(HLE, "FreeMemoryBlock(%i)", uid); userMemory.Free(uid); - RETURN(0); + return 0; } -void GetMemoryBlockPtr() { - SceUID uid = PARAM(0); - DEBUG_LOG(HLE, "GetMemoryBlockPtr(%i)", uid); - RETURN(uid); +u32 GetMemoryBlockPtr(u32 uid) { + INFO_LOG(HLE, "GetMemoryBlockPtr(%i)", uid); + return uid; } -const HLEFunction SysMemUserForUser[] = -{ +u32 sceKernelSetCompiledSdkVersion(u32 param) { + // pretty sure this only takes one arg + ERROR_LOG(HLE,"UNIMPL sceKernelSetCompiledSdkVersion(%08x)", param); + return 0; +} + +u32 sceKernelSetCompiledSdkVersion395(u32 param) { + // pretty sure this only takes one arg + ERROR_LOG(HLE,"UNIMPL sceKernelSetCompiledSdkVersion395(%08x)", param); + return 0; +} + +u32 sceKernelSetCompilerVersion(u32 a, u32 b, u32 c, u32 d) { + ERROR_LOG(HLE,"UNIMPL sceKernelSetCompilerVersion(%08x, %08x, %08x, %08x)", a, b, c, d); + return 0; +} + +const HLEFunction SysMemUserForUser[] = { {0xA291F107,sceKernelMaxFreeMemSize, "sceKernelMaxFreeMemSize"}, {0xF919F628,sceKernelTotalFreeMemSize,"sceKernelTotalFreeMemSize"}, - {0x3FC9AE6A,sceKernelDevkitVersion, "sceKernelDevkitVersion"}, + {0x3FC9AE6A,sceKernelDevkitVersion, "sceKernelDevkitVersion"}, {0x237DBD4F,sceKernelAllocPartitionMemory,"sceKernelAllocPartitionMemory"}, //(int size) ? {0xB6D61D02,sceKernelFreePartitionMemory,"sceKernelFreePartitionMemory"}, //(void *ptr) ? {0x9D9A5BA1,sceKernelGetBlockHeadAddr,"sceKernelGetBlockHeadAddr"}, //(void *ptr) ? {0x13a5abef,sceKernelPrintf,"sceKernelPrintf 0x13a5abef"}, - {0x7591c7db,sceKernelSetCompiledSdkVersion,"sceKernelSetCompiledSdkVersion"}, + {0x7591c7db,WrapU_U,"sceKernelSetCompiledSdkVersion"}, {0x342061E5,0,"sceKernelSetCompiledSdkVersion370"}, {0x315AD3A0,0,"sceKernelSetCompiledSdkVersion380_390"}, - {0xEBD5C3E6,0,"sceKernelSetCompiledSdkVersion395"}, - {0xf77d77cb,sceKernelSetCompilerVersion,"sceKernelSetCompilerVersion"}, + {0xEBD5C3E6,WrapU_U,"sceKernelSetCompiledSdkVersion395"}, + {0xf77d77cb,WrapU_UUUU,"sceKernelSetCompilerVersion"}, {0x35669d4c,0,"sceKernelSetCompiledSdkVersion600_602"}, //?? {0x1b4217bc,0,"sceKernelSetCompiledSdkVersion603_605"}, - {0x358ca1bb,0,"sceKernelSetCompiledSdkVersion606"}, + {0x358ca1bb,0,"sceKernelSetCompiledSdkVersion606"}, + // Obscure raw block API - {0xDB83A952,GetMemoryBlockPtr,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr + {0xDB83A952,WrapU_U,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr {0x91DE343C,0,"SysMemUserForUser_91DE343C"}, - {0x50F61D8A,FreeMemoryBlock,"SysMemUserForUser_50F61D8A"}, // FreeMemoryBlock - {0xFE707FDF,AllocMemoryBlock,"SysMemUserForUser_FE707FDF"}, // AllocMemoryBlock + {0x50F61D8A,WrapU_U,"SysMemUserForUser_50F61D8A"}, // FreeMemoryBlock + {0xFE707FDF,WrapU_CUUU,"SysMemUserForUser_FE707FDF"}, // AllocMemoryBlock }; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 4303eca9e2..46305fe375 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -599,8 +599,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags) return SCE_KERNEL_ERROR_NOFILE; } - if (!size) - { + if (!size) { ERROR_LOG(LOADER, "sceKernelLoadModule(%s, %08x): Module file is size 0", name, flags); return SCE_KERNEL_ERROR_ILLEGAL_OBJECT; } @@ -610,10 +609,8 @@ u32 sceKernelLoadModule(const char *name, u32 flags) SceKernelLMOption *lmoption = 0; int position = 0; // TODO: Use position to decide whether to load high or low - if (PARAM(2)) - { + if (PARAM(2)) { lmoption = (SceKernelLMOption *)Memory::GetPointer(PARAM(2)); - } Module *module = 0; @@ -635,9 +632,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags) INFO_LOG(HLE,"%i=sceKernelLoadModule(name=%s,flag=%08x,%08x,%08x,%08x,position = %08x)", module->GetUID(),name,flags, lmoption->size,lmoption->mpidtext,lmoption->mpiddata,lmoption->position); - } - else - { + } else { INFO_LOG(HLE,"%i=sceKernelLoadModule(name=%s,flag=%08x,(...))", module->GetUID(), name, flags); } diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 345693540c..e3d048e545 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -128,7 +128,7 @@ void __KernelMutexShutdown() void __KernelMutexAcquireLock(Mutex *mutex, int count, SceUID thread) { -#if _DEBUG +#if defined(_DEBUG) std::pair locked = mutexHeldLocks.equal_range(thread); for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) _dbg_assert_msg_(HLE, (*iter).second != mutex->GetUID(), "Thread %d / mutex %d wasn't removed from mutexHeldLocks properly.", thread, mutex->GetUID()); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 39dc209928..2fd575d0d4 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -135,7 +135,6 @@ std::vector::iterator __KernelSemaFindPriority(std::vector &wait return best; } -// int sceKernelCancelSema(SceUID id, int newCount, int *numWaitThreads); int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) { DEBUG_LOG(HLE, "sceKernelCancelSema(%i)", id); @@ -168,7 +167,6 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) } } -//SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { if (!name) @@ -204,7 +202,6 @@ int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 return id; } -//int sceKernelDeleteSema(SceUID semaid); int sceKernelDeleteSema(SceUID id) { DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); @@ -226,7 +223,6 @@ int sceKernelDeleteSema(SceUID id) } } -//int sceKernelDeleteSema(SceUID semaid, SceKernelSemaInfo *info); int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { u32 error; @@ -243,8 +239,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) return error; } } - -//int sceKernelSignalSema(SceUID semaid, int signal); + int sceKernelSignalSema(SceUID id, int signal) { u32 error; @@ -359,15 +354,13 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *bad } } -//int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout); int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr); return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false); -} +} -//int sceKernelWaitSemaCB(SceUID semaid, int signal, SceUInt *timeout); int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr); From fb238c685e604c662586f905e9cb89517df7bd9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:53:19 +0100 Subject: [PATCH 192/276] SasAudio: voice.samplePos -> voice.sampleFrac. Gets rid of annoying overflow errors. --- Core/HW/SasAudio.cpp | 18 +++++++----------- Core/HW/SasAudio.h | 4 ++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 90b4894adb..8b1e50f445 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -47,8 +47,7 @@ bool VagDecoder::DecodeBlock() int shift_factor = predict_nr & 0xf; predict_nr >>= 4; int flags = GetByte(); - if (flags == 7) - { + if (flags == 7) { end_ = true; return false; } @@ -58,16 +57,14 @@ bool VagDecoder::DecodeBlock() else if (flags == 3 && loopEnabled_) { loopAtNextBlock_ = true; } - for (int i = 0; i < 28; i += 2) - { + for (int i = 0; i < 28; i += 2) { int d = GetByte(); int s = (short)((d & 0xf) << 12); samples[i] = (double)(s >> shift_factor); s = (short)((d & 0xf0) << 8); samples[i + 1] = (double)(s >> shift_factor); } - for (int i = 0; i < 28; i++) - { + for (int i = 0; i < 28; i++) { samples[i] = samples[i] + s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1]; s_2 = s_1; s_1 = samples[i]; @@ -219,9 +216,7 @@ void SasInstance::Mix(u32 outAddr) { resampleBuffer[1] = voice.resampleHist[1]; // 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; - u32 numSamples = lastSample - curSample; + u32 numSamples = (voice.sampleFrac + grainSize * voice.pitch) / PSP_SAS_PITCH_BASE; if (numSamples > grainSize * 4) { ERROR_LOG(SAS, "numSamples too large, clamping: %i vs %i", numSamples, grainSize * 4); numSamples = grainSize * 4; @@ -240,7 +235,7 @@ void SasInstance::Mix(u32 outAddr) { voice.resampleHist[1] = resampleBuffer[2 + numSamples - 1]; // Resample to the correct pitch, writing exactly "grainSize" samples. - u32 bufferPos = (voice.samplePos & (PSP_SAS_PITCH_BASE - 1)) + 2 * PSP_SAS_PITCH_BASE; + u32 bufferPos = voice.sampleFrac + 2 * PSP_SAS_PITCH_BASE; for (int i = 0; i < grainSize; i++) { // For now: nearest neighbour, not even using the resample history at all. int sample = resampleBuffer[bufferPos / PSP_SAS_PITCH_BASE]; @@ -262,7 +257,8 @@ void SasInstance::Mix(u32 outAddr) { sendBuffer[i * 2 + 1] += sample * voice.volumeRightSend >> 12; voice.envelope.Step(); } - voice.samplePos += voice.pitch * grainSize; + voice.sampleFrac += voice.pitch * grainSize; + voice.sampleFrac &= (PSP_SAS_PITCH_BASE - 1); if (voice.envelope.HasEnded()) { // NOTICE_LOG(SAS, "Hit end of envelope"); diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index d913a03366..411e0f5863 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -165,7 +165,7 @@ struct SasVoice pcmAddr(0), pcmSize(0), sampleRate(44100), - samplePos(0), + sampleFrac(0), pitch(PSP_SAS_PITCH_BASE), loop(false), noiseFreq(0), @@ -192,7 +192,7 @@ struct SasVoice int pcmSize; int sampleRate; - int samplePos; + int sampleFrac; int pitch; bool loop; From 1b35964445601ef76f1970506b61d1ea663d9990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:54:33 +0100 Subject: [PATCH 193/276] Add support for rotated UVs of flipped RECTANGLES. Avoid using indexed draws when unnecessary. --- GPU/GLES/IndexGenerator.cpp | 57 +++++++++++---- GPU/GLES/IndexGenerator.h | 6 +- GPU/GLES/TransformPipeline.cpp | 129 +++++++++++++++++---------------- GPU/GLES/VertexDecoder.h | 2 +- 4 files changed, 111 insertions(+), 83 deletions(-) diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index 7f1da114c1..32cbcc78a9 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -28,10 +28,16 @@ const u8 indexedPrimitiveType[7] = { GE_PRIM_RECTANGLES, }; +enum { + SEEN_INDEX8 = 1 << 29, + SEEN_INDEX16 = 1 << 30 +}; + void IndexGenerator::Reset() { prim_ = -1; count_ = 0; index_ = 0; + seenPrims_ = 0; this->inds_ = indsBase_; } @@ -41,14 +47,12 @@ bool IndexGenerator::PrimCompatible(int prim) { return indexedPrimitiveType[prim] == prim_; } -void IndexGenerator::Setup(u16 *inds) -{ +void IndexGenerator::Setup(u16 *inds) { this->indsBase_ = inds; Reset(); } -void IndexGenerator::AddPoints(int numVerts) -{ +void IndexGenerator::AddPoints(int numVerts) { //if we have no vertices return for (int i = 0; i < numVerts; i++) { @@ -58,6 +62,7 @@ void IndexGenerator::AddPoints(int numVerts) index_ += numVerts; count_ += numVerts; prim_ = GE_PRIM_POINTS; + seenPrims_ |= 1 << GE_PRIM_POINTS; } void IndexGenerator::AddList(int numVerts) @@ -75,6 +80,7 @@ void IndexGenerator::AddList(int numVerts) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= 1 << GE_PRIM_TRIANGLES; } void IndexGenerator::AddStrip(int numVerts) @@ -91,6 +97,7 @@ void IndexGenerator::AddStrip(int numVerts) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= 1 << GE_PRIM_TRIANGLE_STRIP; } void IndexGenerator::AddFan(int numVerts) @@ -105,6 +112,7 @@ void IndexGenerator::AddFan(int numVerts) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= 1 << GE_PRIM_TRIANGLE_FAN; } void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) @@ -116,6 +124,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u8 *inds, int offset) index_ += numVerts; count_ += numVerts; prim_ = GE_PRIM_POINTS; + seenPrims_ |= (1 << GE_PRIM_POINTS) | SEEN_INDEX8; } void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) @@ -127,6 +136,7 @@ void IndexGenerator::TranslatePoints(int numVerts, const u16 *inds, int offset) index_ += numVerts; count_ += numVerts; prim_ = GE_PRIM_POINTS; + seenPrims_ |= (1 << GE_PRIM_POINTS) | SEEN_INDEX16; } void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) @@ -141,6 +151,7 @@ void IndexGenerator::TranslateList(int numVerts, const u8 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLES) | SEEN_INDEX8; } void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) @@ -157,6 +168,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u8 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLE_STRIP) | SEEN_INDEX8; } void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) @@ -172,6 +184,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u8 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLE_STRIP) | SEEN_INDEX8;; } void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) @@ -186,6 +199,7 @@ void IndexGenerator::TranslateList(int numVerts, const u16 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLES) | SEEN_INDEX16; } void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) @@ -202,6 +216,7 @@ void IndexGenerator::TranslateStrip(int numVerts, const u16 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLE_STRIP) | SEEN_INDEX16; } void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) @@ -217,6 +232,7 @@ void IndexGenerator::TranslateFan(int numVerts, const u16 *inds, int offset) index_ += numVerts; count_ += numTris * 3; prim_ = GE_PRIM_TRIANGLES; + seenPrims_ |= (1 << GE_PRIM_TRIANGLE_FAN) | SEEN_INDEX16; } //Lines @@ -231,6 +247,7 @@ void IndexGenerator::AddLineList(int numVerts) index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= 1 << prim_; } void IndexGenerator::AddLineStrip(int numVerts) @@ -244,6 +261,7 @@ void IndexGenerator::AddLineStrip(int numVerts) index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= 1 << GE_PRIM_LINE_STRIP; } void IndexGenerator::AddRectangles(int numVerts) @@ -257,6 +275,7 @@ void IndexGenerator::AddRectangles(int numVerts) index_ += numVerts; count_ += numRects * 2; prim_ = GE_PRIM_RECTANGLES; + seenPrims_ |= 1 << GE_PRIM_RECTANGLES; } void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) @@ -264,12 +283,13 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) int numLines = numVerts / 2; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + i*2; - *inds_++ = index_ + i*2+1; + *inds_++ = index_ + offset + inds_[i*2]; + *inds_++ = index_ + offset + inds_[i*2+1]; } index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= (1 << GE_PRIM_LINES) | SEEN_INDEX8; } void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset) @@ -277,12 +297,13 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset int numLines = numVerts - 1; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + i; - *inds_++ = index_ + i + 1; + *inds_++ = index_ + offset + inds_[i]; + *inds_++ = index_ + offset + inds_[i + 1]; } index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= (1 << GE_PRIM_LINE_STRIP) | SEEN_INDEX8; } void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset) @@ -290,12 +311,13 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset int numLines = numVerts / 2; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + i*2; - *inds_++ = index_ + i*2+1; + *inds_++ = index_ + offset + inds_[i*2]; + *inds_++ = index_ + offset + inds_[i*2+1]; } index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= 1 << GE_PRIM_LINES; } void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offset) @@ -303,12 +325,13 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse int numLines = numVerts - 1; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + i; - *inds_++ = index_ + i + 1; + *inds_++ = index_ + offset + inds_[i]; + *inds_++ = index_ + offset + inds_[i + 1]; } index_ += numVerts; count_ += numLines * 2; prim_ = GE_PRIM_LINES; + seenPrims_ |= 1 << GE_PRIM_LINE_STRIP; } void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offset) @@ -316,12 +339,13 @@ void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offse int numRects = numVerts / 2; for (int i = 0; i < numRects; i++) { - *inds_++ = index_ + i*2; - *inds_++ = index_ + i*2+1; + *inds_++ = index_ + offset + inds_[i*2]; + *inds_++ = index_ + offset + inds_[i*2+1]; } index_ += numVerts; count_ += numRects * 2; prim_ = GE_PRIM_RECTANGLES; + seenPrims_ |= 1 << GE_PRIM_RECTANGLES; } void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offset) @@ -329,10 +353,11 @@ void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offs int numRects = numVerts / 2; for (int i = 0; i < numRects; i++) { - *inds_++ = index_ + i*2; - *inds_++ = index_ + i*2+1; + *inds_++ = index_ + offset + inds_[i*2]; + *inds_++ = index_ + offset + inds_[i*2+1]; } index_ += numVerts; count_ += numRects * 2; prim_ = GE_PRIM_RECTANGLES; + seenPrims_ |= 1 << GE_PRIM_RECTANGLES; } diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index 2ed1d03d5a..68cc4d8a74 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -58,13 +58,14 @@ public: void TranslateList(int numVerts, const u16 *inds, int offset); void TranslateStrip(int numVerts, const u16 *inds, int offset); void TranslateFan(int numVerts, const u16 *inds, int offset); - - int MaxIndex() { return index_; } + + int MaxIndex() { return index_; } int VertexCount() { return count_; } bool Empty() { return index_ == 0; } void SetIndex(int ind) { index_ = ind; } + int SeenPrims() const { return seenPrims_; } private: u16 *indsBase_; @@ -72,5 +73,6 @@ private: int index_; int count_; int prim_; + int seenPrims_; }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 63df7e64b6..8935422d0a 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -283,6 +283,27 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF VertexAttribDisable(program->a_position, decFmt.posfmt); } +// The verts are in the order: BR BL TL TR +static void SwapUVs(TransformedVertex &a, TransformedVertex &b) { + float tempu = a.u; + float tempv = a.v; + a.u = b.u; + a.v = b.v; + b.u = tempu; + b.v = tempv; +} +// 2 3 3 2 0 3 2 1 +// to to or +// 1 0 0 1 1 2 3 0 + +static void RotateUVs(TransformedVertex v[4]) { + if (v[0].y < v[2].y && v[0].x > v[2].x) { + SwapUVs(v[0], v[2]); + } else if (v[0].y > v[2].y && v[0].x < v[2].x) { + SwapUVs(v[1], v[3]); + } +} + // This is the software transform pipeline, which is necessary for supporting RECT // primitives correctly, and may be easier to use for debugging than the hardware // transform pipeline. @@ -299,8 +320,7 @@ static void DesetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decF // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. void TransformDrawEngine::SoftwareTransformAndDraw( - int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) -{ + int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { /* DEBUG_LOG(G3D, "View matrix:"); const float *m = &gstate.viewMatrix[0]; @@ -334,8 +354,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( float c1[4] = {0, 0, 0, 0}; float uv[2] = {0, 0}; - if (throughmode) - { + if (throughmode) { // Do not touch the coordinates or the colors. No lighting. reader.ReadPos(v); if (reader.hasColor0()) { @@ -343,9 +362,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( for (int j = 0; j < 4; j++) { c1[j] = 0.0f; } - } - else - { + } else { c0[0] = (gstate.materialambient & 0xFF) / 255.f; c0[1] = ((gstate.materialambient >> 8) & 0xFF) / 255.f; c0[2] = ((gstate.materialambient >> 16) & 0xFF) / 255.f; @@ -356,9 +373,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( reader.ReadUV(uv); } // Scale UV? - } - else - { + } else { // We do software T&L for now float out[3], norm[3]; float pos[3], nrm[3] = {0}; @@ -366,17 +381,14 @@ void TransformDrawEngine::SoftwareTransformAndDraw( if (reader.hasNormal()) reader.ReadNrm(nrm); - if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) - { + if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { Vec3ByMatrix43(out, pos, gstate.worldMatrix); if (reader.hasNormal()) { Norm3ByMatrix43(norm, nrm, gstate.worldMatrix); } else { memset(norm, 0, 12); } - } - else - { + } else { float weights[8]; reader.ReadWeights(weights); // Skinning @@ -419,8 +431,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( float litColor1[4]; lighter.Light(litColor0, litColor1, unlitColor, out, norm, dots); - if (gstate.lightingEnable & 1) - { + if (gstate.lightingEnable & 1) { // Don't ignore gstate.lmode - we should send two colors in that case if (gstate.lmode & 1) { // Separate colors @@ -435,9 +446,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( c1[j] = 0.0f; } } - } - else - { + } else { if (reader.hasColor0()) { for (int j = 0; j < 4; j++) { c0[j] = unlitColor[j]; @@ -507,7 +516,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // TODO: Write to a flexible buffer, we don't always need all four components. memcpy(&transformed[index].x, v, 3 * sizeof(float)); - memcpy(&transformed[index].uv, uv, 2 * sizeof(float)); + memcpy(&transformed[index].u, uv, 2 * sizeof(float)); memcpy(&transformed[index].color0, c0, 4 * sizeof(float)); memcpy(&transformed[index].color1, c1, 3 * sizeof(float)); } @@ -540,43 +549,35 @@ void TransformDrawEngine::SoftwareTransformAndDraw( { // We have to turn the rectangle into two triangles, so 6 points. Sigh. - // TODO: there's supposed to be extra magic here to rotate the UV coordinates depending on if upside down etc. - // bottom right - *trans = transVtx; - trans++; - - // top left - *trans = transVtx; - trans->x = saved.x; - trans->uv[0] = saved.uv[0]; - trans->y = saved.y; - trans->uv[1] = saved.uv[1]; - trans++; - - // top right - *trans = transVtx; - trans->x = saved.x; - trans->uv[0] = saved.uv[0]; - trans++; + trans[0] = transVtx; // bottom left - *trans = transVtx; - trans->y = saved.y; - trans->uv[1] = saved.uv[1]; - trans++; - - // bottom right - *trans = transVtx; - trans->x = saved.x; - trans->uv[0] = saved.uv[0]; - trans->y = saved.y; - trans->uv[1] = saved.uv[1]; - trans++; + trans[1] = transVtx; + trans[1].y = saved.y; + trans[1].v = saved.v; // top left - *trans = transVtx; - trans++; + trans[2] = transVtx; + trans[2].x = saved.x; + trans[2].y = saved.y; + trans[2].u = saved.u; + trans[2].v = saved.v; + + // top right + trans[3] = transVtx; + trans[3].x = saved.x; + trans[3].u = saved.u; + + // That's the four corners. Now process UV rotation. + RotateUVs(trans); + + // bottom right + trans[4] = trans[0]; + + // top left + trans[5] = trans[2]; + trans += 6; numTrans += 6; } @@ -605,8 +606,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } -void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) -{ +void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { // For the future if (!indexGen.PrimCompatible(prim)) Flush(); @@ -628,7 +628,6 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert // Decode the verts and apply morphing dec.DecodeVerts(decoded + numVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); numVerts += indexUpperBound - indexLowerBound + 1; - if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); @@ -676,19 +675,13 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert void TransformDrawEngine::Flush() { if (indexGen.Empty()) return; - // From here on out, the index type is ALWAYS 16-bit. Deal with it. - - // And here we should return, having collected the morphed but untransformed vertices. - // Note that DecodeVerts should convert strips into indexed lists etc, adding to our - // current vertex buffer and index buffer. - - // The rest below here should only execute on Flush. #if 0 for (int i = indexLowerBound; i <= indexUpperBound; i++) { PrintDecodedVertex(decoded[i], gstate.vertType); } #endif + // Check if anything needs updating if (gstate_c.textureChanged) { if ((gstate.textureMapEnable & 1) && !gstate.isModeClear()) { @@ -712,7 +705,15 @@ void TransformDrawEngine::Flush() { if (CanUseHardwareTransform(prim)) { SetupDecFmtForDraw(program, dec.GetDecVtxFmt(), decoded); - glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); + // If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS, + // there is no need for the index buffer we built. We can then use glDrawArrays instead + // for a very minor speed boost. + int seen = indexGen.SeenPrims() | 0x83204820; + if (seen == (1 << GE_PRIM_TRIANGLES) || seen == (1 << GE_PRIM_LINES) || seen == (1 << GE_PRIM_POINTS)) { + glDrawArrays(glprim[prim], 0, indexGen.VertexCount()); + } else { + glDrawElements(glprim[prim], indexGen.VertexCount(), GL_UNSIGNED_SHORT, (GLvoid *)decIndex); + } DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { SoftwareTransformAndDraw(prim, decoded, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index d41e5f1fd2..ef34677eb1 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -54,7 +54,7 @@ struct DecVtxFormat { struct TransformedVertex { float x, y, z; // in case of morph, preblend during decode - float uv[2]; // scaled by uscale, vscale, if there + float u; float v; // scaled by uscale, vscale, if there float color0[4]; // prelit float color1[3]; // prelit }; From 27e8e4c6fb2d9114dcff328e0021e90939225533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 09:07:52 +0100 Subject: [PATCH 194/276] Stop ADPCM decoder from running off into space. improves motogp audio. --- Core/HW/SasAudio.cpp | 14 ++++++++------ Core/HW/SasAudio.h | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 8b1e50f445..0049c2b65c 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -27,11 +27,11 @@ static const double f[5][2] = { 98.0 / 64.0, -55.0 / 64.0 }, { 122.0 / 64.0, -60.0 / 64.0 } }; -void VagDecoder::Start(u8 *data, bool loopEnabled) -{ +void VagDecoder::Start(u8 *data, int vagSize, bool loopEnabled) { loopEnabled_ = loopEnabled; loopAtNextBlock_ = false; loopStartBlock_ = 0; + numBlocks_ = vagSize / 16; end_ = false; data_ = data; read_ = data; @@ -41,8 +41,7 @@ void VagDecoder::Start(u8 *data, bool loopEnabled) s_2 = 0.0; } -bool VagDecoder::DecodeBlock() -{ +bool VagDecoder::DecodeBlock() { int predict_nr = GetByte(); int shift_factor = predict_nr & 0xf; predict_nr >>= 4; @@ -71,6 +70,9 @@ bool VagDecoder::DecodeBlock() } curSample = 0; curBlock_++; + if (curBlock_ == numBlocks_) { + end_ = true; + } return true; } @@ -307,7 +309,7 @@ void SasVoice::KeyOn() { switch (type) { case VOICETYPE_VAG: if (Memory::IsValidAddress(vagAddr)) { - vag.Start(Memory::GetPointer(vagAddr), loop); + vag.Start(Memory::GetPointer(vagAddr), vagSize, loop); } else { ERROR_LOG(SAS, "Invalid VAG address %08x", vagAddr); return; @@ -330,7 +332,7 @@ void SasVoice::ChangedParams(bool changedVag) { if (!playing && on) { playing = true; if (changedVag) - vag.Start(Memory::GetPointer(vagAddr), loop); + vag.Start(Memory::GetPointer(vagAddr), vagSize, loop); } // TODO: restart VAG somehow } diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 411e0f5863..410a0df2e4 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -78,7 +78,7 @@ class VagDecoder { public: VagDecoder() : data_(0), read_(0) {} - void Start(u8 *data, bool loopEnabled); + void Start(u8 *data, int vagSize, bool loopEnabled); void GetSamples(s16 *outSamples, int numSamples); @@ -97,6 +97,7 @@ private: u8 *read_; int curBlock_; int loopStartBlock_; + int numBlocks_; // rolling state. start at 0, should probably reset to 0 on loops? double s_1; From c1041cfff2517bf2cd60d4b613ee5e16d44daa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 09:23:15 +0100 Subject: [PATCH 195/276] Apparently RECTANGLES shouldn't flip that way. --- GPU/GLES/TransformPipeline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 8935422d0a..7cbd383ebf 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -298,8 +298,10 @@ static void SwapUVs(TransformedVertex &a, TransformedVertex &b) { static void RotateUVs(TransformedVertex v[4]) { if (v[0].y < v[2].y && v[0].x > v[2].x) { - SwapUVs(v[0], v[2]); + // This appears to be wrong. + // SwapUVs(v[0], v[2]); } else if (v[0].y > v[2].y && v[0].x < v[2].x) { + // This works fine in Star Soldier. SwapUVs(v[1], v[3]); } } From 4b9b23dfb4001ad8aea495971cbf1bf863a18685 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 22:55:50 -0800 Subject: [PATCH 196/276] Correct arguments in sceIoGetAsyncStat(). --- Core/HLE/sceIo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 9f03b26d17..74bc480c8c 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -746,7 +746,7 @@ u32 sceIoReadAsync(int id, u32 data_addr, int size) return 0; } -u32 sceIoGetAsyncStat(int id, u32 address, u32 uknwn) +u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) { u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); @@ -754,7 +754,7 @@ u32 sceIoGetAsyncStat(int id, u32 address, u32 uknwn) { Memory::Write_U64(f->asyncResult, address); DEBUG_LOG(HLE, "%i = sceIoGetAsyncStat(%i, %i, %08x) (HACK)", - (u32) f->asyncResult, id, address, uknwn); + (u32) f->asyncResult, id, poll, address); return 0; //completed } else From b2ef54e1941a1e00b35f60181354b1216fd25325 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 23:02:53 -0800 Subject: [PATCH 197/276] Make waiting on async IO reschedule. --- Core/HLE/sceIo.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 74bc480c8c..fb635bc0e0 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -755,6 +755,8 @@ u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) Memory::Write_U64(f->asyncResult, address); DEBUG_LOG(HLE, "%i = sceIoGetAsyncStat(%i, %i, %08x) (HACK)", (u32) f->asyncResult, id, poll, address); + if (!poll) + hleReSchedule("io waited"); return 0; //completed } else @@ -764,7 +766,7 @@ u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) } } -void sceIoWaitAsync(int id, u32 address, u32 uknwn) { +int sceIoWaitAsync(int id, u32 address) { u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { @@ -775,15 +777,16 @@ void sceIoWaitAsync(int id, u32 address, u32 uknwn) { } Memory::Write_U64(res, address); DEBUG_LOG(HLE, "%i = sceIoWaitAsync(%i, %08x) (HACK)", (u32) res, id, - uknwn); - RETURN(0); //completed + address); + hleReSchedule("io waited"); + return 0; //completed } else { ERROR_LOG(HLE, "ERROR - sceIoWaitAsync waiting for invalid id %i", id); - RETURN(-1); + return -1; } } -void sceIoWaitAsyncCB(int id, u32 address) { +int sceIoWaitAsyncCB(int id, u32 address) { // Should process callbacks here u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); @@ -796,10 +799,13 @@ void sceIoWaitAsyncCB(int id, u32 address) { Memory::Write_U64(res, address); DEBUG_LOG(HLE, "%i = sceIoWaitAsyncCB(%i, %08x) (HACK)", (u32) res, id, address); - RETURN(0); //completed + hleCheckCurrentCallbacks(); + hleReSchedule(true, "io waited"); + return 0; //completed } else { ERROR_LOG(HLE, "ERROR - sceIoWaitAsyncCB waiting for invalid id %i", id); + return -1; } } @@ -946,8 +952,8 @@ const HLEFunction IoFileMgrForUser[] = { { 0x6d08a871, 0, "sceIoUnassign" }, { 0x42EC03AC, &WrapU_IVI, "sceIoWrite" }, //(int fd, void *data, int size); { 0x0facab19, 0, "sceIoWriteAsync" }, - { 0x35dbd746, &WrapV_IU, "sceIoWaitAsyncCB" }, - { 0xe23eec33, &WrapV_IUU, "sceIoWaitAsync" }, + { 0x35dbd746, &WrapI_IU, "sceIoWaitAsyncCB" }, + { 0xe23eec33, &WrapI_IU, "sceIoWaitAsync" }, }; void Register_IoFileMgrForUser() { From f75f2748b1d9c346c05ff40de4c270ac35fcd731 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 23:04:06 -0800 Subject: [PATCH 198/276] Tests show io open also rescheds, async or not. --- Core/HLE/sceIo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index fb635bc0e0..62b64e79e3 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -382,6 +382,8 @@ u32 sceIoOpen(const char* filename, int mode) { if (mode & O_CREAT) access |= FILEACCESS_CREATE; + hleReSchedule("file opened"); + u32 h = pspFileSystem.OpenFile(filename, (FileAccess) access); if (h == 0) { From a4154dbc171a161a281dba407b7721587791bf36 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 23:25:17 -0800 Subject: [PATCH 199/276] Clean up a few IO wrappers with deferred HLE. --- Core/HLE/FunctionWrappers.h | 5 ++++ Core/HLE/sceIo.cpp | 47 ++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 4185bdcdae..2795e24c4f 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -444,6 +444,11 @@ template void WrapU_CI() { RETURN(retval); } +template void WrapU_CII() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2)); + RETURN(retval); +} + template void WrapU_CIUIU() { int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 62b64e79e3..3b7c7612a4 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -370,16 +370,16 @@ u32 sceIoLseek32(int id, int offset, int whence) { } } -u32 sceIoOpen(const char* filename, int mode) { +u32 sceIoOpen(const char* filename, int flags, int mode) { //memory stick filename int access = FILEACCESS_NONE; - if (mode & O_RDONLY) + if (flags & O_RDONLY) access |= FILEACCESS_READ; - if (mode & O_WRONLY) + if (flags & O_WRONLY) access |= FILEACCESS_WRITE; - if (mode & O_APPEND) + if (flags & O_APPEND) access |= FILEACCESS_APPEND; - if (mode & O_CREAT) + if (flags & O_CREAT) access |= FILEACCESS_CREATE; hleReSchedule("file opened"); @@ -388,8 +388,8 @@ u32 sceIoOpen(const char* filename, int mode) { if (h == 0) { ERROR_LOG(HLE, - "ERROR_ERRNO_FILE_NOT_FOUND=sceIoOpen(%s, %08x) - file not found", - filename, mode); + "ERROR_ERRNO_FILE_NOT_FOUND=sceIoOpen(%s, %08x, %08x) - file not found", + filename, flags, mode); return ERROR_ERRNO_FILE_NOT_FOUND; } @@ -398,7 +398,7 @@ u32 sceIoOpen(const char* filename, int mode) { f->handle = h; f->fullpath = filename; f->asyncResult = id; - DEBUG_LOG(HLE, "%i=sceIoOpen(%s, %08x)", id, filename, mode); + DEBUG_LOG(HLE, "%i=sceIoOpen(%s, %08x, %08x)", id, filename, flags, mode); return id; } @@ -675,10 +675,10 @@ u32 sceIoChdir(const char *dirname) { return 1; } -void sceIoChangeAsyncPriority() +int sceIoChangeAsyncPriority(int id, int priority) { - ERROR_LOG(HLE, "UNIMPL sceIoChangeAsyncPriority(%d)", PARAM(0)); - RETURN(0); + ERROR_LOG(HLE, "UNIMPL sceIoChangeAsyncPriority(%d, %d)", id, priority); + return 0; } u32 __IoClose(SceUID id, int param) @@ -688,13 +688,12 @@ u32 __IoClose(SceUID id, int param) return kernelObjects.Destroy < FileNode > (id); } -//TODO Not really sure if this should be wrapped nor how -void sceIoCloseAsync() +int sceIoCloseAsync(SceUID id) { - DEBUG_LOG(HLE, "sceIoCloseAsync(%d)", PARAM(0)); + DEBUG_LOG(HLE, "sceIoCloseAsync(%d)", id); //sceIoClose(); defAction = &__IoClose; - RETURN(0); + return 0; } u32 sceIoLseekAsync(int id, s64 offset, int whence) @@ -731,13 +730,13 @@ u32 sceIoLseek32Async(int id, int offset, int whence) return 0; } -void sceIoOpenAsync(const char *filename, int mode) +u32 sceIoOpenAsync(const char *filename, int flags, int mode) { DEBUG_LOG(HLE, "sceIoOpenAsync() sorta implemented"); - RETURN(sceIoOpen(filename, mode)); -// __IoCompleteAsyncIO(currentMIPS->r[2]); // The return value - // We have to return a UID here, which may have been destroyed when we reach Wait if it failed. - // Now that we're just faking it, we just don't RETURN(0) here. + u32 fd = sceIoOpen(filename, flags, mode); + //__IoCompleteAsyncIO(fd); // The return value + // We have to return an fd here, which may have been destroyed when we reach Wait if it failed. + return fd; } u32 sceIoReadAsync(int id, u32 data_addr, int size) @@ -931,17 +930,17 @@ const HLEFunction IoFileMgrForUser[] = { { 0x08bd7374, 0, "sceIoGetDevType" }, { 0xB2A628C1, &WrapU_CCCU, "sceIoAssign" }, { 0xe8bc6571, 0, "sceIoCancel" }, - { 0xb293727f, sceIoChangeAsyncPriority, "sceIoChangeAsyncPriority" }, + { 0xb293727f, &WrapI_II, "sceIoChangeAsyncPriority" }, { 0x810C4BC3, &WrapU_I, "sceIoClose" }, //(int fd); - { 0xff5940b6, sceIoCloseAsync, "sceIoCloseAsync" }, + { 0xff5940b6, &WrapI_I, "sceIoCloseAsync" }, { 0x54F5FB11, &WrapU_CIUIUI, "sceIoDevctl" }, //(const char *name int cmd, void *arg, size_t arglen, void *buf, size_t *buflen); { 0xcb05f8d6, &WrapU_IUU, "sceIoGetAsyncStat" }, { 0x27EB27B8, &WrapI64_II64I, "sceIoLseek" }, //(int fd, int offset, int whence); { 0x68963324, &WrapU_III, "sceIoLseek32" }, { 0x1b385d8f, &WrapU_III, "sceIoLseek32Async" }, { 0x71b19e77, &WrapU_II64I, "sceIoLseekAsync" }, - { 0x109F50BC, &WrapU_CI, "sceIoOpen" }, //(const char* file, int mode); - { 0x89AA9906, &WrapV_CI, "sceIoOpenAsync" }, + { 0x109F50BC, &WrapU_CII, "sceIoOpen" }, //(const char* file, int mode); + { 0x89AA9906, &WrapU_CII, "sceIoOpenAsync" }, { 0x06A70004, &WrapU_CI, "sceIoMkdir" }, //(const char *dir, int mode); { 0x3251ea56, &WrapU_IU, "sceIoPollAsync" }, { 0x6A638D83, &WrapU_IUI, "sceIoRead" }, //(int fd, void *data, int size); From 8d946a7a3a478ba0827f11f6c57b6a93e6f73eea Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Dec 2012 23:39:34 -0800 Subject: [PATCH 200/276] Ensure we don't close the wrong fd in async io. --- Core/HLE/sceIo.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 3b7c7612a4..25f7869e72 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -681,18 +681,20 @@ int sceIoChangeAsyncPriority(int id, int priority) return 0; } -u32 __IoClose(SceUID id, int param) +u32 __IoClose(SceUID actedFd, int closedFd) { - DEBUG_LOG(HLE, "Deferred IoClose(%d)", id); - __IoCompleteAsyncIO(id); - return kernelObjects.Destroy < FileNode > (id); + DEBUG_LOG(HLE, "Deferred IoClose(%d, %d)", actedFd, closedFd); + __IoCompleteAsyncIO(closedFd); + return kernelObjects.Destroy < FileNode > (closedFd); } int sceIoCloseAsync(SceUID id) { DEBUG_LOG(HLE, "sceIoCloseAsync(%d)", id); //sceIoClose(); + // TODO: Not sure this is a good solution. Seems like you can defer one per fd. defAction = &__IoClose; + defParam = id; return 0; } From be779d7f77ed1be9f2934c9c54d6a04d8c82236c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 00:12:35 -0800 Subject: [PATCH 201/276] Actually run callbacks for async IO. Probably needs to actually be delayed though. --- Core/HLE/sceIo.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 25f7869e72..dfea927df2 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -224,7 +224,7 @@ void __IoCompleteAsyncIO(SceUID id) { FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { if (f->callbackID) { - // __KernelNotifyCallbackType(THREAD_CALLBACK_IO, __KernelGetCurThread(), f->callbackID, f->callbackArg); + __KernelNotifyCallback(THREAD_CALLBACK_IO, f->callbackID, f->callbackArg); } } } @@ -714,9 +714,12 @@ u32 sceIoSetAsyncCallback(int id, u32 clbckId, u32 clbckArg) FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { + // TODO: Check replacing / updating? f->callbackID = clbckId; f->callbackArg = clbckArg; - return 0; + // TODO: Not sure when this is unregistered? + error = __KernelRegisterCallback(THREAD_CALLBACK_IO, clbckId); + return error; } else { @@ -736,7 +739,8 @@ u32 sceIoOpenAsync(const char *filename, int flags, int mode) { DEBUG_LOG(HLE, "sceIoOpenAsync() sorta implemented"); u32 fd = sceIoOpen(filename, flags, mode); - //__IoCompleteAsyncIO(fd); // The return value + // TODO: This can't actually have a callback yet, but if it's set before waiting, it should be called. + __IoCompleteAsyncIO(fd); // We have to return an fd here, which may have been destroyed when we reach Wait if it failed. return fd; } From 0587104c16024b9c8e6bca3b109a9930caa791ad Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 02:17:47 -0800 Subject: [PATCH 202/276] No need to register now, actually. Was using NotifyCallbackType before but that wasn't necessary anyway, so this is cleaner/better. --- Core/HLE/sceIo.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index dfea927df2..179a9fe445 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -717,9 +717,7 @@ u32 sceIoSetAsyncCallback(int id, u32 clbckId, u32 clbckArg) // TODO: Check replacing / updating? f->callbackID = clbckId; f->callbackArg = clbckArg; - // TODO: Not sure when this is unregistered? - error = __KernelRegisterCallback(THREAD_CALLBACK_IO, clbckId); - return error; + return 0; } else { From 724640d3080a98ea2c3e74fcdbbc157e629a7a1d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 02:23:04 -0800 Subject: [PATCH 203/276] Revert rescheduling in sceIoOpen(). Broke Orbit and Breakquest, maybe my tests are wrong. Scheduling is hard. This reverts commit f75f2748b1d9c346c05ff40de4c270ac35fcd731. --- Core/HLE/sceIo.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 179a9fe445..2523539a0a 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -382,8 +382,6 @@ u32 sceIoOpen(const char* filename, int flags, int mode) { if (flags & O_CREAT) access |= FILEACCESS_CREATE; - hleReSchedule("file opened"); - u32 h = pspFileSystem.OpenFile(filename, (FileAccess) access); if (h == 0) { From df04bbe4dd118ca134f156d9e93b6f91e725d0cf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 03:30:08 -0800 Subject: [PATCH 204/276] Fix a crash when switching between jit/interp. --- Core/MIPS/MIPS.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 477b2dd4f7..e4fa5549fe 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -53,7 +53,11 @@ MIPSState::~MIPSState() void MIPSState::Reset() { if (MIPSComp::jit) + { delete MIPSComp::jit; + MIPSComp::jit = 0; + } + if (PSP_CoreParameter().cpuCore == CPU_JIT) MIPSComp::jit = new MIPSComp::Jit(this); From ddfa56e0f2dab808d64228c3507603996b871432 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 04:02:33 -0800 Subject: [PATCH 205/276] Fix GetMemoryBlockPtr() to take both arguments. --- Core/HLE/sceKernelMemory.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 4034b096dd..8afa2dd40e 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -634,11 +634,11 @@ void sceKernelReferVplStatus() // TODO: Make proper kernel objects for these instead of using the UID as a pointer. u32 AllocMemoryBlock(const char *pname, u32 type, u32 size, u32 paramsAddr) { - INFO_LOG(HLE,"AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %i, %08x)", pname, type, size, paramsAddr); // Just support allocating a block in the user region. - u32 blockPtr = userMemory.Alloc(size, false, pname); + u32 blockPtr = userMemory.Alloc(size, type == 1, pname); + INFO_LOG(HLE,"%08x=AllocMemoryBlock(SysMemUserForUser_FE707FDF)(%s, %i, %08x, %08x)", blockPtr, pname, type, size, paramsAddr); // Create a UID object??? Nah, let's just us the UID itself (hack!) @@ -646,14 +646,15 @@ u32 AllocMemoryBlock(const char *pname, u32 type, u32 size, u32 paramsAddr) { } u32 FreeMemoryBlock(u32 uid) { - INFO_LOG(HLE, "FreeMemoryBlock(%i)", uid); + INFO_LOG(HLE, "FreeMemoryBlock(%08x)", uid); userMemory.Free(uid); return 0; } -u32 GetMemoryBlockPtr(u32 uid) { - INFO_LOG(HLE, "GetMemoryBlockPtr(%i)", uid); - return uid; +u32 GetMemoryBlockPtr(u32 uid, u32 addr) { + INFO_LOG(HLE, "GetMemoryBlockPtr(%08x, %08x)", uid, addr); + Memory::Write_U32(uid, addr); + return 0; } u32 sceKernelSetCompiledSdkVersion(u32 param) { @@ -691,7 +692,7 @@ const HLEFunction SysMemUserForUser[] = { {0x358ca1bb,0,"sceKernelSetCompiledSdkVersion606"}, // Obscure raw block API - {0xDB83A952,WrapU_U,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr + {0xDB83A952,WrapU_UU,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr {0x91DE343C,0,"SysMemUserForUser_91DE343C"}, {0x50F61D8A,WrapU_U,"SysMemUserForUser_50F61D8A"}, // FreeMemoryBlock {0xFE707FDF,WrapU_CUUU,"SysMemUserForUser_FE707FDF"}, // AllocMemoryBlock From ddd3e4384f714382844a0c6948ea8b459a8a67aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 11:36:47 +0100 Subject: [PATCH 206/276] audio: need to clear the rest of the buffer at end of sample. --- Core/HW/SasAudio.cpp | 10 +++++++--- Core/HW/SasAudio.h | 5 ++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 0049c2b65c..ed17365368 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -41,14 +41,14 @@ void VagDecoder::Start(u8 *data, int vagSize, bool loopEnabled) { s_2 = 0.0; } -bool VagDecoder::DecodeBlock() { +void VagDecoder::DecodeBlock() { int predict_nr = GetByte(); int shift_factor = predict_nr & 0xf; predict_nr >>= 4; int flags = GetByte(); if (flags == 7) { end_ = true; - return false; + return; } else if (flags == 6) { loopStartBlock_ = curBlock_; @@ -73,7 +73,6 @@ bool VagDecoder::DecodeBlock() { if (curBlock_ == numBlocks_) { end_ = true; } - return true; } void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { @@ -90,6 +89,11 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { s_2 = 0.0; } DecodeBlock(); + if (end_) { + // Clear the rest of the buffer and return. + memset(&outSamples[i], 0, (numSamples - i) * sizeof(s16)); + return; + } } outSamples[i] = end_ ? 0 : samples[curSample++]; } diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 410a0df2e4..b32ba7d347 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -74,15 +74,14 @@ enum VoiceType { // It compresses 28 16-bit samples into a block of 16 bytes. // TODO: Get rid of the doubles, making sure it does not impact sound quality. // Doubles are pretty fast on Android devices these days though. -class VagDecoder -{ +class VagDecoder { public: VagDecoder() : data_(0), read_(0) {} void Start(u8 *data, int vagSize, bool loopEnabled); void GetSamples(s16 *outSamples, int numSamples); - bool DecodeBlock(); + void DecodeBlock(); bool End() const { return end_; } u8 GetByte() { From 35f60501c10b02743d15615c2c8c5a011bcce867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 19:30:46 +0100 Subject: [PATCH 207/276] Update a function name --- Core/HLE/sceKernelMemory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 8afa2dd40e..5513850417 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -682,18 +682,18 @@ const HLEFunction SysMemUserForUser[] = { {0xB6D61D02,sceKernelFreePartitionMemory,"sceKernelFreePartitionMemory"}, //(void *ptr) ? {0x9D9A5BA1,sceKernelGetBlockHeadAddr,"sceKernelGetBlockHeadAddr"}, //(void *ptr) ? {0x13a5abef,sceKernelPrintf,"sceKernelPrintf 0x13a5abef"}, + {0xf77d77cb,WrapU_UUUU,"sceKernelSetCompilerVersion"}, {0x7591c7db,WrapU_U,"sceKernelSetCompiledSdkVersion"}, {0x342061E5,0,"sceKernelSetCompiledSdkVersion370"}, {0x315AD3A0,0,"sceKernelSetCompiledSdkVersion380_390"}, {0xEBD5C3E6,WrapU_U,"sceKernelSetCompiledSdkVersion395"}, - {0xf77d77cb,WrapU_UUUU,"sceKernelSetCompilerVersion"}, + {0x91DE343C,0,"sceKernelSetCompiledSdkVersion_500_505"}, {0x35669d4c,0,"sceKernelSetCompiledSdkVersion600_602"}, //?? {0x1b4217bc,0,"sceKernelSetCompiledSdkVersion603_605"}, {0x358ca1bb,0,"sceKernelSetCompiledSdkVersion606"}, // Obscure raw block API {0xDB83A952,WrapU_UU,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr - {0x91DE343C,0,"SysMemUserForUser_91DE343C"}, {0x50F61D8A,WrapU_U,"SysMemUserForUser_50F61D8A"}, // FreeMemoryBlock {0xFE707FDF,WrapU_CUUU,"SysMemUserForUser_FE707FDF"}, // AllocMemoryBlock }; From 3872753b8acc6a1051c48c6a6f527998cf58b831 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 11:32:51 -0800 Subject: [PATCH 208/276] Highlight changed regs in the Windows debugger. --- Windows/Debugger/CtrlRegisterList.cpp | 26 ++++++++++++++++++++++++-- Windows/Debugger/CtrlRegisterList.h | 10 ++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Windows/Debugger/CtrlRegisterList.cpp b/Windows/Debugger/CtrlRegisterList.cpp index db610d1028..b86b0b7dca 100644 --- a/Windows/Debugger/CtrlRegisterList.cpp +++ b/Windows/Debugger/CtrlRegisterList.cpp @@ -128,12 +128,19 @@ CtrlRegisterList::CtrlRegisterList(HWND _wnd) category=0; showHex=false; cpu=0; + lastPC = 0; + lastCat0Values = NULL; + changedCat0Regs = NULL; } CtrlRegisterList::~CtrlRegisterList() { DeleteObject(font); + if (lastCat0Values != NULL) + delete [] lastCat0Values; + if (changedCat0Regs != NULL) + delete [] changedCat0Regs; } void fillRect(HDC hdc, RECT *rect, COLORREF colour); @@ -214,6 +221,18 @@ void CtrlRegisterList::onPaint(WPARAM wParam, LPARAM lParam) Rectangle(hdc,16,rowY1,width,rowY2); + // Check for any changes in the registers. + if (lastPC != cpu->GetPC()) + { + for (int i = 0, n = cpu->GetNumRegsInCategory(0); i < n; ++i) + { + u32 v = cpu->GetRegValue(0, i); + changedCat0Regs[i] = v != lastCat0Values[i]; + lastCat0Values[i] = v; + } + lastPC = cpu->GetPC(); + } + SelectObject(hdc,currentBrush); DeleteObject(mojsBrush); if (iGetNumRegsInCategory(category)) @@ -225,10 +244,13 @@ void CtrlRegisterList::onPaint(WPARAM wParam, LPARAM lParam) SetTextColor(hdc,0x000000); cpu->PrintRegValue(category,i,temp); - SetTextColor(hdc,0x004000); + if (category == 0 && changedCat0Regs[i]) + SetTextColor(hdc, 0x0000FF); + else + SetTextColor(hdc,0x004000); TextOut(hdc,77,rowY1,temp,strlen(temp)); } - + /* } diff --git a/Windows/Debugger/CtrlRegisterList.h b/Windows/Debugger/CtrlRegisterList.h index ff55ff39ef..f45f980f6b 100644 --- a/Windows/Debugger/CtrlRegisterList.h +++ b/Windows/Debugger/CtrlRegisterList.h @@ -40,6 +40,10 @@ class CtrlRegisterList DebugInterface *cpu; static TCHAR szClassName[]; + u32 lastPC; + u32 *lastCat0Values; + bool *changedCat0Regs; + public: CtrlRegisterList(HWND _wnd); ~CtrlRegisterList(); @@ -60,6 +64,12 @@ public: void setCPU(DebugInterface *deb) { cpu = deb; + + int regs = cpu->GetNumRegsInCategory(0); + lastCat0Values = new u32[regs]; + changedCat0Regs = new bool[regs]; + memset(lastCat0Values, 0, regs * sizeof(u32)); + memset(changedCat0Regs, 0, regs * sizeof(bool)); } DebugInterface *getCPU() { From fcc5bfee990f22861c9e0c87bbaeec0c17ab8170 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 13:36:10 -0800 Subject: [PATCH 209/276] Add more atrac3 stubs to get games farther. --- Core/HLE/sceAtrac.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index ae6b3e8589..ca31dba60d 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -59,7 +59,7 @@ u32 sceAtracEndEntry() u32 sceAtracGetAtracID(int codecType) { ERROR_LOG(HLE, "UNIMPL sceAtracGetAtracID(%i)", codecType); - return 0; + return 1; } u32 sceAtracGetBufferInfoForReseting(int atracID, int sample, u32 bufferInfoAddr) @@ -95,6 +95,8 @@ u32 sceAtracGetInternalErrorInfo(int atracID, u32 errorAddr) u32 sceAtracGetMaxSample(int atracID, u32 maxSamplesAddr) { ERROR_LOG(HLE, "UNIMPL sceAtracGetMaxSample(%i, %08x)", atracID, maxSamplesAddr); + if (Memory::IsValidAddress(maxSamplesAddr)) + Memory::Write_U32(1024, maxSamplesAddr); return 0; } @@ -205,6 +207,19 @@ int sceAtracReinit() return 0; } +int sceAtracGetOutputChannel(int atracID, u32 outputChanPtr) +{ + ERROR_LOG(HLE, "UNIMPL sceAtracGetOutputChannel(%i, %08x)", atracID, outputChanPtr); + if (Memory::IsValidAddress(outputChanPtr)) + Memory::Write_U32(2, outputChanPtr); + return 0; +} + +int sceAtracIsSecondBufferNeeded(int atracID) +{ + ERROR_LOG(HLE, "UNIMPL sceAtracIsSecondBufferNeeded(%i)", atracID); + return 0; +} const HLEFunction sceAtrac3plus[] = { @@ -233,10 +248,16 @@ const HLEFunction sceAtrac3plus[] = {0xd1f59fdb,WrapU_V,"sceAtracStartEntry"}, {0x868120b5,WrapU_II,"sceAtracSetLoopNum"}, {0x132f1eca,WrapI_V,"sceAtracReinit"}, - {0xeca32a99,0,"sceAtracIsSecondBufferNeeded"}, + {0xeca32a99,WrapI_I,"sceAtracIsSecondBufferNeeded"}, {0x0fae370e,WrapI_IUUU,"sceAtracSetHalfwayBufferAndGetID"}, - {0x2DD3E298,0,"sceAtrac3plus_2DD3E298"}, + {0x2DD3E298,0,"sceAtracGetBufferInfoForResetting"}, {0x5CF9D852,0,"sceAtracSetMOutHalfwayBuffer"}, + {0xB3B5D042,WrapI_IU,"sceAtracGetOutputChannel"}, + {0xF6837A1A,0,"sceAtracSetMOutData"}, + {0x472E3825,0,"sceAtracSetMOutDataAndGetID"}, + {0x9CD7DE03,0,"sceAtracSetMOutHalfwayBufferAndGetID"}, + {0x5622B7C1,0,"sceAtracSetAA3DataAndGetID"}, + {0x5DD66588,0,"sceAtracSetAA3HalfwayBufferAndGetID"}, }; From 709df11c9e565860d589098cb7a10971135908a5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 17:33:56 -0800 Subject: [PATCH 210/276] Stub out mode 12 so games think it's working. --- Core/Dialog/PSPSaveDialog.cpp | 9 +++++++++ Core/Dialog/PSPSaveDialog.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 5fad54b585..2660f562eb 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -91,6 +91,7 @@ int PSPSaveDialog::Init(int paramAddr) { ERROR_LOG(HLE, "Load/Save function %d not coded. Title: %s Save: %s File: %s", param.GetPspParam()->mode, param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str()); param.GetPspParam()->result = 0; + status = SCE_UTILITY_STATUS_INITIALIZE; display = DS_NONE; return 0; // Return 0 should allow the game to continue, but missing function must be implemented and returning the right value or the game can block. } @@ -664,10 +665,18 @@ int PSPSaveDialog::Update() param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; } status = SCE_UTILITY_STATUS_FINISHED; + // TODO: intentional missing break? case SCE_UTILITY_SAVEDATA_TYPE_LIST: param.GetList(param.GetPspParam()); param.GetPspParam()->result = 0; status = SCE_UTILITY_STATUS_FINISHED; + break; + // TODO: Don't know the name? + case 12: + // Pretend we have nothing, always. + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + status = SCE_UTILITY_STATUS_FINISHED; + break; default: status = SCE_UTILITY_STATUS_FINISHED; break; diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index 14034e6fa2..c8149b7702 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -30,6 +30,8 @@ #define SCE_UTILITY_SAVEDATA_ERROR_LOAD_PARAM (0x80110308) #define SCE_UTILITY_SAVEDATA_ERROR_LOAD_INTERNAL (0x8011030b) +#define SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA (0x80110327) + #define SCE_UTILITY_SAVEDATA_ERROR_SAVE_NO_MS (0x80110381) #define SCE_UTILITY_SAVEDATA_ERROR_SAVE_EJECT_MS (0x80110382) #define SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE (0x80110383) From f5998d524a19ea6e369b2f0ae50475577dfd28c1 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Wed, 26 Dec 2012 10:56:18 -0800 Subject: [PATCH 211/276] Add HOST_IS_CASE_SENSITIVE define --- Core/FileSystems/DirectoryFileSystem.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 6b87c3f784..c187db572c 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -28,6 +28,26 @@ typedef void * HANDLE; #endif +#if defined(__APPLE__) + +#if TARGET_OS_IPHONE +#define HOST_IS_CASE_SENSITIVE true +#elif TARGET_IPHONE_SIMULATOR +#define HOST_IS_CASE_SENSITIVE false +#else +// Mac OSX case sensitivity defaults off, but is user configurable (when +// creating a filesytem), so assume the worst: +#define HOST_IS_CASE_SENSITIVE true +#endif + +#elif defined(_WIN32) || defined(__SYMBIAN32__) +#define HOST_IS_CASE_SENSITIVE false + +#else // Android, Linux, BSD (and the rest?) +#define HOST_IS_CASE_SENSITIVE true + +#endif + class DirectoryFileSystem : public IFileSystem { public: DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath); From a0e1ab1181ed2eaa94b01c99aa2df34e671ca4ba Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 02:20:00 -0800 Subject: [PATCH 212/276] Reindent. --- Core/FileSystems/DirectoryFileSystem.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index aa7185f07c..6340d05fe5 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -128,8 +128,8 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { entry.hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0); bool success = entry.hFile != INVALID_HANDLE_VALUE; #else - entry.hFile = fopen(fullName.c_str(), access & FILEACCESS_WRITE ? "wb" : "rb"); - bool success = entry.hFile != 0; + entry.hFile = fopen(fullName.c_str(), access & FILEACCESS_WRITE ? "wb" : "rb"); + bool success = entry.hFile != 0; #endif if (!success) { @@ -209,18 +209,18 @@ size_t DirectoryFileSystem::SeekFile(u32 handle, s32 position, FileMove type) { #ifdef _WIN32 DWORD moveMethod = 0; switch (type) { - case FILEMOVE_BEGIN: moveMethod = FILE_BEGIN; break; - case FILEMOVE_CURRENT: moveMethod = FILE_CURRENT; break; - case FILEMOVE_END: moveMethod = FILE_END; break; + case FILEMOVE_BEGIN: moveMethod = FILE_BEGIN; break; + case FILEMOVE_CURRENT: moveMethod = FILE_CURRENT; break; + case FILEMOVE_END: moveMethod = FILE_END; break; } DWORD newPos = SetFilePointer((*iter).second.hFile, (LONG)position, 0, moveMethod); return newPos; #else int moveMethod = 0; switch (type) { - case FILEMOVE_BEGIN: moveMethod = SEEK_SET; break; - case FILEMOVE_CURRENT: moveMethod = SEEK_CUR; break; - case FILEMOVE_END: moveMethod = SEEK_END; break; + case FILEMOVE_BEGIN: moveMethod = SEEK_SET; break; + case FILEMOVE_CURRENT: moveMethod = SEEK_CUR; break; + case FILEMOVE_END: moveMethod = SEEK_END; break; } fseek(iter->second.hFile, position, moveMethod); return ftell(iter->second.hFile); From 3839179a097d850bd9972c62f7d5cabb0a4cdc99 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 03:24:21 -0800 Subject: [PATCH 213/276] Implement opening for append in DirectoryFileSystem. Add more non-Windows access modes. --- Core/FileSystems/DirectoryFileSystem.cpp | 30 +++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 6340d05fe5..e076061c87 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -106,6 +106,7 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { OpenFileEntry entry; + //TODO: tests, should append seek to end of file? seeking in a file opened for append? #ifdef _WIN32 // Convert parameters to Windows permissions and access DWORD desired = 0; @@ -127,8 +128,35 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { //Let's do it! entry.hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0); bool success = entry.hFile != INVALID_HANDLE_VALUE; + + if (success && (access & FILEACCESS_APPEND)) { + SetFilePointer(entry.hFile, 0, NULL, FILE_END); + } #else - entry.hFile = fopen(fullName.c_str(), access & FILEACCESS_WRITE ? "wb" : "rb"); + // Convert flags in access parameter to fopen access mode + const char *mode = NULL; + if (access & FILEACCESS_APPEND) { + if (access & FILEACCESS_READ) + mode = "ab+"; // append+read, create if needed + else + mode = "ab"; // append only, create if needed + } else if (access & FILEACCESS_WRITE) { + if (access & FILEACCESS_READ) { + // FILEACCESS_CREATE is ignored for read only, write only, and append + // because C++ standard fopen's nonexistant file creation can only be + // customized for files opened read+write + if (access & FILEACCESS_CREATE) + mode = "wb+"; // read+write, create if needed + else + mode = "rb+"; // read+write, but don't create + } else { + mode = "wb"; // write only, create if needed + } + } else { // neither write nor append, so default to read only + mode = "rb"; + } + + entry.hFile = fopen(fullName.c_str(), mode); bool success = entry.hFile != 0; #endif From 928150fbf4a49ad94a7df32541d0eebe0af3c2b1 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 04:15:08 -0800 Subject: [PATCH 214/276] Add an ERROR_LOG for GetDirListing not implemented on non-Windows. --- Core/FileSystems/DirectoryFileSystem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index e076061c87..4e01590805 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -318,6 +318,8 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { if (!retval) break; } +#else + ERROR_LOG(HLE, "GetDirListing not implemented on non-Windows"); #endif return myVector; } From 725094eaefa003b95186e2fc7539bcad654b122e Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 04:23:04 -0800 Subject: [PATCH 215/276] Storing a size_t returned from std::string in an int and checking for negative is weird. --- Core/FileSystems/DirectoryFileSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 4e01590805..7b648ead8f 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -78,8 +78,8 @@ bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string std::string fullTo = to; // TO filename may not include path. Intention is that it uses FROM's path if (to.find("/") != std::string::npos) { - int offset = from.find_last_of("/"); - if (offset >= 0) { + size_t offset = from.find_last_of("/"); + if (offset != std::string::npos) { fullTo = from.substr(0, offset + 1) + to; } } From 9e85c01c1f03148beb85f0e92cfb9cb5d7ca78bb Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 04:27:07 -0800 Subject: [PATCH 216/276] Simulate case insensitivity on case sensitive platforms. --- Core/FileSystems/DirectoryFileSystem.cpp | 254 +++++++++++++++++++++-- Core/FileSystems/DirectoryFileSystem.h | 9 + 2 files changed, 245 insertions(+), 18 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 7b648ead8f..44d6dcfd2b 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -18,6 +18,7 @@ #ifdef _WIN32 #include #else +#include #include #include #endif @@ -25,8 +26,105 @@ #include "FileUtil.h" #include "DirectoryFileSystem.h" -// TODO: Simulate case insensitivity on Unix. -// NOTE: MacOSX is already case insensitive. + +#if HOST_IS_CASE_SENSITIVE + +static bool FixFilenameCase(const std::string &path, std::string &filename) +{ + // Are we lucky? + if (File::Exists(path + filename)) + return true; + + size_t filenameSize = filename.size(); + for (size_t i = 0; i < filenameSize; i++) + { + filename[i] = tolower(filename[i]); + } + + //TODO: lookup filename in cache for basePath + + struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; } diren; + struct dirent_large; + struct dirent *result = NULL; + + DIR *dirp = opendir(path.c_str()); + if (!dirp) + return false; + + bool retValue = false; + + while (!readdir_r(dirp, (dirent*) &diren, &result) && result) + { + if (result->d_namlen != filenameSize) + continue; + + size_t i; + for (i = 0; i < filenameSize; i++) + { + if (filename[i] != tolower(result->d_name[i])) + break; + } + + if (i < filenameSize) + continue; + + filename = result->d_name; + retValue = true; + } + + closedir(dirp); + + return retValue; +} + +bool DirectoryFileSystem::FixPathCase(std::string &path, FixPathCaseBehavior behavior) +{ + size_t len = path.size(); + + if (len == 0) + return true; + + if (path[len - 1] == '/') + { + len--; + + if (len == 0) + return true; + } + + std::string fullPath; + fullPath.reserve(basePath.size() + len + 1); + + fullPath.clear(); + fullPath.append(basePath); + + size_t start = 0; + while (start < len) + { + size_t i = path.find('/', start); + if (i == std::string::npos) + i = len; + + if (i > start) + { + std::string component = path.substr(start, i - start); + + if (FixFilenameCase(fullPath, component) == false) + return (behavior == FPC_FILE_MUST_EXIST || (behavior == FPC_PATH_MUST_EXIST && i >= len)); + + path.replace(start, i - start, component); + + fullPath.append(component); + fullPath.append(1, '/'); + } + + start = i + 1; + } + + return true; +} + +#endif DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath) : basePath(_basePath) { File::CreateFullPath(basePath); @@ -60,11 +158,37 @@ std::string DirectoryFileSystem::GetLocalPath(std::string localpath) { } bool DirectoryFileSystem::MkDir(const std::string &dirname) { + +#if HOST_IS_CASE_SENSITIVE + // Must fix case BEFORE attempting, because MkDir would create + // duplicate (different case) directories + + std::string fixedCase = dirname; + if ( ! FixPathCase(fixedCase, FPC_PARTIAL_ALLOWED) ) + return false; + + return File::CreateFullPath(GetLocalPath(fixedCase)); +#else return File::CreateFullPath(GetLocalPath(dirname)); +#endif } bool DirectoryFileSystem::RmDir(const std::string &dirname) { std::string fullName = GetLocalPath(dirname); + +#if HOST_IS_CASE_SENSITIVE + // Maybe we're lucky? + if (File::DeleteDirRecursively(fullName)) + return true; + + // Nope, fix case and try again + fullName = dirname; + if ( ! FixPathCase(fullName, FPC_FILE_MUST_EXIST) ) + return false; // or go on and attempt (for a better error code than just false?) + + fullName = GetLocalPath(fullName); +#endif + /*#ifdef _WIN32 return RemoveDirectory(fullName.c_str()) == TRUE; #else @@ -74,7 +198,6 @@ bool DirectoryFileSystem::RmDir(const std::string &dirname) { } bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string &to) { - std::string fullFrom = GetLocalPath(from); std::string fullTo = to; // TO filename may not include path. Intention is that it uses FROM's path if (to.find("/") != std::string::npos) { @@ -83,26 +206,85 @@ bool DirectoryFileSystem::RenameFile(const std::string &from, const std::string fullTo = from.substr(0, offset + 1) + to; } } - fullTo = GetLocalPath(fullTo); -#ifdef _WIN32 - return MoveFile(fullFrom.c_str(), fullTo.c_str()) == TRUE; -#else - return 0 == rename(fullFrom.c_str(), fullTo.c_str()); + std::string fullFrom = GetLocalPath(from); + +#if HOST_IS_CASE_SENSITIVE + // In case TO should overwrite a file with different case + if ( ! FixPathCase(fullTo, FPC_PATH_MUST_EXIST) ) + return false; // or go on and attempt (for a better error code than just false?) #endif + + fullTo = GetLocalPath(fullTo); + const char * fullToC = fullTo.c_str(); + +#ifdef _WIN32 + bool retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE); +#else + bool retValue = (0 == rename(fullFrom.c_str(), fullToC)); +#endif + +#if HOST_IS_CASE_SENSITIVE + if (! retValue) + { + // May have failed due to case sensitivity on FROM, so try again + fullFrom = from; + if ( ! FixPathCase(fullFrom, FPC_FILE_MUST_EXIST) ) + return false; // or go on and attempt (for a better error code than just false?) + fullFrom = GetLocalPath(fullFrom); + +#ifdef _WIN32 + retValue = (MoveFile(fullFrom.c_str(), fullToC) == TRUE); +#else + retValue = (0 == rename(fullFrom.c_str(), fullToC)); +#endif + } +#endif + + return retValue; } bool DirectoryFileSystem::DeleteFile(const std::string &filename) { std::string fullName = GetLocalPath(filename); #ifdef _WIN32 - return ::DeleteFile(fullName.c_str()) == TRUE; + bool retValue = (::DeleteFile(fullName.c_str()) == TRUE); #else - return 0 == unlink(fullName.c_str()); + bool retValue = (0 == unlink(fullName.c_str())); #endif + +#if HOST_IS_CASE_SENSITIVE + if (! retValue) + { + // May have failed due to case sensitivity, so try again + fullName = filename; + if ( ! FixPathCase(fullName, FPC_FILE_MUST_EXIST) ) + return false; // or go on and attempt (for a better error code than just false?) + fullName = GetLocalPath(fullName); + +#ifdef _WIN32 + retValue = (::DeleteFile(fullName.c_str()) == TRUE); +#else + retValue = (0 == unlink(fullName.c_str())); +#endif + } +#endif + + return retValue; } u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { +#if HOST_IS_CASE_SENSITIVE + if (access & (FILEACCESS_APPEND|FILEACCESS_CREATE|FILEACCESS_WRITE)) + { + DEBUG_LOG(HLE, "Checking case for path %s", filename.c_str()); + if ( ! FixPathCase(filename, FPC_PATH_MUST_EXIST) ) + return 0; // or go on and attempt (for a better error code than just 0?) + } + // else we try fopen first (in case we're lucky) before simulating case insensitivity +#endif + std::string fullName = GetLocalPath(filename); - INFO_LOG(HLE,"Actually opening %s (%s)", fullName.c_str(), filename.c_str()); + const char *fullNameC = fullName.c_str(); + INFO_LOG(HLE,"Actually opening %s (%s)", fullNameC, filename.c_str()); OpenFileEntry entry; @@ -126,12 +308,8 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { openmode = OPEN_EXISTING; } //Let's do it! - entry.hFile = CreateFile(fullName.c_str(), desired, sharemode, 0, openmode, 0, 0); + entry.hFile = CreateFile(fullNameC, desired, sharemode, 0, openmode, 0, 0); bool success = entry.hFile != INVALID_HANDLE_VALUE; - - if (success && (access & FILEACCESS_APPEND)) { - SetFilePointer(entry.hFile, 0, NULL, FILE_END); - } #else // Convert flags in access parameter to fopen access mode const char *mode = NULL; @@ -156,17 +334,48 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { mode = "rb"; } - entry.hFile = fopen(fullName.c_str(), mode); + entry.hFile = fopen(fullNameC, mode); bool success = entry.hFile != 0; #endif +#if HOST_IS_CASE_SENSITIVE + if (!success && + !(access & FILEACCESS_APPEND) && + !(access & FILEACCESS_CREATE) && + !(access & FILEACCESS_WRITE)) + { + if ( ! FixPathCase(filename, FPC_PATH_MUST_EXIST) ) + return 0; // or go on and attempt (for a better error code than just 0?) + fullName = GetLocalPath(filename); + fullNameC = fullName.c_str(); + + DEBUG_LOG(HLE, "Case may have been incorrect, second try opening %s (%s)", fullNameC, filename.c_str()); + + // And try again with the correct case this time +#ifdef _WIN32 + entry.hFile = CreateFile(fullNameC, desired, sharemode, 0, openmode, 0, 0); + success = entry.hFile != INVALID_HANDLE_VALUE; +#else + entry.hFile = fopen(fullNameC, mode); + success = entry.hFile != 0; +#endif + } +#endif + if (!success) { #ifdef _WIN32 ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, %i - access = %i", GetLastError(), (int)access); +#else + ERROR_LOG(HLE, "DirectoryFileSystem::OpenFile: FAILED, access = %i", (int)access); #endif //wwwwaaaaahh!! return 0; } else { +#ifdef _WIN32 + if (access & FILEACCESS_APPEND) + SetFilePointer(entry.hFile, 0, NULL, FILE_END); +#endif + u32 newHandle = hAlloc->GetNewHandle(); entries[newHandle] = entry; @@ -265,8 +474,17 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) { x.name = filename; std::string fullName = GetLocalPath(filename); - if (!File::Exists(fullName)) { + if (! File::Exists(fullName)) { +#if HOST_IS_CASE_SENSITIVE + if (! FixPathCase(filename, FPC_FILE_MUST_EXIST)) + return x; + fullName = GetLocalPath(filename); + + if (! File::Exists(fullName)) + return x; +#else return x; +#endif } x.type = File::IsDirectory(fullName) ? FILETYPE_NORMAL : FILETYPE_DIRECTORY; x.exists = true; diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index c187db572c..2de2ff9e2e 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -83,4 +83,13 @@ private: // In case of Windows: Translate slashes, etc. std::string GetLocalPath(std::string localpath); + +#if HOST_IS_CASE_SENSITIVE + typedef enum { + FPC_FILE_MUST_EXIST, // all path components must exist (rmdir, move from) + FPC_PATH_MUST_EXIST, // all except the last one must exist - still tries to fix last one (fopen, move to) + FPC_PARTIAL_ALLOWED, // don't care how many exist (mkdir recursive) + } FixPathCaseBehavior; + bool FixPathCase(std::string &path, FixPathCaseBehavior behavior); +#endif }; From 3862aea4deeb6b42b3a11b21031c71191b5b3cab Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 04:28:28 -0800 Subject: [PATCH 217/276] Minor comment edit. --- Core/FileSystems/DirectoryFileSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 44d6dcfd2b..fd7c4b8174 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -41,7 +41,7 @@ static bool FixFilenameCase(const std::string &path, std::string &filename) filename[i] = tolower(filename[i]); } - //TODO: lookup filename in cache for basePath + //TODO: lookup filename in cache for "path" struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; } diren; struct dirent_large; @@ -331,7 +331,7 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access) { mode = "wb"; // write only, create if needed } } else { // neither write nor append, so default to read only - mode = "rb"; + mode = "rb"; // read only, don't create } entry.hFile = fopen(fullNameC, mode); From 1c5ea9903197d6ed8340f96656b082ca258cabd4 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 05:14:06 -0800 Subject: [PATCH 218/276] Remove pointless string clear() --- Core/FileSystems/DirectoryFileSystem.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index fd7c4b8174..954dea960e 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -94,8 +94,6 @@ bool DirectoryFileSystem::FixPathCase(std::string &path, FixPathCaseBehavior beh std::string fullPath; fullPath.reserve(basePath.size() + len + 1); - - fullPath.clear(); fullPath.append(basePath); size_t start = 0; From 33429ebf930544ca097726740653980c6a44901b Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 05:27:13 -0800 Subject: [PATCH 219/276] Confirmed: PSP ignores .. beyond root. --- Core/FileSystems/MetaFileSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index b239a7657e..ed18b31a07 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -42,8 +42,8 @@ static bool ApplyPathStringToComponentsVector(std::vector &vector, } else { - // what does the real PSP do for "/../filename"? - WARN_LOG(HLE, "RealPath: .. as first path component: \"%s\"", pathString.c_str()); + // The PSP silently ignores attempts to .. to parent of root directory + WARN_LOG(HLE, "RealPath: ignoring .. beyond root - root directory is its own parent: \"%s\"", pathString.c_str()); } } else From 57ee25e239cc77fa9c5b8bc8ad4fa05a2f4aa177 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Thu, 27 Dec 2012 06:36:00 -0800 Subject: [PATCH 220/276] Fix brain fart. --- Core/FileSystems/DirectoryFileSystem.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 954dea960e..611f8b7e65 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -107,8 +107,12 @@ bool DirectoryFileSystem::FixPathCase(std::string &path, FixPathCaseBehavior beh { std::string component = path.substr(start, i - start); - if (FixFilenameCase(fullPath, component) == false) - return (behavior == FPC_FILE_MUST_EXIST || (behavior == FPC_PATH_MUST_EXIST && i >= len)); + // Fix case and stop on nonexistant path component + if (FixFilenameCase(fullPath, component) == false) { + // Still counts as success if partial matches allowed or if this + // is the last component and only the ones before it are required + return (behavior == FPC_PARTIAL_ALLOWED || (behavior == FPC_PATH_MUST_EXIST && i >= len)); + } path.replace(start, i - start, component); From a7af13b52391ebd678935d8a4f2ed1ac9c1a307c Mon Sep 17 00:00:00 2001 From: Arthur Blot Date: Thu, 27 Dec 2012 21:32:12 +0100 Subject: [PATCH 221/276] Implemented classic segment relocations --- Core/ELF/ElfReader.cpp | 243 ++++++++++++++++++++++------------------- Core/ELF/ElfReader.h | 2 + 2 files changed, 131 insertions(+), 114 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 36f5d08899..a397b9b1fa 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -50,6 +50,118 @@ void addrToHiLo(u32 addr, u16 &hi, s16 &lo) } } +void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs) +{ + for (int r = 0; r < numRelocs; r++) + { + u32 info = rels[r].r_info; + u32 addr = rels[r].r_offset; + + int type = info & 0xf; + + int readwrite = (info>>8) & 0xff; + int relative = (info>>16) & 0xff; + + //0 = code + //1 = data + + addr += segmentVAddr[readwrite]; + + u32 op = Memory::ReadUnchecked_U32(addr); + + const bool log = false; + //log=true; + if (log) + { + DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info); + } + u32 relocateTo = segmentVAddr[relative]; + +#define R_MIPS32 2 +#define R_MIPS26 4 +#define R_MIPS16_HI 5 +#define R_MIPS16_LO 6 + + switch (type) + { + case R_MIPS32: + if (log) + DEBUG_LOG(LOADER,"Full address reloc %08x", addr); + //full address, no problemo + op += relocateTo; + break; + + case R_MIPS26: //j, jal + //add on to put in correct address space + if (log) + DEBUG_LOG(LOADER,"j/jal reloc %08x", addr); + op = (op & 0xFC000000) | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF); + break; + + case R_MIPS16_HI: //lui part of lui-addiu pairs + { + if (log) + DEBUG_LOG(LOADER,"HI reloc %08x", addr); + + u32 cur = (op & 0xFFFF) << 16; + u16 hi = 0; + bool found = false; + for (int t = r + 1; te_phnum); // First pass : Get the damn bits into RAM - u32 segmentVAddr[32]; - u32 baseAddress = bRelocate?vaddr:0; + for (int i=0; ie_phnum; i++) { Elf32_Phdr *p = segments + i; @@ -170,7 +281,6 @@ bool ElfReader::LoadInto(u32 loadAddress) if (s->sh_type == SHT_PSPREL) { //We have a relocation table! - int symbolSection = s->sh_link; int sectionToModify = s->sh_info; if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) @@ -184,116 +294,7 @@ bool ElfReader::LoadInto(u32 loadAddress) Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i); DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify)); - - for (int r = 0; r < numRelocs; r++) - { - u32 info = rels[r].r_info; - u32 addr = rels[r].r_offset; - - int type = info & 0xf; - - int readwrite = (info>>8) & 0xff; - int relative = (info>>16) & 0xff; - - //0 = code - //1 = data - - addr += segmentVAddr[readwrite]; - - u32 op = Memory::ReadUnchecked_U32(addr); - - const bool log = false; - //log=true; - if (log) - { - DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info); - } - u32 relocateTo = segmentVAddr[relative]; - -#define R_MIPS32 2 -#define R_MIPS26 4 -#define R_MIPS16_HI 5 -#define R_MIPS16_LO 6 - - switch (type) - { - case R_MIPS32: - if (log) - DEBUG_LOG(LOADER,"Full address reloc %08x", addr); - //full address, no problemo - op += relocateTo; - break; - - case R_MIPS26: //j, jal - //add on to put in correct address space - if (log) - DEBUG_LOG(LOADER,"j/jal reloc %08x", addr); - op = (op & 0xFC000000) | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF); - break; - - case R_MIPS16_HI: //lui part of lui-addiu pairs - { - if (log) - DEBUG_LOG(LOADER,"HI reloc %08x", addr); - - u32 cur = (op & 0xFFFF) << 16; - u16 hi = 0; - bool found = false; - for (int t = r + 1; tsh_type == SHT_REL) { @@ -305,7 +306,6 @@ bool ElfReader::LoadInto(u32 loadAddress) else { //We have a relocation table! - int symbolSection = s->sh_link; int sectionToModify = s->sh_info; if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) { @@ -317,6 +317,21 @@ bool ElfReader::LoadInto(u32 loadAddress) } } + // Segment relocations (a few games use them) + for (int i=0; ie_phnum; i++) + { + Elf32_Phdr *p = &segments[i]; + if (p->p_type == 0x700000A0) + { + INFO_LOG(LOADER,"Loading segment relocations"); + + int numRelocs = p->p_filesz / sizeof(Elf32_Rel); + + Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i); + LoadRelocations(rels, numRelocs); + } + } + NOTICE_LOG(LOADER,"ELF loading completed successfully."); return true; } diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index 9290cc22b5..d23cf2a550 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -42,6 +42,7 @@ class ElfReader bool bRelocate; u32 entryPoint; u32 vaddr; + u32 segmentVAddr[32]; public: ElfReader(void *ptr) { @@ -117,4 +118,5 @@ public: // More indepth stuff:) bool LoadInto(u32 vaddr); bool LoadSymbols(); + void LoadRelocations(Elf32_Rel *rels, int numRelocs); }; From 515b9f5c05f8435bdbfbf8f40d711afddbef6e35 Mon Sep 17 00:00:00 2001 From: TMaul Date: Wed, 26 Dec 2012 21:25:10 +0000 Subject: [PATCH 222/276] Random bits of cleanup --- Common/FileUtil.cpp | 4 ++++ Core/HLE/sceIo.cpp | 22 +++++++++++----------- Core/HLE/sceKernelAlarm.cpp | 4 ++-- Core/HLE/sceKernelEventFlag.cpp | 16 ++++++++-------- Core/HLE/sceKernelMbx.cpp | 4 ++-- Core/HLE/sceKernelMsgPipe.cpp | 18 +++++++++--------- Core/HLE/sceKernelSemaphore.cpp | 12 ++++++------ 7 files changed, 42 insertions(+), 38 deletions(-) diff --git a/Common/FileUtil.cpp b/Common/FileUtil.cpp index 3bebbe77f8..8ba82fa901 100644 --- a/Common/FileUtil.cpp +++ b/Common/FileUtil.cpp @@ -335,6 +335,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) ERROR_LOG(COMMON, "Copy: failed reading from source, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); + fclose(input); + fclose(output); return false; } } @@ -346,6 +348,8 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename) ERROR_LOG(COMMON, "Copy: failed writing to output, %s --> %s: %s", srcFilename.c_str(), destFilename.c_str(), GetLastErrorMsg()); + fclose(input); + fclose(output); return false; } } diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 2523539a0a..cd39374d6f 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -220,7 +220,7 @@ u32 sceKernelStderr() { } void __IoCompleteAsyncIO(SceUID id) { - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { if (f->callbackID) { @@ -267,7 +267,7 @@ u32 sceIoRead(int id, u32 data_addr, int size) { return 0; //stdin } - u32 error; + u32 error = 0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { if (data_addr) { @@ -303,7 +303,7 @@ u32 sceIoWrite(int id, void *data_ptr, int size) //(int fd, void *data, int size str[size] = temp; return size; } - u32 error; + u32 error = 0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u8 *data = (u8*) data_ptr; @@ -316,7 +316,7 @@ u32 sceIoWrite(int id, void *data_ptr, int size) //(int fd, void *data, int size } s64 sceIoLseek(int id, s64 offset, int whence) { - u32 error; + u32 error = 0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { FileMove seek = FILEMOVE_BEGIN; @@ -344,7 +344,7 @@ s64 sceIoLseek(int id, s64 offset, int whence) { } u32 sceIoLseek32(int id, int offset, int whence) { - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { DEBUG_LOG(HLE, "sceIoLseek32(%d,%08x,%i)", id, (int) offset, whence); @@ -708,7 +708,7 @@ u32 sceIoSetAsyncCallback(int id, u32 clbckId, u32 clbckArg) DEBUG_LOG(HLE, "sceIoSetAsyncCallback(%d, %i, %08x)", id, clbckId, clbckArg); - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { @@ -751,7 +751,7 @@ u32 sceIoReadAsync(int id, u32 data_addr, int size) u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) { - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { @@ -770,7 +770,7 @@ u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) } int sceIoWaitAsync(int id, u32 address) { - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -791,7 +791,7 @@ int sceIoWaitAsync(int id, u32 address) { int sceIoWaitAsyncCB(int id, u32 address) { // Should process callbacks here - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -813,7 +813,7 @@ int sceIoWaitAsyncCB(int id, u32 address) { } u32 sceIoPollAsync(int id, u32 address) { - u32 error; + u32 error=0; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -859,7 +859,7 @@ u32 sceIoDopen(const char *path) { } u32 sceIoDread(int id, u32 dirent_addr) { - u32 error; + u32 error=0; DirListing *dir = kernelObjects.Get(id, error); if (dir) { if (dir->index == (int) dir->listing.size()) { diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 4e378b2a49..7b0df87b44 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -84,7 +84,7 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) { int uid = (int) userdata; - u32 error; + u32 error=0; Alarm *alarm = kernelObjects.Get(uid, error); if (alarm) __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); @@ -152,7 +152,7 @@ int sceKernelCancelAlarm(SceUID uid) int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) { - u32 error; + u32 error=0; Alarm *alarm = kernelObjects.Get(uid, error); if (!alarm) { diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index a28c06c0d6..42df1072dd 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -204,7 +204,7 @@ u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) { DEBUG_LOG(HLE, "sceKernelCancelEventFlag(%i, %08X, %08X)", uid, pattern, numWaitThreadsPtr); - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(uid, error); if (e) { @@ -225,7 +225,7 @@ u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) u32 sceKernelClearEventFlag(SceUID id, u32 bits) { - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -245,7 +245,7 @@ u32 sceKernelDeleteEventFlag(SceUID uid) { DEBUG_LOG(HLE, "sceKernelDeleteEventFlag(%i)", uid); - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(uid, error); if (e) { @@ -261,7 +261,7 @@ u32 sceKernelDeleteEventFlag(SceUID uid) u32 sceKernelSetEventFlag(SceUID id, u32 bitsToSet) { - u32 error; + u32 error=0; DEBUG_LOG(HLE, "sceKernelSetEventFlag(%i, %08x)", id, bitsToSet); EventFlag *e = kernelObjects.Get(id, error); if (e) @@ -367,7 +367,7 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -420,7 +420,7 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -481,7 +481,7 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -511,7 +511,7 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr) { DEBUG_LOG(HLE, "sceKernelReferEventFlagStatus(%i, %08x)", id, statusPtr); - u32 error; + u32 error=0; EventFlag *e = kernelObjects.Get(id, error); if (e) { diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index c8c758a215..ae0cab10cd 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -295,7 +295,7 @@ SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr) int sceKernelDeleteMbx(SceUID id) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (m) { @@ -318,7 +318,7 @@ int sceKernelDeleteMbx(SceUID id) int sceKernelSendMbx(SceUID id, u32 packetAddr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) { diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 1521d5f188..be51e24fa7 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -186,7 +186,7 @@ void sceKernelCreateMsgPipe() void sceKernelDeleteMsgPipe() { SceUID uid = PARAM(0); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { @@ -320,7 +320,7 @@ void sceKernelSendMsgPipe() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipe(%i) - ERROR %08x", uid, error); @@ -341,7 +341,7 @@ void sceKernelSendMsgPipeCB() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipeCB(%i) - ERROR %08x", uid, error); @@ -362,7 +362,7 @@ void sceKernelTrySendMsgPipe() int waitMode = PARAM(3); u32 resultAddr = PARAM(4); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTrySendMsgPipe(%i) - ERROR %08x", uid, error); @@ -496,7 +496,7 @@ void sceKernelReceiveMsgPipe() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipe(%i) - ERROR %08x", uid, error); @@ -517,7 +517,7 @@ void sceKernelReceiveMsgPipeCB() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipeCB(%i) - ERROR %08x", uid, error); @@ -537,7 +537,7 @@ void sceKernelTryReceiveMsgPipe() int waitMode = PARAM(3); u32 resultAddr = PARAM(4); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTryReceiveMsgPipe(%i) - ERROR %08x", uid, error); @@ -555,7 +555,7 @@ void sceKernelCancelMsgPipe() u32 numSendThreadsAddr = PARAM(1); u32 numReceiveThreadsAddr = PARAM(2); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { @@ -588,7 +588,7 @@ void sceKernelReferMsgPipeStatus() u32 msgPipeStatusAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelReferMsgPipeStatus(%i, %08x)", uid, msgPipeStatusAddr); - u32 error; + u32 error=0; MsgPipe *m = kernelObjects.Get(uid, error); if (m) { diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 2fd575d0d4..e634b3573d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -139,7 +139,7 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) { DEBUG_LOG(HLE, "sceKernelCancelSema(%i)", id); - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -206,7 +206,7 @@ int sceKernelDeleteSema(SceUID id) { DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -225,7 +225,7 @@ int sceKernelDeleteSema(SceUID id) int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -242,7 +242,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) int sceKernelSignalSema(SceUID id, int signal) { - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -324,7 +324,7 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) { - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -376,7 +376,7 @@ int sceKernelPollSema(SceUID id, int wantedCount) if (wantedCount <= 0) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - u32 error; + u32 error=0; Semaphore *s = kernelObjects.Get(id, error); if (s) { From d950ccc1a30fb76385b534aa50f1b60493a7eabc Mon Sep 17 00:00:00 2001 From: TMaul Date: Wed, 26 Dec 2012 22:25:34 +0000 Subject: [PATCH 223/276] Clean up more warnings --- Common/LogManager.cpp | 2 +- Core/HLE/sceKernelMbx.cpp | 10 +++++----- Core/HLE/sceKernelMemory.cpp | 28 ++++++++++++++-------------- Core/HLE/sceKernelModule.cpp | 2 +- Core/HLE/sceKernelMutex.cpp | 12 ++++++------ 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp index 64da7ff032..62174d3d31 100644 --- a/Common/LogManager.cpp +++ b/Common/LogManager.cpp @@ -159,7 +159,7 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const static const char level_to_char[7] = "-NEWID"; char formattedTime[13]; Common::Timer::GetTimeFormatted(formattedTime); - sprintf(msg, "%s %s:%u %c[%s]: %s\n", + sprintf(msg, "%s %s:%d %c[%s]: %s\n", formattedTime, file, line, level_to_char[(int)level], log->GetShortName(), temp); diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index ae0cab10cd..5eebea0387 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -410,7 +410,7 @@ int sceKernelSendMbx(SceUID id, u32 packetAddr) int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -437,7 +437,7 @@ int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -465,7 +465,7 @@ int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -488,7 +488,7 @@ int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -515,7 +515,7 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr) int sceKernelReferMbxStatus(SceUID id, u32 infoAddr) { - u32 error; + u32 error=0; Mbx *m = kernelObjects.Get(id, error); if (!m) { diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 5513850417..edd94ddb7c 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -167,7 +167,7 @@ void sceKernelCreateFpl() void sceKernelDeleteFpl() { SceUID id = PARAM(0); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -184,7 +184,7 @@ void sceKernelDeleteFpl() void sceKernelAllocateFpl() { SceUID id = PARAM(0); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -214,7 +214,7 @@ void sceKernelAllocateFpl() void sceKernelAllocateFplCB() { SceUID id = PARAM(0); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -243,7 +243,7 @@ void sceKernelAllocateFplCB() void sceKernelTryAllocateFpl() { SceUID id = PARAM(0); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -272,7 +272,7 @@ void sceKernelFreeFpl() u32 blockAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelFreeFpl(%i, %08x)", id, blockAddr); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { int blockNum = (blockAddr - fpl->address) / fpl->nf.blocksize; @@ -295,7 +295,7 @@ void sceKernelCancelFpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"UNIMPL: sceKernelCancelFpl(%i)", id); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -312,7 +312,7 @@ void sceKernelReferFplStatus() SceUID id = PARAM(0); u32 statusAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelReferFplStatus(%i, %08x)", id, statusAddr); - u32 error; + u32 error=0; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -415,7 +415,7 @@ void sceKernelGetBlockHeadAddr() { SceUID id = PARAM(0); - u32 error; + u32 error=0; PartitionMemoryBlock *block = kernelObjects.Get(id, error); if (block) { @@ -480,7 +480,7 @@ void sceKernelDeleteVpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"sceKernelDeleteVpl(%i)", id); - u32 error; + u32 error=0; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -498,7 +498,7 @@ void sceKernelAllocateVpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"sceKernelAllocateVpl()"); - u32 error; + u32 error=0; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -527,7 +527,7 @@ void sceKernelAllocateVpl() void sceKernelAllocateVplCB() { SceUID id = PARAM(0); - u32 error; + u32 error=0; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -557,7 +557,7 @@ void sceKernelAllocateVplCB() void sceKernelTryAllocateVpl() { SceUID id = PARAM(0); - u32 error; + u32 error=0; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -588,7 +588,7 @@ void sceKernelFreeVpl() SceUID id = PARAM(0); u32 blockPtr = PARAM(1); DEBUG_LOG(HLE,"sceKernelFreeVpl(%i, %08x)", id, blockPtr); - u32 error; + u32 error=0; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -614,7 +614,7 @@ void sceKernelCancelVpl() void sceKernelReferVplStatus() { SceUID id = PARAM(0); - u32 error; + u32 error=0; VPL *v = kernelObjects.Get(id, error); if (v) { diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 46305fe375..46ecd8cf70 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -497,7 +497,7 @@ void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOptio u32 __KernelGetModuleGP(SceUID uid) { - u32 error; + u32 error=0; Module *module = kernelObjects.Get(uid, error); if (module) { diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index e3d048e545..1a8f4b4a0e 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -256,7 +256,7 @@ bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int int sceKernelDeleteMutex(SceUID id) { DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id); - u32 error; + u32 error=0; Mutex *mutex = kernelObjects.Get(id, error); if (mutex) { @@ -409,7 +409,7 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr); - u32 error; + u32 error=0; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -431,7 +431,7 @@ int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr); - u32 error; + u32 error=0; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -456,7 +456,7 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) int sceKernelTryLockMutex(SceUID id, int count) { DEBUG_LOG(HLE, "sceKernelTryLockMutex(%i, %i)", id, count); - u32 error; + u32 error=0; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -471,7 +471,7 @@ int sceKernelTryLockMutex(SceUID id, int count) int sceKernelUnlockMutex(SceUID id, int count) { DEBUG_LOG(HLE, "sceKernelUnlockMutex(%i, %i)", id, count); - u32 error; + u32 error=0; Mutex *mutex = kernelObjects.Get(id, error); if (error) @@ -581,7 +581,7 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); - u32 error; + u32 error=0; LwMutex *mutex = kernelObjects.Get(workarea.uid, error); if (mutex) { From 76726a8f325f531125f5b84b7cf795bf79cdc163 Mon Sep 17 00:00:00 2001 From: TMaul Date: Thu, 27 Dec 2012 20:00:47 +0000 Subject: [PATCH 224/276] Revert some error=0 stuff Just make them unitialised. --- Core/HLE/sceIo.cpp | 16 ++++++++-------- Core/HLE/sceKernelAlarm.cpp | 4 ++-- Core/HLE/sceKernelEventFlag.cpp | 16 ++++++++-------- Core/HLE/sceKernelMbx.cpp | 14 +++++++------- Core/HLE/sceKernelMemory.cpp | 28 ++++++++++++++-------------- Core/HLE/sceKernelModule.cpp | 2 +- Core/HLE/sceKernelMsgPipe.cpp | 18 +++++++++--------- Core/HLE/sceKernelMutex.cpp | 12 ++++++------ 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index cd39374d6f..fd2cb461d2 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -220,7 +220,7 @@ u32 sceKernelStderr() { } void __IoCompleteAsyncIO(SceUID id) { - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { if (f->callbackID) { @@ -344,7 +344,7 @@ s64 sceIoLseek(int id, s64 offset, int whence) { } u32 sceIoLseek32(int id, int offset, int whence) { - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { DEBUG_LOG(HLE, "sceIoLseek32(%d,%08x,%i)", id, (int) offset, whence); @@ -708,7 +708,7 @@ u32 sceIoSetAsyncCallback(int id, u32 clbckId, u32 clbckArg) DEBUG_LOG(HLE, "sceIoSetAsyncCallback(%d, %i, %08x)", id, clbckId, clbckArg); - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { @@ -751,7 +751,7 @@ u32 sceIoReadAsync(int id, u32 data_addr, int size) u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) { - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { @@ -770,7 +770,7 @@ u32 sceIoGetAsyncStat(int id, u32 poll, u32 address) } int sceIoWaitAsync(int id, u32 address) { - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -791,7 +791,7 @@ int sceIoWaitAsync(int id, u32 address) { int sceIoWaitAsyncCB(int id, u32 address) { // Should process callbacks here - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -813,7 +813,7 @@ int sceIoWaitAsyncCB(int id, u32 address) { } u32 sceIoPollAsync(int id, u32 address) { - u32 error=0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u64 res = f->asyncResult; @@ -859,7 +859,7 @@ u32 sceIoDopen(const char *path) { } u32 sceIoDread(int id, u32 dirent_addr) { - u32 error=0; + u32 error; DirListing *dir = kernelObjects.Get(id, error); if (dir) { if (dir->index == (int) dir->listing.size()) { diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 7b0df87b44..4e378b2a49 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -84,7 +84,7 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) { int uid = (int) userdata; - u32 error=0; + u32 error; Alarm *alarm = kernelObjects.Get(uid, error); if (alarm) __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); @@ -152,7 +152,7 @@ int sceKernelCancelAlarm(SceUID uid) int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) { - u32 error=0; + u32 error; Alarm *alarm = kernelObjects.Get(uid, error); if (!alarm) { diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 42df1072dd..a28c06c0d6 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -204,7 +204,7 @@ u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) { DEBUG_LOG(HLE, "sceKernelCancelEventFlag(%i, %08X, %08X)", uid, pattern, numWaitThreadsPtr); - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(uid, error); if (e) { @@ -225,7 +225,7 @@ u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr) u32 sceKernelClearEventFlag(SceUID id, u32 bits) { - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -245,7 +245,7 @@ u32 sceKernelDeleteEventFlag(SceUID uid) { DEBUG_LOG(HLE, "sceKernelDeleteEventFlag(%i)", uid); - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(uid, error); if (e) { @@ -261,7 +261,7 @@ u32 sceKernelDeleteEventFlag(SceUID uid) u32 sceKernelSetEventFlag(SceUID id, u32 bitsToSet) { - u32 error=0; + u32 error; DEBUG_LOG(HLE, "sceKernelSetEventFlag(%i, %08x)", id, bitsToSet); EventFlag *e = kernelObjects.Get(id, error); if (e) @@ -367,7 +367,7 @@ int sceKernelWaitEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -420,7 +420,7 @@ int sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -481,7 +481,7 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti if (bits == 0) return SCE_KERNEL_ERROR_EVF_ILPAT; - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(id, error); if (e) { @@ -511,7 +511,7 @@ int sceKernelPollEventFlag(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 ti u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr) { DEBUG_LOG(HLE, "sceKernelReferEventFlagStatus(%i, %08x)", id, statusPtr); - u32 error=0; + u32 error; EventFlag *e = kernelObjects.Get(id, error); if (e) { diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index 5eebea0387..c8c758a215 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -295,7 +295,7 @@ SceUID sceKernelCreateMbx(const char *name, u32 attr, u32 optAddr) int sceKernelDeleteMbx(SceUID id) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (m) { @@ -318,7 +318,7 @@ int sceKernelDeleteMbx(SceUID id) int sceKernelSendMbx(SceUID id, u32 packetAddr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) { @@ -410,7 +410,7 @@ int sceKernelSendMbx(SceUID id, u32 packetAddr) int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -437,7 +437,7 @@ int sceKernelReceiveMbx(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -465,7 +465,7 @@ int sceKernelReceiveMbxCB(SceUID id, u32 packetAddrPtr, u32 timeoutPtr) int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -488,7 +488,7 @@ int sceKernelPollMbx(SceUID id, u32 packetAddrPtr) int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) @@ -515,7 +515,7 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr) int sceKernelReferMbxStatus(SceUID id, u32 infoAddr) { - u32 error=0; + u32 error; Mbx *m = kernelObjects.Get(id, error); if (!m) { diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index edd94ddb7c..5513850417 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -167,7 +167,7 @@ void sceKernelCreateFpl() void sceKernelDeleteFpl() { SceUID id = PARAM(0); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -184,7 +184,7 @@ void sceKernelDeleteFpl() void sceKernelAllocateFpl() { SceUID id = PARAM(0); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -214,7 +214,7 @@ void sceKernelAllocateFpl() void sceKernelAllocateFplCB() { SceUID id = PARAM(0); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -243,7 +243,7 @@ void sceKernelAllocateFplCB() void sceKernelTryAllocateFpl() { SceUID id = PARAM(0); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -272,7 +272,7 @@ void sceKernelFreeFpl() u32 blockAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelFreeFpl(%i, %08x)", id, blockAddr); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { int blockNum = (blockAddr - fpl->address) / fpl->nf.blocksize; @@ -295,7 +295,7 @@ void sceKernelCancelFpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"UNIMPL: sceKernelCancelFpl(%i)", id); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -312,7 +312,7 @@ void sceKernelReferFplStatus() SceUID id = PARAM(0); u32 statusAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelReferFplStatus(%i, %08x)", id, statusAddr); - u32 error=0; + u32 error; FPL *fpl = kernelObjects.Get(id, error); if (fpl) { @@ -415,7 +415,7 @@ void sceKernelGetBlockHeadAddr() { SceUID id = PARAM(0); - u32 error=0; + u32 error; PartitionMemoryBlock *block = kernelObjects.Get(id, error); if (block) { @@ -480,7 +480,7 @@ void sceKernelDeleteVpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"sceKernelDeleteVpl(%i)", id); - u32 error=0; + u32 error; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -498,7 +498,7 @@ void sceKernelAllocateVpl() { SceUID id = PARAM(0); DEBUG_LOG(HLE,"sceKernelAllocateVpl()"); - u32 error=0; + u32 error; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -527,7 +527,7 @@ void sceKernelAllocateVpl() void sceKernelAllocateVplCB() { SceUID id = PARAM(0); - u32 error=0; + u32 error; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -557,7 +557,7 @@ void sceKernelAllocateVplCB() void sceKernelTryAllocateVpl() { SceUID id = PARAM(0); - u32 error=0; + u32 error; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -588,7 +588,7 @@ void sceKernelFreeVpl() SceUID id = PARAM(0); u32 blockPtr = PARAM(1); DEBUG_LOG(HLE,"sceKernelFreeVpl(%i, %08x)", id, blockPtr); - u32 error=0; + u32 error; VPL *vpl = kernelObjects.Get(id, error); if (vpl) { @@ -614,7 +614,7 @@ void sceKernelCancelVpl() void sceKernelReferVplStatus() { SceUID id = PARAM(0); - u32 error=0; + u32 error; VPL *v = kernelObjects.Get(id, error); if (v) { diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 46ecd8cf70..46305fe375 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -497,7 +497,7 @@ void __KernelStartModule(Module *m, int args, const char *argp, SceKernelSMOptio u32 __KernelGetModuleGP(SceUID uid) { - u32 error=0; + u32 error; Module *module = kernelObjects.Get(uid, error); if (module) { diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index be51e24fa7..1521d5f188 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -186,7 +186,7 @@ void sceKernelCreateMsgPipe() void sceKernelDeleteMsgPipe() { SceUID uid = PARAM(0); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { @@ -320,7 +320,7 @@ void sceKernelSendMsgPipe() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipe(%i) - ERROR %08x", uid, error); @@ -341,7 +341,7 @@ void sceKernelSendMsgPipeCB() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelSendMsgPipeCB(%i) - ERROR %08x", uid, error); @@ -362,7 +362,7 @@ void sceKernelTrySendMsgPipe() int waitMode = PARAM(3); u32 resultAddr = PARAM(4); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTrySendMsgPipe(%i) - ERROR %08x", uid, error); @@ -496,7 +496,7 @@ void sceKernelReceiveMsgPipe() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipe(%i) - ERROR %08x", uid, error); @@ -517,7 +517,7 @@ void sceKernelReceiveMsgPipeCB() u32 resultAddr = PARAM(4); u32 timeoutPtr = PARAM(5); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelReceiveMsgPipeCB(%i) - ERROR %08x", uid, error); @@ -537,7 +537,7 @@ void sceKernelTryReceiveMsgPipe() int waitMode = PARAM(3); u32 resultAddr = PARAM(4); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { ERROR_LOG(HLE, "sceKernelTryReceiveMsgPipe(%i) - ERROR %08x", uid, error); @@ -555,7 +555,7 @@ void sceKernelCancelMsgPipe() u32 numSendThreadsAddr = PARAM(1); u32 numReceiveThreadsAddr = PARAM(2); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) { @@ -588,7 +588,7 @@ void sceKernelReferMsgPipeStatus() u32 msgPipeStatusAddr = PARAM(1); DEBUG_LOG(HLE,"sceKernelReferMsgPipeStatus(%i, %08x)", uid, msgPipeStatusAddr); - u32 error=0; + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (m) { diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 1a8f4b4a0e..e3d048e545 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -256,7 +256,7 @@ bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int int sceKernelDeleteMutex(SceUID id) { DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id); - u32 error=0; + u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (mutex) { @@ -409,7 +409,7 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr); - u32 error=0; + u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -431,7 +431,7 @@ int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) { DEBUG_LOG(HLE, "sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr); - u32 error=0; + u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -456,7 +456,7 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) int sceKernelTryLockMutex(SceUID id, int count) { DEBUG_LOG(HLE, "sceKernelTryLockMutex(%i, %i)", id, count); - u32 error=0; + u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) @@ -471,7 +471,7 @@ int sceKernelTryLockMutex(SceUID id, int count) int sceKernelUnlockMutex(SceUID id, int count) { DEBUG_LOG(HLE, "sceKernelUnlockMutex(%i, %i)", id, count); - u32 error=0; + u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (error) @@ -581,7 +581,7 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); - u32 error=0; + u32 error; LwMutex *mutex = kernelObjects.Get(workarea.uid, error); if (mutex) { From fefd166050e01e3a14860e51e09873dd90d60c11 Mon Sep 17 00:00:00 2001 From: TMaul Date: Thu, 27 Dec 2012 20:01:16 +0000 Subject: [PATCH 225/276] More error=0 reverts --- Core/HLE/sceKernelSemaphore.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index e634b3573d..2fd575d0d4 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -139,7 +139,7 @@ int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) { DEBUG_LOG(HLE, "sceKernelCancelSema(%i)", id); - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -206,7 +206,7 @@ int sceKernelDeleteSema(SceUID id) { DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -225,7 +225,7 @@ int sceKernelDeleteSema(SceUID id) int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -242,7 +242,7 @@ int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) int sceKernelSignalSema(SceUID id, int signal) { - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -324,7 +324,7 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) { - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { @@ -376,7 +376,7 @@ int sceKernelPollSema(SceUID id, int wantedCount) if (wantedCount <= 0) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - u32 error=0; + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { From 8704ec233ce15ec8e74763f523f6b968fcc5df91 Mon Sep 17 00:00:00 2001 From: TMaul Date: Thu, 27 Dec 2012 20:02:20 +0000 Subject: [PATCH 226/276] Last of the error=0 reverts --- Core/HLE/sceIo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index fd2cb461d2..2523539a0a 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -267,7 +267,7 @@ u32 sceIoRead(int id, u32 data_addr, int size) { return 0; //stdin } - u32 error = 0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { if (data_addr) { @@ -303,7 +303,7 @@ u32 sceIoWrite(int id, void *data_ptr, int size) //(int fd, void *data, int size str[size] = temp; return size; } - u32 error = 0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { u8 *data = (u8*) data_ptr; @@ -316,7 +316,7 @@ u32 sceIoWrite(int id, void *data_ptr, int size) //(int fd, void *data, int size } s64 sceIoLseek(int id, s64 offset, int whence) { - u32 error = 0; + u32 error; FileNode *f = kernelObjects.Get < FileNode > (id, error); if (f) { FileMove seek = FILEMOVE_BEGIN; From 750447793ea283ea4e95fcf4d6d8abaf7167c213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 20:47:09 +0100 Subject: [PATCH 227/276] Clamp colors before fragment shader. --- GPU/GLES/VertexShaderGenerator.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 41dd351bea..319802a9e6 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -241,8 +241,6 @@ char *GenerateVertexShader(int prim) WRITE(p, " gl_Position = u_proj * vec4(a_position, 1.0);\n"); } } else { - // This is the real deal. - // Step 1: World Transform / Skinning if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { // No skinning, just standard T&L. @@ -289,11 +287,11 @@ char *GenerateVertexShader(int prim) } // Calculate lights if needed. If shade mapping is enabled, lights may need to be - // at least partially calculated + // at least partially calculated. for (int i = 0; i < 4; i++) { if (doLight[i] == LIGHT_OFF) continue; - + GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3); GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3); @@ -309,9 +307,9 @@ char *GenerateVertexShader(int prim) if (poweredDiffuse) { WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i, i); } - + if (doLight[i] == LIGHT_DOTONLY) - continue; // Actually, might want specular dot.... TODO + continue; // TODO: Actually, might want specular dot.... TODO WRITE(p, " float lightScale%i = 1.0;\n", i); if (type != GE_LIGHTTYPE_DIRECTIONAL) { @@ -332,9 +330,9 @@ char *GenerateVertexShader(int prim) if (gstate.lightingEnable & 1) { // Sum up ambient, emissive here. - WRITE(p, " v_color0 = lightSum0 + u_ambient * vec4(%s, 1.0) + vec4(u_matemissive, 0.0);\n", ambient); + WRITE(p, " v_color0 = clamp(lightSum0 + u_ambient * vec4(%s, 1.0) + vec4(u_matemissive, 0.0), 0.0, 1.0);\n", ambient); if (lmode) { - WRITE(p, " v_color1 = lightSum1;\n"); + WRITE(p, " v_color1 = clamp(lightSum1, 0.0, 1.0);\n"); } else { WRITE(p, " v_color0 += vec4(lightSum1, 0.0);\n"); } @@ -342,7 +340,7 @@ char *GenerateVertexShader(int prim) // Lighting doesn't affect color. if (hasColor) { WRITE(p, " v_color0 = a_color0;\n"); - } else { + } else { WRITE(p, " v_color0 = u_matambientalpha;\n"); } if (lmode) @@ -379,7 +377,7 @@ char *GenerateVertexShader(int prim) WRITE(p, " v_texcoord = vec2(dot%i, dot%i);\n", gstate.getUVLS0(), gstate.getUVLS1()); break; - case 3: + case 3: // ILLEGAL break; } From 3f5eae3db5d8f1deaa76b282c4f40e80f93649eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 21:08:41 +0100 Subject: [PATCH 228/276] Add some options to ingame menu. Minor fixes. --- Core/HLE/sceDisplay.cpp | 2 +- Core/HLE/scePower.cpp | 15 +++++++++++++-- android/jni/MenuScreens.cpp | 5 +++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index d8d323cc58..ac780633a2 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -171,7 +171,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. // Here we will be drawing to the non buffered front surface. - if (g_Config.bShowDebugStats) { + if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { gpu->UpdateStats(); char stats[512]; sprintf(stats, diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index c6b0fecb7d..68fd2215d7 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -162,6 +162,17 @@ void scePowerSetClockFrequency(u32 cpufreq, u32 busfreq, u32 gpufreq) { INFO_LOG(HLE,"scePowerSetClockFrequency(%i,%i,%i)", cpufreq, busfreq, gpufreq); } +u32 scePowerSetCpuClockFrequency(u32 cpufreq) { + CoreTiming::SetClockFrequencyMHz(cpufreq); + DEBUG_LOG(HLE,"scePowerSetCpuClockFrequency(%i)", cpufreq); + return 0; +} + +u32 scePowerSetBusClockFrequency(u32 busfreq) { + DEBUG_LOG(HLE,"scePowerSetBusClockFrequency(%i)", busfreq); + return 0; +} + u32 scePowerGetCpuClockFrequencyInt() { int freq = CoreTiming::GetClockFrequencyMHz(); INFO_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", freq); @@ -217,8 +228,8 @@ static const HLEFunction scePower[] = { {0x0074EF9B,0,"scePowerGetResumeCount"}, {0xDFA8BAF8,WrapI_I,"scePowerUnregisterCallback"}, {0xDB9D28DD,WrapI_I,"scePowerUnregitserCallback"}, //haha - {0x843FBF43,0,"scePowerSetCpuClockFrequency"}, - {0xB8D7B3FB,0,"scePowerSetBusClockFrequency"}, + {0x843FBF43,WrapU_U,"scePowerSetCpuClockFrequency"}, + {0xB8D7B3FB,WrapU_U,"scePowerSetBusClockFrequency"}, {0xFEE03A2F,0,"scePowerGetCpuClockFrequency"}, {0x478FE6F5,0,"scePowerGetBusClockFrequency"}, {0xFDB5BFE9,WrapU_V,"scePowerGetCpuClockFrequencyInt"}, diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 7fe29c5d9d..f557e43584 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -207,6 +207,11 @@ void InGameMenuScreen::render() { ui_draw2d.DrawText(UBUNTU48, "Emulation Paused", dp_xres / 2, 30, 0xFFFFFFFF, ALIGN_HCENTER); + int x = 30; + int y = 50; + UICheckBox(GEN_ID, x, y += 50, "Show Debug Statistics (experimental)", ALIGN_TOPLEFT, &g_Config.bShowDebugStats); + UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform); + VLinear vlinear(dp_xres - 10, 160, 20); if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Continue", ALIGN_RIGHT)) { screenManager()->finishDialog(this, DR_CANCEL); From 57b4d658ccb5b2354b531031178f8d992f8df963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 27 Dec 2012 00:18:45 +0100 Subject: [PATCH 229/276] Don't log display lists, instead dump them on demand. Makes it fairly convenient to dump and look at display lists at run time on non windows platforms. Adding a menu item on Windows should be trivial. --- CMakeLists.txt | 2 + GPU/GLES/DisplayListInterpreter.cpp | 267 +++++----- GPU/GLES/DisplayListInterpreter.h | 7 +- GPU/GPU.vcxproj | 4 +- GPU/GPUInterface.h | 3 + GPU/GeDisasm.cpp | 735 ++++++++++++++++++++++++++++ GPU/GeDisasm.h | 18 + GPU/Null/NullGpu.h | 1 + GPU/ge_constants.h | 6 +- android/jni/Android.mk | 1 + android/jni/MenuScreens.cpp | 13 +- android/jni/NativeApp.cpp | 9 + 12 files changed, 938 insertions(+), 128 deletions(-) create mode 100644 GPU/GeDisasm.cpp create mode 100644 GPU/GeDisasm.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d5ce06a75f..caaee30936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -802,6 +802,8 @@ add_library(GPU OBJECT GPU/GLES/VertexShaderGenerator.cpp GPU/GLES/VertexShaderGenerator.h GPU/GPUInterface.h + GPU/GeDisasm.cpp + GPU/GeDisasm.h GPU/GPUState.cpp GPU/GPUState.h GPU/Math3D.cpp diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index bf70ae40e2..f68fee9a43 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -23,6 +23,7 @@ #include "../GPUState.h" #include "../ge_constants.h" +#include "../GeDisasm.h" #include "ShaderManager.h" #include "DisplayListInterpreter.h" @@ -36,13 +37,19 @@ extern u32 curTextureWidth; extern u32 curTextureHeight; +const int flushOnChangedBeforeCommandList[] = { + GE_CMD_VERTEXTYPE, + GE_CMD_BLENDMODE, + GE_CMD_BLENDFIXEDA, + GE_CMD_BLENDFIXEDB, +}; + const int flushBeforeCommandList[] = { GE_CMD_BEZIER, GE_CMD_SPLINE, GE_CMD_SIGNAL, GE_CMD_FINISH, GE_CMD_BJUMP, - GE_CMD_VERTEXTYPE, GE_CMD_OFFSETADDR, GE_CMD_REGION1, GE_CMD_REGION2, @@ -118,9 +125,6 @@ const int flushBeforeCommandList[] = { GE_CMD_MATERIALUPDATE, GE_CMD_CLEARMODE, GE_CMD_ALPHABLENDENABLE, - GE_CMD_BLENDMODE, - GE_CMD_BLENDFIXEDA, - GE_CMD_BLENDFIXEDB, GE_CMD_ALPHATESTENABLE, GE_CMD_ALPHATEST, GE_CMD_TEXFUNC, @@ -155,7 +159,9 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1) { + dlIdGenerator(1), + dumpThisFrame_(false), + dumpNextFrame_(false) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; shaderManager_ = new ShaderManager(); @@ -166,12 +172,15 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) ERROR_LOG(G3D, "gstate has drifted out of sync!"); } - flushBeforeCommand_ = new bool[256]; + flushBeforeCommand_ = new u8[256]; memset(flushBeforeCommand_, 0, 256 * sizeof(bool)); - for (int i = 0; i < ARRAY_SIZE(flushBeforeCommandList); i++) { - flushBeforeCommand_[flushBeforeCommandList[i]] = true; + for (int i = 0; i < ARRAY_SIZE(flushOnChangedBeforeCommandList); i++) { + flushBeforeCommand_[flushOnChangedBeforeCommandList[i]] = 2; } - flushBeforeCommand_[1] = false; + for (int i = 0; i < ARRAY_SIZE(flushBeforeCommandList); i++) { + flushBeforeCommand_[flushBeforeCommandList[i]] = 1; + } + flushBeforeCommand_[1] = 0; } GLES_GPU::~GLES_GPU() { @@ -202,9 +211,20 @@ void GLES_GPU::InitClear() { glViewport(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); } +void GLES_GPU::DumpNextFrame() { + dumpNextFrame_ = true; +} + void GLES_GPU::BeginFrame() { TextureCache_Decimate(); + if (dumpNextFrame_) { + NOTICE_LOG(G3D, "DUMPING THIS FRAME"); + dumpThisFrame_ = true; + dumpNextFrame_ = false; + } else if (dumpThisFrame_) { + dumpThisFrame_ = false; + } shaderManager_->DirtyShader(); // Not sure if this is really needed. @@ -225,7 +245,7 @@ void GLES_GPU::BeginFrame() { void GLES_GPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) { if (framebuf & 0x04000000) { - DEBUG_LOG(G3D, "Switch display framebuffer %08x", framebuf); + //DEBUG_LOG(G3D, "Switch display framebuffer %08x", framebuf); displayFramebufPtr_ = framebuf; displayStride_ = stride; displayFormat_ = format; @@ -369,7 +389,7 @@ bool GLES_GPU::ProcessDLQueue() { DisplayList &l = *iter; dcontext.pc = l.listpc; dcontext.stallAddr = l.stall; -// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr); +// //DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr); if (!InterpretList()) { l.listpc = dcontext.pc; l.stall = dcontext.stallAddr; @@ -450,17 +470,17 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { switch (cmd) { case GE_CMD_BASE: - DEBUG_LOG(G3D,"DL BASE: %06x", data & 0xFFFFFF); + //DEBUG_LOG(G3D,"DL BASE: %06x", data & 0xFFFFFF); break; case GE_CMD_VADDR: /// <<8???? gstate_c.vertexAddr = ((gstate.base & 0x00FF0000) << 8)|data; - DEBUG_LOG(G3D,"DL VADDR: %06x", gstate_c.vertexAddr); + //DEBUG_LOG(G3D,"DL VADDR: %06x", gstate_c.vertexAddr); break; case GE_CMD_IADDR: gstate_c.indexAddr = ((gstate.base & 0x00FF0000) << 8)|data; - DEBUG_LOG(G3D,"DL IADDR: %06x", gstate_c.indexAddr); + //DEBUG_LOG(G3D,"DL IADDR: %06x", gstate_c.indexAddr); break; case GE_CMD_PRIM: @@ -478,7 +498,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { "TRIANGLE_FAN=5,", "RECTANGLES=6,", }; - DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); + //DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { @@ -513,7 +533,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; transformDraw_.DrawBezier(bz_ucount, bz_vcount); - DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); + //DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); } break; @@ -524,14 +544,14 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int sp_utype = (data >> 16) & 0x3; int sp_vtype = (data >> 18) & 0x3; //drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); - DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); + //DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); } break; case GE_CMD_JUMP: { u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; - DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target); + //DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target); dcontext.pc = target - 4; // pc will be increased after we return, counteract that } break; @@ -544,7 +564,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { } else { stack[stackptr++] = retval; u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF; - DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval); + //DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval); dcontext.pc = target - 4; // pc will be increased after we return, counteract that } } @@ -554,27 +574,27 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { //TODO : debug! { u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF); - DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target); + //DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target); dcontext.pc = target - 4; } break; case GE_CMD_SIGNAL: { - DEBUG_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); + //DEBUG_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); // Processed in GE_END. } break; case GE_CMD_FINISH: - DEBUG_LOG(G3D,"DL CMD FINISH"); + //DEBUG_LOG(G3D,"DL CMD FINISH"); // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; case GE_CMD_END: - DEBUG_LOG(G3D,"DL CMD END"); + //DEBUG_LOG(G3D,"DL CMD END"); switch (prev >> 24) { case GE_CMD_SIGNAL: @@ -586,10 +606,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // We should probably defer to sceGe here, no sense in implementing this stuff in every GPU switch (behaviour) { case 1: // Signal with Wait - DEBUG_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + //DEBUG_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); break; case 2: - DEBUG_LOG(G3D, "Signal without wait. signal/end: %04x %04x", signal, enddata); + //DEBUG_LOG(G3D, "Signal without wait. signal/end: %04x %04x", signal, enddata); break; case 3: ERROR_LOG(G3D, "Signal with Pause UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); @@ -616,19 +636,19 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { finished = true; break; default: - DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); + //DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); break; } break; case GE_CMD_BJUMP: // bounding box jump. Let's just not jump, for now. - DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); + //DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); break; case GE_CMD_BOUNDINGBOX: // bounding box test. Let's do nothing. - DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); + //DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); break; case GE_CMD_ORIGIN: @@ -636,7 +656,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_VERTEXTYPE: - DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); + //DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); if (diff & GE_VTYPE_THROUGH) { // Throughmode changed, let's make the proj matrix dirty. shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); @@ -653,7 +673,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int x1 = data & 0x3ff; int y1 = data >> 10; //topleft - DEBUG_LOG(G3D,"DL Region TL: %d %d", x1, y1); + //DEBUG_LOG(G3D,"DL Region TL: %d %d", x1, y1); } break; @@ -661,67 +681,67 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { int x2 = data & 0x3ff; int y2 = data >> 10; - DEBUG_LOG(G3D,"DL Region BR: %d %d", x2, y2); + //DEBUG_LOG(G3D,"DL Region BR: %d %d", x2, y2); } break; case GE_CMD_CLIPENABLE: - DEBUG_LOG(G3D, "DL Clip Enable: %i (ignoring)", data); + //DEBUG_LOG(G3D, "DL Clip Enable: %i (ignoring)", data); //we always clip, this is opengl break; case GE_CMD_CULLFACEENABLE: - DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); + //DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); break; case GE_CMD_TEXTUREMAPENABLE: gstate_c.textureChanged = true; - DEBUG_LOG(G3D, "DL Texture map enable: %i", data); + //DEBUG_LOG(G3D, "DL Texture map enable: %i", data); break; case GE_CMD_LIGHTINGENABLE: - DEBUG_LOG(G3D, "DL Lighting enable: %i", data); + //DEBUG_LOG(G3D, "DL Lighting enable: %i", data); data += 1; //We don't use OpenGL lighting break; case GE_CMD_FOGENABLE: - DEBUG_LOG(G3D, "DL Fog Enable: %i", data); + //DEBUG_LOG(G3D, "DL Fog Enable: %i", data); break; case GE_CMD_DITHERENABLE: - DEBUG_LOG(G3D, "DL Dither Enable: %i", data); + //DEBUG_LOG(G3D, "DL Dither Enable: %i", data); break; case GE_CMD_OFFSETX: - DEBUG_LOG(G3D, "DL Offset X: %i", data); + //DEBUG_LOG(G3D, "DL Offset X: %i", data); break; case GE_CMD_OFFSETY: - DEBUG_LOG(G3D, "DL Offset Y: %i", data); + //DEBUG_LOG(G3D, "DL Offset Y: %i", data); break; case GE_CMD_TEXSCALEU: gstate_c.uScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); + //DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: gstate_c.vScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); + //DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: gstate_c.uOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); + //DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: gstate_c.vOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); + //DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; @@ -729,38 +749,38 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { int x1 = data & 0x3ff; int y1 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); + //DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); } break; case GE_CMD_SCISSOR2: { int x2 = data & 0x3ff; int y2 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); + //DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); } break; case GE_CMD_MINZ: gstate_c.zMin = getFloat24(data) / 65535.f; - DEBUG_LOG(G3D, "DL MinZ: %f", gstate_c.zMin); + //DEBUG_LOG(G3D, "DL MinZ: %f", gstate_c.zMin); break; case GE_CMD_MAXZ: gstate_c.zMax = getFloat24(data) / 65535.f; - DEBUG_LOG(G3D, "DL MaxZ: %f", gstate_c.zMax); + //DEBUG_LOG(G3D, "DL MaxZ: %f", gstate_c.zMax); break; case GE_CMD_FRAMEBUFPTR: { u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); + //DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); } break; case GE_CMD_FRAMEBUFWIDTH: { u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); + //DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); } break; @@ -776,7 +796,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: gstate_c.textureChanged = true; - DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); + //DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); break; case GE_CMD_TEXBUFWIDTH0: @@ -788,18 +808,18 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: gstate_c.textureChanged = true; - DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); + //DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); break; case GE_CMD_CLUTADDR: gstate_c.textureChanged = true; - //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); + ////DEBUG_LOG(G3D,"CLUT base addr: %06x", data); gstate_c.textureChanged = true; break; case GE_CMD_CLUTADDRUPPER: gstate_c.textureChanged = true; - DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); + //DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); break; case GE_CMD_LOADCLUT: @@ -809,28 +829,28 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { u32 clutAddr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); if (clutAddr) { - DEBUG_LOG(G3D,"DL Clut load: %08x", clutAddr); + //DEBUG_LOG(G3D,"DL Clut load: %08x", clutAddr); } else { - DEBUG_LOG(G3D,"DL Empty Clut load"); + //DEBUG_LOG(G3D,"DL Empty Clut load"); } // Should hash and invalidate all paletted textures on use } break; case GE_CMD_TEXMAPMODE: - DEBUG_LOG(G3D,"Tex map mode: %06x", data); + //DEBUG_LOG(G3D,"Tex map mode: %06x", data); break; case GE_CMD_TEXSHADELS: - DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); + //DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); break; case GE_CMD_CLUTFORMAT: { gstate_c.textureChanged = true; - DEBUG_LOG(G3D,"DL Clut format: %06x", data); + //DEBUG_LOG(G3D,"DL Clut format: %06x", data); } break; @@ -844,7 +864,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { u32 xferSrc = gstate.transfersrc | ((data&0xFF0000)<<8); u32 xferSrcW = gstate.transfersrcw & 1023; - DEBUG_LOG(G3D,"Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); + //DEBUG_LOG(G3D,"Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); break; } @@ -858,7 +878,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { u32 xferDst= gstate.transferdst | ((data&0xFF0000)<<8); u32 xferDstW = gstate.transferdstw & 1023; - DEBUG_LOG(G3D,"Block Transfer Dest: %08x W: %i", xferDst, xferDstW); + //DEBUG_LOG(G3D,"Block Transfer Dest: %08x W: %i", xferDst, xferDstW); break; } @@ -866,7 +886,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { u32 x = (data & 1023)+1; u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Src Rect TL: %i, %i", x, y); + //DEBUG_LOG(G3D, "DL Block Transfer Src Rect TL: %i, %i", x, y); break; } @@ -874,7 +894,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { u32 x = (data & 1023)+1; u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Dest Rect TL: %i, %i", x, y); + //DEBUG_LOG(G3D, "DL Block Transfer Dest Rect TL: %i, %i", x, y); break; } @@ -882,7 +902,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { u32 w = (data & 1023)+1; u32 h = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Rect Size: %i x %i", w, h); + //DEBUG_LOG(G3D, "DL Block Transfer Rect Size: %i x %i", w, h); break; } @@ -905,64 +925,64 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXSIZE5: case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: - DEBUG_LOG(G3D,"DL Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); + //DEBUG_LOG(G3D,"DL Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); gstate_c.textureChanged = true; break; case GE_CMD_ZBUFPTR: { u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); + //DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); } break; case GE_CMD_ZBUFWIDTH: { u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D,"Zbuf Width: %i", w); + //DEBUG_LOG(G3D,"Zbuf Width: %i", w); } break; case GE_CMD_AMBIENTCOLOR: - DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); + //DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); break; case GE_CMD_AMBIENTALPHA: - DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); + //DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); break; case GE_CMD_MATERIALAMBIENT: - DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); + //DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: - DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); + //DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: - DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); + //DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: - DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); + //DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: - DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); + //DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: - DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); + //DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); if (diff) shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; @@ -971,7 +991,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_LIGHTTYPE1: case GE_CMD_LIGHTTYPE2: case GE_CMD_LIGHTTYPE3: - DEBUG_LOG(G3D,"DL Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); + //DEBUG_LOG(G3D,"DL Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); break; case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: @@ -983,7 +1003,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int l = n / 3; int c = n % 3; float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); + //DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); gstate_c.lightpos[l][c] = val; if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); @@ -999,7 +1019,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int l = n / 3; int c = n % 3; float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); + //DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); gstate_c.lightdir[l][c] = val; if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); @@ -1015,7 +1035,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int l = n / 3; int c = n % 3; float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); + //DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); gstate_c.lightatt[l][c] = val; if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); @@ -1033,7 +1053,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; - DEBUG_LOG(G3D,"DL Light color %i", l); + //DEBUG_LOG(G3D,"DL Light color %i", l); gstate_c.lightColor[t][l][0] = r; gstate_c.lightColor[t][l][1] = g; gstate_c.lightColor[t][l][2] = b; @@ -1046,38 +1066,38 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_VIEWPORTY1: case GE_CMD_VIEWPORTX2: case GE_CMD_VIEWPORTY2: - DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); + //DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); break; case GE_CMD_VIEWPORTZ1: gstate_c.zScale = getFloat24(data) / 65535.f; - DEBUG_LOG(G3D,"DL Z scale: %f", gstate_c.zScale); + //DEBUG_LOG(G3D,"DL Z scale: %f", gstate_c.zScale); break; case GE_CMD_VIEWPORTZ2: gstate_c.zOff = getFloat24(data) / 65535.f; - DEBUG_LOG(G3D,"DL Z pos: %f", gstate_c.zOff); + //DEBUG_LOG(G3D,"DL Z pos: %f", gstate_c.zOff); break; case GE_CMD_LIGHTENABLE0: case GE_CMD_LIGHTENABLE1: case GE_CMD_LIGHTENABLE2: case GE_CMD_LIGHTENABLE3: - DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); + //DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); break; case GE_CMD_CULL: - DEBUG_LOG(G3D,"DL cull: %06x", data); + //DEBUG_LOG(G3D,"DL cull: %06x", data); break; case GE_CMD_LMODE: - DEBUG_LOG(G3D,"DL Shade mode: %06x", data); + //DEBUG_LOG(G3D,"DL Shade mode: %06x", data); break; case GE_CMD_PATCHDIVISION: gstate_c.patch_div_s = data & 0xFF; gstate_c.patch_div_t = (data >> 8) & 0xFF; - DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate_c.patch_div_s, gstate_c.patch_div_t); + //DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate_c.patch_div_s, gstate_c.patch_div_t); break; case GE_CMD_MATERIALUPDATE: - DEBUG_LOG(G3D,"DL Material Update: %d", data); + //DEBUG_LOG(G3D,"DL Material Update: %d", data); break; @@ -1090,7 +1110,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { EnterClearMode(data); else LeaveClearMode(); - DEBUG_LOG(G3D,"DL Clear mode: %06x", data); + //DEBUG_LOG(G3D,"DL Clear mode: %06x", data); break; @@ -1098,34 +1118,34 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // ALPHA BLENDING ////////////////////////////////////////////////////////////////// case GE_CMD_ALPHABLENDENABLE: - DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); + //DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); break; case GE_CMD_BLENDMODE: - DEBUG_LOG(G3D,"DL Blend mode: %06x", data); + //DEBUG_LOG(G3D,"DL Blend mode: %06x", data); break; case GE_CMD_BLENDFIXEDA: - DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); + //DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); break; case GE_CMD_BLENDFIXEDB: - DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); + //DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); break; case GE_CMD_ALPHATESTENABLE: - DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); + //DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); // This is done in the shader. break; case GE_CMD_ALPHATEST: - DEBUG_LOG(G3D,"DL Alpha test settings"); + //DEBUG_LOG(G3D,"DL Alpha test settings"); shaderManager_->DirtyUniform(DIRTY_ALPHACOLORREF); break; case GE_CMD_TEXFUNC: { - DEBUG_LOG(G3D,"DL TexFunc %i", data&7); + //DEBUG_LOG(G3D,"DL TexFunc %i", data&7); /* int m=GL_MODULATE; switch (data & 7) @@ -1154,41 +1174,41 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { int min = data & 7; int mag = (data >> 8) & 1; - DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); + //DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); } break; case GE_CMD_TEXENVCOLOR: - DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); + //DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_TEXENV); break; case GE_CMD_TEXMODE: - DEBUG_LOG(G3D,"DL TexMode %08x", data); + //DEBUG_LOG(G3D,"DL TexMode %08x", data); break; case GE_CMD_TEXFORMAT: - DEBUG_LOG(G3D,"DL TexFormat %08x", data); + //DEBUG_LOG(G3D,"DL TexFormat %08x", data); break; case GE_CMD_TEXFLUSH: - DEBUG_LOG(G3D,"DL TexFlush"); + //DEBUG_LOG(G3D,"DL TexFlush"); break; case GE_CMD_TEXWRAP: - DEBUG_LOG(G3D,"DL TexWrap %08x", data); + //DEBUG_LOG(G3D,"DL TexWrap %08x", data); break; ////////////////////////////////////////////////////////////////// // Z/STENCIL TESTING ////////////////////////////////////////////////////////////////// case GE_CMD_ZTESTENABLE: - DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); + //DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); break; case GE_CMD_STENCILTESTENABLE: - DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); + //DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); break; case GE_CMD_ZTEST: { - DEBUG_LOG(G3D,"DL Z test mode: %i", data); + //DEBUG_LOG(G3D,"DL Z test mode: %i", data); } break; @@ -1203,7 +1223,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { int index = cmd - GE_CMD_MORPHWEIGHT0; float weight = getFloat24(data); - DEBUG_LOG(G3D,"DL MorphWeight %i = %f", index, weight); + //DEBUG_LOG(G3D,"DL MorphWeight %i = %f", index, weight); gstate_c.morphWeights[index] = weight; } break; @@ -1212,16 +1232,16 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_DITH1: case GE_CMD_DITH2: case GE_CMD_DITH3: - DEBUG_LOG(G3D,"DL DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); + //DEBUG_LOG(G3D,"DL DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); break; case GE_CMD_WORLDMATRIXNUMBER: - DEBUG_LOG(G3D,"DL World # %i", data & 0xF); + //DEBUG_LOG(G3D,"DL World # %i", data & 0xF); gstate.worldmtxnum &= 0xFF00000F; break; case GE_CMD_WORLDMATRIXDATA: - DEBUG_LOG(G3D,"DL World data # %f", getFloat24(data)); + //DEBUG_LOG(G3D,"DL World data # %f", getFloat24(data)); { int num = gstate.worldmtxnum & 0xF; if (num < 12) @@ -1232,12 +1252,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_VIEWMATRIXNUMBER: - DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF); + //DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF); gstate.viewmtxnum &= 0xFF00000F; break; case GE_CMD_VIEWMATRIXDATA: - DEBUG_LOG(G3D,"DL VIEW data # %f", getFloat24(data)); + //DEBUG_LOG(G3D,"DL VIEW data # %f", getFloat24(data)); { int num = gstate.viewmtxnum & 0xF; if (num < 12) @@ -1248,12 +1268,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_PROJMATRIXNUMBER: - DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF); + //DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF); gstate.projmtxnum &= 0xFF00000F; break; case GE_CMD_PROJMATRIXDATA: - DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data)); + //DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data)); { int num = gstate.projmtxnum & 0xF; gstate.projMatrix[num++] = getFloat24(data); @@ -1263,12 +1283,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_TGENMATRIXNUMBER: - DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF); + //DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF); gstate.texmtxnum &= 0xFF00000F; break; case GE_CMD_TGENMATRIXDATA: - DEBUG_LOG(G3D,"DL TGEN data # %f", getFloat24(data)); + //DEBUG_LOG(G3D,"DL TGEN data # %f", getFloat24(data)); { int num = gstate.texmtxnum & 0xF; if (num < 12) @@ -1279,12 +1299,12 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_BONEMATRIXNUMBER: - DEBUG_LOG(G3D,"DL BONE #%i", data); + //DEBUG_LOG(G3D,"DL BONE #%i", data); gstate.boneMatrixNumber &= 0xFF00007F; break; case GE_CMD_BONEMATRIXDATA: - DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); + //DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); { int num = gstate.boneMatrixNumber & 0x7F; shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); @@ -1296,7 +1316,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; default: - DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); + //DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); break; //ETC... @@ -1322,8 +1342,15 @@ bool GLES_GPU::InterpretList() op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory u32 cmd = op >> 24; u32 diff = op ^ gstate.cmdmem[cmd]; - if (flushBeforeCommand_[cmd]) + if (flushBeforeCommand_[cmd] == 1 || (diff && flushBeforeCommand_[cmd] == 2)) transformDraw_.Flush(); + // TODO: Add a compiler flag to remove stuff like this at very-final build time. + if (dumpThisFrame_) { + char temp[256]; + GeDisassembleOp(dcontext.pc, op, prev, temp); + NOTICE_LOG(G3D, "%s", temp); + } + gstate.cmdmem[cmd] = op; ExecuteOp(op, diff); @@ -1368,10 +1395,10 @@ void GLES_GPU::DoBlockTransfer() int width = (gstate.transfersize & 0x3FF) + 1; int height = ((gstate.transfersize >> 10) & 0x3FF) + 1; - + int bpp = (gstate.transferstart & 1) ? 4 : 2; - DEBUG_LOG(HLE, "Block transfer: %08x to %08x, %i x %i , ...", srcBasePtr, dstBasePtr, width, height); + DEBUG_LOG(G3D, "Block transfer: %08x to %08x, %i x %i , ...", srcBasePtr, dstBasePtr, width, height); // Do the copy! for (int y = 0; y < height; y++) { diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 9d9a7f8733..ae22e56188 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -53,7 +53,9 @@ public: virtual void InvalidateCache(u32 addr, int size); virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders. + virtual void DumpNextFrame(); virtual void Flush(); + private: void DoBlockTransfer(); bool ProcessDLQueue(); @@ -65,7 +67,7 @@ private: FramebufferManager framebufferManager; TransformDrawEngine transformDraw_; ShaderManager *shaderManager_; - bool *flushBeforeCommand_; + u8 *flushBeforeCommand_; bool interruptsEnabled_; u32 displayFramebufPtr_; @@ -78,6 +80,9 @@ private: float renderWidthFactor_; float renderHeightFactor_; + bool dumpNextFrame_; + bool dumpThisFrame_; + struct CmdProcessorState { u32 pc; u32 stallAddr; diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 9b3228b826..a88d235a12 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -127,6 +127,7 @@ + @@ -145,6 +146,7 @@ AssemblyAndSourceCode + @@ -160,4 +162,4 @@ - \ No newline at end of file + diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index cad06fe3bf..81d71d9a52 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -54,4 +54,7 @@ public: virtual void DeviceLost() = 0; virtual void Flush() = 0; + + // Debugging + virtual void DumpNextFrame() = 0; }; diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp new file mode 100644 index 0000000000..3cb88d4e7d --- /dev/null +++ b/GPU/GeDisasm.cpp @@ -0,0 +1,735 @@ +// 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 "../Core/MemMap.h" + +#include "GPUState.h" +#include "ge_constants.h" + +void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { + u32 cmd = op >> 24; + u32 data = op & 0xFFFFFF; + + // Handle control and drawing commands here directly. The others we delegate. + switch (cmd) + { + case GE_CMD_BASE: + sprintf(buffer, "BASE: %06x", data & 0xFFFFFF); + break; + + case GE_CMD_VADDR: /// <<8???? + sprintf(buffer, "VADDR: %06x", gstate_c.vertexAddr); + break; + + case GE_CMD_IADDR: + sprintf(buffer, "IADDR: %06x", gstate_c.indexAddr); + break; + + case GE_CMD_PRIM: + { + u32 count = data & 0xFFFF; + u32 type = data >> 16; + static const char* types[7] = { + "POINTS=0,", + "LINES=1,", + "LINE_STRIP=2,", + "TRIANGLES=3,", + "TRIANGLE_STRIP=4,", + "TRIANGLE_FAN=5,", + "RECTANGLES=6,", + }; + sprintf(buffer, "DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); + } + break; + + // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. + case GE_CMD_BEZIER: + { + int bz_ucount = data & 0xFF; + int bz_vcount = (data >> 8) & 0xFF; + sprintf(buffer, "DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); + } + break; + + case GE_CMD_SPLINE: + { + int sp_ucount = data & 0xFF; + int sp_vcount = (data >> 8) & 0xFF; + int sp_utype = (data >> 16) & 0x3; + int sp_vtype = (data >> 18) & 0x3; + sprintf(buffer, "DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); + } + break; + + case GE_CMD_JUMP: + { + u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; + sprintf(buffer, "CMD JUMP - %08x to %08x", pc, target); + } + break; + + case GE_CMD_CALL: + { + u32 retval = pc + 4; + u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF; + sprintf(buffer, "CMD CALL - %08x to %08x, ret=%08x", pc, target, retval); + } + break; + + case GE_CMD_RET: + sprintf(buffer, "CMD RET"); + break; + + case GE_CMD_SIGNAL: + sprintf(buffer, "GE_CMD_SIGNAL %06x", data); + break; + + case GE_CMD_FINISH: + sprintf(buffer, "CMD FINISH %06x", data); + break; + + case GE_CMD_END: + sprintf(buffer, "CMD END"); + switch (prev >> 24) + { + case GE_CMD_SIGNAL: + { + // TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935# + int behaviour = (prev >> 16) & 0xFF; + int signal = prev & 0xFFFF; + int enddata = data & 0xFFFF; + // We should probably defer to sceGe here, no sense in implementing this stuff in every GPU + switch (behaviour) { + case 1: // Signal with Wait + sprintf(buffer, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + break; + case 2: + sprintf(buffer, "Signal without wait. signal/end: %04x %04x", signal, enddata); + break; + case 3: + sprintf(buffer, "Signal with Pause UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + break; + case 0x10: + sprintf(buffer, "Signal with Jump UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + break; + case 0x11: + sprintf(buffer, "Signal with Call UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + break; + case 0x12: + sprintf(buffer, "Signal with Return UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + break; + default: + sprintf(buffer, "UNKNOWN Signal UNIMPLEMENTED %i ! signal/end: %04x %04x", behaviour, signal, enddata); + break; + } + } + break; + case GE_CMD_FINISH: + break; + default: + sprintf(buffer, "Ah, not finished: %06x", prev & 0xFFFFFF); + break; + } + break; + + case GE_CMD_BJUMP: + // bounding box jump. Let's just not jump, for now. + sprintf(buffer, "BBOX JUMP - unimplemented"); + break; + + case GE_CMD_BOUNDINGBOX: + // bounding box test. Let's do nothing. + sprintf(buffer, "BBOX TEST - unimplemented"); + break; + + case GE_CMD_ORIGIN: + sprintf(buffer, "Origin: %06x", data); + break; + + case GE_CMD_VERTEXTYPE: + sprintf(buffer, "SetVertexType: %06x", data); + break; + + case GE_CMD_OFFSETADDR: + sprintf(buffer, "OffsetAddr: %06x", data); + break; + + case GE_CMD_REGION1: + { + int x1 = data & 0x3ff; + int y1 = data >> 10; + //topleft + sprintf(buffer, "Region TL: %d %d", x1, y1); + } + break; + + case GE_CMD_REGION2: + { + int x2 = data & 0x3ff; + int y2 = data >> 10; + sprintf(buffer, "Region BR: %d %d", x2, y2); + } + break; + + case GE_CMD_CLIPENABLE: + sprintf(buffer, "Clip Enable: %i (ignoring)", data); + //we always clip, this is opengl + break; + + case GE_CMD_CULLFACEENABLE: + sprintf(buffer, "CullFace Enable: %i (ignoring)", data); + break; + + case GE_CMD_TEXTUREMAPENABLE: + sprintf(buffer, "Texture map enable: %i", data); + break; + + case GE_CMD_LIGHTINGENABLE: + sprintf(buffer, "Lighting enable: %i", data); + break; + + case GE_CMD_FOGENABLE: + sprintf(buffer, "Fog Enable: %i", data); + break; + + case GE_CMD_DITHERENABLE: + sprintf(buffer, "Dither Enable: %i", data); + break; + + case GE_CMD_OFFSETX: + sprintf(buffer, "Offset X: %i", data); + break; + + case GE_CMD_OFFSETY: + sprintf(buffer, "Offset Y: %i", data); + break; + + case GE_CMD_TEXSCALEU: + sprintf(buffer, "Texture U Scale: %f", gstate_c.uScale); + break; + + case GE_CMD_TEXSCALEV: + sprintf(buffer, "Texture V Scale: %f", gstate_c.vScale); + break; + + case GE_CMD_TEXOFFSETU: + sprintf(buffer, "Texture U Offset: %f", gstate_c.uOff); + break; + + case GE_CMD_TEXOFFSETV: + sprintf(buffer, "Texture V Offset: %f", gstate_c.vOff); + break; + + case GE_CMD_SCISSOR1: + { + int x1 = data & 0x3ff; + int y1 = data >> 10; + sprintf(buffer, "Scissor TL: %i, %i", x1,y1); + } + break; + case GE_CMD_SCISSOR2: + { + int x2 = data & 0x3ff; + int y2 = data >> 10; + sprintf(buffer, "Scissor BR: %i, %i", x2, y2); + } + break; + + case GE_CMD_MINZ: + { + float zMin = getFloat24(data) / 65535.f; + sprintf(buffer, "MinZ: %f", zMin); + } + break; + + case GE_CMD_MAXZ: + { + float zMax = getFloat24(data) / 65535.f; + sprintf(buffer, "MaxZ: %f", zMax); + } + break; + + case GE_CMD_FRAMEBUFPTR: + { + u32 ptr = op & 0xFFE000; + sprintf(buffer, "FramebufPtr: %08x", ptr); + } + break; + + case GE_CMD_FRAMEBUFWIDTH: + { + u32 w = data & 0xFFFFFF; + sprintf(buffer, "FramebufWidth: %i", w); + } + break; + + case GE_CMD_FRAMEBUFPIXFORMAT: + break; + + case GE_CMD_TEXADDR0: + case GE_CMD_TEXADDR1: + case GE_CMD_TEXADDR2: + case GE_CMD_TEXADDR3: + case GE_CMD_TEXADDR4: + case GE_CMD_TEXADDR5: + case GE_CMD_TEXADDR6: + case GE_CMD_TEXADDR7: + sprintf(buffer, "Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); + break; + + case GE_CMD_TEXBUFWIDTH0: + case GE_CMD_TEXBUFWIDTH1: + case GE_CMD_TEXBUFWIDTH2: + case GE_CMD_TEXBUFWIDTH3: + case GE_CMD_TEXBUFWIDTH4: + case GE_CMD_TEXBUFWIDTH5: + case GE_CMD_TEXBUFWIDTH6: + case GE_CMD_TEXBUFWIDTH7: + sprintf(buffer, "Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); + break; + + case GE_CMD_CLUTADDR: + sprintf(buffer, "CLUT base addr: %06x", data); + break; + + case GE_CMD_CLUTADDRUPPER: + sprintf(buffer, "CLUT addr upper %08x", data); + break; + + case GE_CMD_LOADCLUT: + // This could be used to "dirty" textures with clut. + sprintf(buffer, "Clut load"); + break; + + case GE_CMD_TEXMAPMODE: + sprintf(buffer, "Tex map mode: %06x", data); + break; + + case GE_CMD_TEXSHADELS: + sprintf(buffer, "Tex shade light sources: %06x", data); + break; + + case GE_CMD_CLUTFORMAT: + { + sprintf(buffer, "Clut format: %06x", data); + } + break; + + case GE_CMD_TRANSFERSRC: + { + // Nothing to do, the next one prints + } + break; + + case GE_CMD_TRANSFERSRCW: + { + u32 xferSrc = gstate.transfersrc | ((data&0xFF0000)<<8); + u32 xferSrcW = gstate.transfersrcw & 1023; + sprintf(buffer, "Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); + break; + } + + case GE_CMD_TRANSFERDST: + { + // Nothing to do, the next one prints + } + break; + + case GE_CMD_TRANSFERDSTW: + { + u32 xferDst= gstate.transferdst | ((data&0xFF0000)<<8); + u32 xferDstW = gstate.transferdstw & 1023; + sprintf(buffer, "Block Transfer Dest: %08x W: %i", xferDst, xferDstW); + break; + } + + case GE_CMD_TRANSFERSRCPOS: + { + u32 x = (data & 1023)+1; + u32 y = ((data>>10) & 1023)+1; + sprintf(buffer, "Block Transfer Src Rect TL: %i, %i", x, y); + break; + } + + case GE_CMD_TRANSFERDSTPOS: + { + u32 x = (data & 1023)+1; + u32 y = ((data>>10) & 1023)+1; + sprintf(buffer, "Block Transfer Dest Rect TL: %i, %i", x, y); + break; + } + + case GE_CMD_TRANSFERSIZE: + { + u32 w = (data & 1023)+1; + u32 h = ((data>>10) & 1023)+1; + sprintf(buffer, "Block Transfer Rect Size: %i x %i", w, h); + break; + } + + case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK + { + sprintf(buffer, "Block Transfer Start"); + break; + } + + case GE_CMD_TEXSIZE0: + case GE_CMD_TEXSIZE1: + case GE_CMD_TEXSIZE2: + case GE_CMD_TEXSIZE3: + case GE_CMD_TEXSIZE4: + case GE_CMD_TEXSIZE5: + case GE_CMD_TEXSIZE6: + case GE_CMD_TEXSIZE7: + sprintf(buffer, "Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); + break; + + case GE_CMD_ZBUFPTR: + { + u32 ptr = op & 0xFFE000; + sprintf(buffer, "Zbuf Ptr: %06x", ptr); + } + break; + + case GE_CMD_ZBUFWIDTH: + { + u32 w = data & 0xFFFFFF; + sprintf(buffer, "Zbuf Width: %i", w); + } + break; + + case GE_CMD_AMBIENTCOLOR: + sprintf(buffer, "Ambient Color: %06x", data); + break; + + case GE_CMD_AMBIENTALPHA: + sprintf(buffer, "Ambient Alpha: %06x", data); + break; + + case GE_CMD_MATERIALAMBIENT: + sprintf(buffer, "Material Ambient Color: %06x", data); + break; + + case GE_CMD_MATERIALDIFFUSE: + sprintf(buffer, "Material Diffuse Color: %06x", data); + break; + + case GE_CMD_MATERIALEMISSIVE: + sprintf(buffer, "Material Emissive Color: %06x", data); + break; + + case GE_CMD_MATERIALSPECULAR: + sprintf(buffer, "Material Specular Color: %06x", data); + break; + + case GE_CMD_MATERIALALPHA: + sprintf(buffer, "Material Alpha Color: %06x", data); + break; + + case GE_CMD_MATERIALSPECULARCOEF: + sprintf(buffer, "Material specular coef: %f", getFloat24(data)); + break; + + case GE_CMD_LIGHTTYPE0: + case GE_CMD_LIGHTTYPE1: + case GE_CMD_LIGHTTYPE2: + case GE_CMD_LIGHTTYPE3: + sprintf(buffer, "Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); + break; + + case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: + case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1: + case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: + case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: + { + int n = cmd - GE_CMD_LX0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + sprintf(buffer, "Light %i %c pos: %f", l, c+'X', val); + } + break; + + case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0: + case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1: + case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: + case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: + { + int n = cmd - GE_CMD_LDX0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + sprintf(buffer, "Light %i %c dir: %f", l, c+'X', val); + } + break; + + case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0: + case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1: + case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: + case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: + { + int n = cmd - GE_CMD_LKA0; + int l = n / 3; + int c = n % 3; + float val = getFloat24(data); + sprintf(buffer, "Light %i %c att: %f", l, c+'X', val); + } + break; + + + case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3: + case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: + case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: + { + float r = (float)(data & 0xff)/255.0f; + float g = (float)((data>>8) & 0xff)/255.0f; + float b = (float)(data>>16)/255.0f; + + int l = (cmd - GE_CMD_LAC0) / 3; + int t = (cmd - GE_CMD_LAC0) % 3; + sprintf(buffer, "Light %i color %i: %f %f %f", l, t, r, g, b); + } + break; + + case GE_CMD_VIEWPORTX1: + case GE_CMD_VIEWPORTY1: + case GE_CMD_VIEWPORTX2: + case GE_CMD_VIEWPORTY2: + sprintf(buffer, "Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); + break; + case GE_CMD_VIEWPORTZ1: + { + float zScale = getFloat24(data) / 65535.f; + sprintf(buffer, "Z scale: %f", zScale); + } + break; + case GE_CMD_VIEWPORTZ2: + { + float zOff = getFloat24(data) / 65535.f; + sprintf(buffer, "Z pos: %f", zOff); + } + break; + case GE_CMD_LIGHTENABLE0: + case GE_CMD_LIGHTENABLE1: + case GE_CMD_LIGHTENABLE2: + case GE_CMD_LIGHTENABLE3: + sprintf(buffer, "Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); + break; + case GE_CMD_CULL: + sprintf(buffer, "cull: %06x", data); + break; + + case GE_CMD_LMODE: + sprintf(buffer, "Shade mode: %06x", data); + break; + + case GE_CMD_PATCHDIVISION: + { + int patch_div_s = data & 0xFF; + int patch_div_t = (data >> 8) & 0xFF; + sprintf(buffer, "Patch subdivision: %i x %i", patch_div_s, patch_div_t); + } + break; + + case GE_CMD_MATERIALUPDATE: + sprintf(buffer, "Material Update: %d", data); + break; + + + ////////////////////////////////////////////////////////////////// + // CLEARING + ////////////////////////////////////////////////////////////////// + case GE_CMD_CLEARMODE: + // If it becomes a performance problem, check diff&1 + sprintf(buffer, "Clear mode: %06x", data); + break; + + + ////////////////////////////////////////////////////////////////// + // ALPHA BLENDING + ////////////////////////////////////////////////////////////////// + case GE_CMD_ALPHABLENDENABLE: + sprintf(buffer, "Alpha blend enable: %d", data); + break; + + case GE_CMD_BLENDMODE: + sprintf(buffer, "Blend mode: %06x", data); + break; + + case GE_CMD_BLENDFIXEDA: + sprintf(buffer, "Blend fix A: %06x", data); + break; + + case GE_CMD_BLENDFIXEDB: + sprintf(buffer, "Blend fix B: %06x", data); + break; + + case GE_CMD_ALPHATESTENABLE: + sprintf(buffer, "Alpha test enable: %d", data); + break; + + case GE_CMD_ALPHATEST: + sprintf(buffer, "Alpha test settings"); + break; + + case GE_CMD_ANTIALIASENABLE: + sprintf(buffer, "Antialias enable: %d", data); + break; + + case GE_CMD_PATCHCULLENABLE: + sprintf(buffer, "Antialias enable: %d", data); + break; + + case GE_CMD_COLORTESTENABLE: + sprintf(buffer, "Color Test enable: %d", data); + break; + + case GE_CMD_LOGICOPENABLE: + sprintf(buffer, "Logic op enable: %d", data); + break; + + case GE_CMD_TEXFUNC: + sprintf(buffer, "TexFunc %i", data&7); + break; + + case GE_CMD_TEXFILTER: + { + int min = data & 7; + int mag = (data >> 8) & 1; + sprintf(buffer, "TexFilter min: %i mag: %i", min, mag); + } + break; + + case GE_CMD_TEXENVCOLOR: + sprintf(buffer, "TexEnvColor %06x", data); + break; + + case GE_CMD_TEXMODE: + sprintf(buffer, "TexMode %08x", data); + break; + + case GE_CMD_TEXFORMAT: + sprintf(buffer, "TexFormat %08x", data); + break; + + case GE_CMD_TEXFLUSH: + sprintf(buffer, "TexFlush"); + break; + + case GE_CMD_TEXWRAP: + sprintf(buffer, "TexWrap %08x", data); + break; + ////////////////////////////////////////////////////////////////// + // Z/STENCIL TESTING + ////////////////////////////////////////////////////////////////// + + case GE_CMD_ZTESTENABLE: + sprintf(buffer, "Z test enable: %d", data & 1); + break; + + case GE_CMD_STENCILTESTENABLE: + sprintf(buffer, "Stencil test enable: %d", data); + break; + + case GE_CMD_ZTEST: + sprintf(buffer, "Z test mode: %i", data); + break; + + case GE_CMD_MORPHWEIGHT0: + case GE_CMD_MORPHWEIGHT1: + case GE_CMD_MORPHWEIGHT2: + case GE_CMD_MORPHWEIGHT3: + case GE_CMD_MORPHWEIGHT4: + case GE_CMD_MORPHWEIGHT5: + case GE_CMD_MORPHWEIGHT6: + case GE_CMD_MORPHWEIGHT7: + { + int index = cmd - GE_CMD_MORPHWEIGHT0; + float weight = getFloat24(data); + sprintf(buffer, "MorphWeight %i = %f", index, weight); + } + break; + + case GE_CMD_DITH0: + case GE_CMD_DITH1: + case GE_CMD_DITH2: + case GE_CMD_DITH3: + sprintf(buffer, "DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); + break; + + case GE_CMD_LOGICOP: + sprintf(buffer, "LogicOp: %06x", data); + break; + + case GE_CMD_ZWRITEDISABLE: + sprintf(buffer, "ZMask: %06x", data); + break; + + case GE_CMD_MASKRGB: + sprintf(buffer, "MaskRGB: %06x", data); + break; + + case GE_CMD_MASKALPHA: + sprintf(buffer, "MaskAlpha: %06x", data); + break; + + case GE_CMD_WORLDMATRIXNUMBER: + sprintf(buffer, "World # %i", data & 0xF); + break; + + case GE_CMD_WORLDMATRIXDATA: + sprintf(buffer, "World data # %f", getFloat24(data)); + break; + + case GE_CMD_VIEWMATRIXNUMBER: + sprintf(buffer, "VIEW # %i", data & 0xF); + break; + + case GE_CMD_VIEWMATRIXDATA: + sprintf(buffer, "VIEW data # %f", getFloat24(data)); + break; + + case GE_CMD_PROJMATRIXNUMBER: + sprintf(buffer, "PROJECTION # %i", data & 0xF); + break; + + case GE_CMD_PROJMATRIXDATA: + sprintf(buffer, "PROJECTION matrix data # %f", getFloat24(data)); + break; + + case GE_CMD_TGENMATRIXNUMBER: + sprintf(buffer, "TGEN # %i", data & 0xF); + break; + + case GE_CMD_TGENMATRIXDATA: + sprintf(buffer, "TGEN data # %f", getFloat24(data)); + break; + + case GE_CMD_BONEMATRIXNUMBER: + sprintf(buffer, "BONE #%i", data); + break; + + case GE_CMD_BONEMATRIXDATA: + sprintf(buffer, "BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); + break; + + default: + sprintf(buffer, "Unknown: %08x @ %08x", op, pc); + break; + } +} + diff --git a/GPU/GeDisasm.h b/GPU/GeDisasm.h new file mode 100644 index 0000000000..6badfc49a3 --- /dev/null +++ b/GPU/GeDisasm.h @@ -0,0 +1,18 @@ +// 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/. + +void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer); diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 05b98aa851..5e9f163713 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -45,6 +45,7 @@ public: virtual void Flush() {} virtual void DeviceLost() {} + virtual void DumpNextFrame() {} private: bool ProcessDLQueue(); diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index d23449f88c..319a0c4ca9 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -52,11 +52,11 @@ enum GECommand GE_CMD_DITHERENABLE, GE_CMD_ALPHABLENDENABLE=0x21, GE_CMD_ALPHATESTENABLE=0x22, - GE_CMD_ZTESTENABLE, + GE_CMD_ZTESTENABLE=0x23, GE_CMD_STENCILTESTENABLE=0x24, - GE_CMD_ANTIALIASENABLE, + GE_CMD_ANTIALIASENABLE=0x25, GE_CMD_PATCHCULLENABLE=0x26, - GE_CMD_COLORTESTENABLE, + GE_CMD_COLORTESTENABLE=0x27, GE_CMD_LOGICOPENABLE=0x28, GE_CMD_BONEMATRIXNUMBER=0x2A, GE_CMD_BONEMATRIXDATA=0x2B, diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 84ddbce292..409fffe706 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -69,6 +69,7 @@ LOCAL_SRC_FILES := \ $(SRC)/Common/MathUtil.cpp \ $(SRC)/GPU/Math3D.cpp \ $(SRC)/GPU/GPUState.cpp \ + $(SRC)/GPU/GeDisasm.cpp \ $(SRC)/GPU/GLES/Framebuffer.cpp \ $(SRC)/GPU/GLES/DisplayListInterpreter.cpp \ $(SRC)/GPU/GLES/TextureCache.cpp \ diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index f557e43584..b35ae132a7 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -31,6 +31,9 @@ #include "util/random/rng.h" #include "UIShader.h" +#include "../../GPU/ge_constants.h" +#include "../../GPU/GPUState.h" +#include "../../GPU/GPUInterface.h" #include "../../Core/Config.h" #include "../../Core/CoreParameter.h" @@ -62,7 +65,6 @@ static void DrawBackground(float alpha) { static float ybase[100] = {0}; if (xbase[0] == 0.0f) { GMRng rng; - printf("%i %i AAAH\n", dp_xres, dp_yres); for (int i = 0; i < 100; i++) { xbase[i] = rng.F() * dp_xres; ybase[i] = rng.F() * dp_yres; @@ -109,9 +111,9 @@ void LogoScreen::render() { UIBegin(); DrawBackground(alpha); - ui_draw2d.SetFontScale(1.5f,1.5f); + ui_draw2d.SetFontScale(1.5f, 1.5f); ui_draw2d.DrawText(UBUNTU48, "PPSSPP", dp_xres / 2, dp_yres / 2 - 30, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); - ui_draw2d.SetFontScale(1.0f,1.0f); + ui_draw2d.SetFontScale(1.0f, 1.0f); ui_draw2d.DrawText(UBUNTU24, "Created by Henrik Rydgard", dp_xres / 2, dp_yres / 2 + 40, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); ui_draw2d.DrawText(UBUNTU24, "Free Software under GPL 2.0", dp_xres / 2, dp_yres / 2 + 70, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); ui_draw2d.DrawText(UBUNTU24, "www.ppsspp.org", dp_xres / 2, dp_yres / 2 + 130, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); @@ -220,6 +222,11 @@ void InGameMenuScreen::render() { if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Return to Menu", ALIGN_RIGHT)) { screenManager()->finishDialog(this, DR_OK); } + + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Dump Next Frame", ALIGN_RIGHT)) { + gpu->DumpNextFrame(); + } + DrawWatermark(); UIEnd(); diff --git a/android/jni/NativeApp.cpp b/android/jni/NativeApp.cpp index 1a9fb6e7b4..d732413783 100644 --- a/android/jni/NativeApp.cpp +++ b/android/jni/NativeApp.cpp @@ -174,6 +174,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co g_Config.Load(config_filename.c_str()); + const char *fileToLog = 0; + bool gfxLog = false; // Parse command line LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO; @@ -199,6 +201,10 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co g_Config.iCpuCore = CPU_INTERPRETER; g_Config.bSaveSettings = false; break; + case '-': + if (!strncmp(argv[i], "--log=", strlen("--log=")) && strlen(argv[i]) > strlen("--log=")) + fileToLog = argv[i] + strlen("--log="); + break; } } else { if (boot_filename.empty()) { @@ -215,6 +221,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co } } + if (fileToLog != NULL) + LogManager::GetInstance()->ChangeFileLog(fileToLog); + if (g_Config.currentDirectory == "") { #if defined(ANDROID) || defined(BLACKBERRY) || defined(__SYMBIAN32__) g_Config.currentDirectory = external_directory; From 1a378ea7a923bd42d1e342b92454fbf8a87d12a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 27 Dec 2012 23:41:22 +0100 Subject: [PATCH 230/276] Try to fix linux build --- Core/FileSystems/DirectoryFileSystem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 611f8b7e65..51dbcc7979 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #endif #include "FileUtil.h" @@ -55,7 +56,8 @@ static bool FixFilenameCase(const std::string &path, std::string &filename) while (!readdir_r(dirp, (dirent*) &diren, &result) && result) { - if (result->d_namlen != filenameSize) + // Hm, is this check UTF-8 compatible? (size vs strlen) + if (strlen(result->d_name) != filenameSize) continue; size_t i; From 3e8561ab5b9ce203f7125a9d0e414525b117c16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 27 Dec 2012 23:45:06 +0100 Subject: [PATCH 231/276] ge: fix bug with indexed primitives --- GPU/GLES/IndexGenerator.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/GPU/GLES/IndexGenerator.cpp b/GPU/GLES/IndexGenerator.cpp index 32cbcc78a9..0193c88203 100644 --- a/GPU/GLES/IndexGenerator.cpp +++ b/GPU/GLES/IndexGenerator.cpp @@ -283,8 +283,8 @@ void IndexGenerator::TranslateLineList(int numVerts, const u8 *inds, int offset) int numLines = numVerts / 2; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + offset + inds_[i*2]; - *inds_++ = index_ + offset + inds_[i*2+1]; + *inds_++ = index_ + offset + inds[i*2]; + *inds_++ = index_ + offset + inds[i*2+1]; } index_ += numVerts; count_ += numLines * 2; @@ -297,8 +297,8 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u8 *inds, int offset int numLines = numVerts - 1; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + offset + inds_[i]; - *inds_++ = index_ + offset + inds_[i + 1]; + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; } index_ += numVerts; count_ += numLines * 2; @@ -311,8 +311,8 @@ void IndexGenerator::TranslateLineList(int numVerts, const u16 *inds, int offset int numLines = numVerts / 2; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + offset + inds_[i*2]; - *inds_++ = index_ + offset + inds_[i*2+1]; + *inds_++ = index_ + offset + inds[i*2]; + *inds_++ = index_ + offset + inds[i*2+1]; } index_ += numVerts; count_ += numLines * 2; @@ -325,8 +325,8 @@ void IndexGenerator::TranslateLineStrip(int numVerts, const u16 *inds, int offse int numLines = numVerts - 1; for (int i = 0; i < numLines; i++) { - *inds_++ = index_ + offset + inds_[i]; - *inds_++ = index_ + offset + inds_[i + 1]; + *inds_++ = index_ + offset + inds[i]; + *inds_++ = index_ + offset + inds[i + 1]; } index_ += numVerts; count_ += numLines * 2; @@ -339,8 +339,8 @@ void IndexGenerator::TranslateRectangles(int numVerts, const u8 *inds, int offse int numRects = numVerts / 2; for (int i = 0; i < numRects; i++) { - *inds_++ = index_ + offset + inds_[i*2]; - *inds_++ = index_ + offset + inds_[i*2+1]; + *inds_++ = index_ + offset + inds[i*2]; + *inds_++ = index_ + offset + inds[i*2+1]; } index_ += numVerts; count_ += numRects * 2; @@ -353,8 +353,8 @@ void IndexGenerator::TranslateRectangles(int numVerts, const u16 *inds, int offs int numRects = numVerts / 2; for (int i = 0; i < numRects; i++) { - *inds_++ = index_ + offset + inds_[i*2]; - *inds_++ = index_ + offset + inds_[i*2+1]; + *inds_++ = index_ + offset + inds[i*2]; + *inds_++ = index_ + offset + inds[i*2+1]; } index_ += numVerts; count_ += numRects * 2; From 8ed8f57a7f61ce75d7be44bee3bd520a8c38972c Mon Sep 17 00:00:00 2001 From: Arthur Blot Date: Fri, 28 Dec 2012 01:05:03 +0100 Subject: [PATCH 232/276] Hopefully fix all the ELF loading issues --- Core/ELF/ElfReader.cpp | 17 ++++++++++------- Core/ELF/ElfReader.h | 4 ++++ Core/HLE/sceKernelModule.cpp | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index a397b9b1fa..2969b975e5 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -318,17 +318,20 @@ bool ElfReader::LoadInto(u32 loadAddress) } // Segment relocations (a few games use them) - for (int i=0; ie_phnum; i++) + if (GetNumSections() == 0) { - Elf32_Phdr *p = &segments[i]; - if (p->p_type == 0x700000A0) + for (int i=0; ie_phnum; i++) { - INFO_LOG(LOADER,"Loading segment relocations"); + Elf32_Phdr *p = &segments[i]; + if (p->p_type == 0x700000A0) + { + INFO_LOG(LOADER,"Loading segment relocations"); - int numRelocs = p->p_filesz / sizeof(Elf32_Rel); + int numRelocs = p->p_filesz / sizeof(Elf32_Rel); - Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i); - LoadRelocations(rels, numRelocs); + Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i); + LoadRelocations(rels, numRelocs); + } } } diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index d23cf2a550..9e98b46b9f 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -105,6 +105,10 @@ public: { return segments[segment].p_offset; } + u32 GetSegmentVaddr(int segment) + { + return segmentVAddr[segment]; + } bool DidRelocate() { return bRelocate; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 46305fe375..a1b045bc9f 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -249,7 +249,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro if (sceModuleInfoSection != -1) modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSectionAddr(sceModuleInfoSection)); else - modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetVaddr() + (reader.GetSegmentPaddr(0) & 0x7FFFFFFF) - reader.GetSegmentOffset(0)); + modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSegmentVaddr(0) + (reader.GetSegmentPaddr(0) & 0x7FFFFFFF) - reader.GetSegmentOffset(0)); // Check for module blacklist - we don't allow games to load these modules from disc // as we have HLE implementations and the originals won't run in the emu because they From 91c188c4d05e150dd905a3d170cbae035f7dc0fc Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 28 Dec 2012 11:22:12 +0800 Subject: [PATCH 233/276] Border cosmetic fix in save/load menu --- Core/Util/PPGeDraw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 57e79195e6..f7655f0cbc 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -279,8 +279,8 @@ void PPGeDraw4Patch(int atlasImage, float x, float y, float w, float h, u32 colo if (!dlPtr) return; const AtlasImage &img = ppge_images[atlasImage]; - float borderx = img.w / 2; - float bordery = img.h / 2; + float borderx = img.w / 20; + float bordery = img.h / 20; float u1 = img.u1, uhalf = (img.u1 + img.u2) / 2, u2 = img.u2; float v1 = img.v1, vhalf = (img.v1 + img.v2) / 2, v2 = img.v2; float xmid1 = x + borderx; From cb2d8d5c755849a8a2262c46f70b660e9278a1c3 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 28 Dec 2012 11:40:44 +0800 Subject: [PATCH 234/276] Add 2 stubs in sceAtrac --- Core/HLE/sceAtrac.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index ae6b3e8589..37d9c148cc 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -71,12 +71,16 @@ u32 sceAtracGetBufferInfoForReseting(int atracID, int sample, u32 bufferInfoAddr u32 sceAtracGetBitrate(int atracID, u32 outBitrateAddr) { ERROR_LOG(HLE, "UNIMPL sceAtracGetBitrate(%i, %08x)", atracID, outBitrateAddr); + if (Memory::IsValidAddress(outBitrateAddr)) + Memory::Write_U32(64, outBitrateAddr); return 0; } u32 sceAtracGetChannel(int atracID, u32 channelAddr) { ERROR_LOG(HLE, "UNIMPL sceAtracGetChannel(%i, %08x)", atracID, channelAddr); + if (Memory::IsValidAddress(channelAddr)) + Memory::Write_U32(2, channelAddr); return 0; } From f78c519a96094625c7a059c9ddf1d0caff955d20 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 28 Dec 2012 12:03:53 +0800 Subject: [PATCH 235/276] OSK dialog cosmetic fix --- Core/Dialog/PSPOskDialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index a1c6e8fe7b..791a6d565d 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -106,8 +106,8 @@ void PSPOskDialog::RenderKeyboard() if (limit <= 0) limit = 16; - const float keyboardLeftSide = (480.0f - (16.0f * KEYSPERROW)) / 2.0f; - float previewLeftSide = (480.0f - (16.0f * limit)) / 2.0f; + const float keyboardLeftSide = (480.0f - (23.0f * KEYSPERROW)) / 2.0f; + float previewLeftSide = (480.0f - (15.0f * limit)) / 2.0f; PPGeDrawText(oskDesc.c_str(), 480/2, 20, PPGE_ALIGN_CENTER, 0.5f, 0xFFFFFFFF); for (int i = 0; i < limit; ++i) @@ -134,10 +134,10 @@ void PSPOskDialog::RenderKeyboard() color = 0xFF7f7f7f; temp[0] = oskKeys[row][col]; - PPGeDrawText(temp, keyboardLeftSide + (16.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, color); + PPGeDrawText(temp, keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, color); if (selectedRow == row && col == selectedExtra) - PPGeDrawText("_", keyboardLeftSide + (16.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, 0xFFFFFFFF); + PPGeDrawText("_", keyboardLeftSide + (25.0f * col), 70.0f + (25.0f * row), NULL, 0.6f, 0xFFFFFFFF); } } From a23ca01f16874b2f600de6815c51700e5e83f530 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Mon, 24 Dec 2012 22:28:10 +0100 Subject: [PATCH 236/276] Mode 8 Correction Modif for save encryption in Param.sfo and export save filename and encode key in a file --- Core/Dialog/PSPSaveDialog.cpp | 4 +-- Core/Dialog/SavedataParam.cpp | 46 +++++++++++++++++++++++++++++------ Core/ELF/ParamSFO.cpp | 44 ++++++++++++++++++--------------- Core/ELF/ParamSFO.h | 40 ++++++++++++++++++++++++++++-- 4 files changed, 104 insertions(+), 30 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 2660f562eb..92a0a5e398 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -47,8 +47,8 @@ int PSPSaveDialog::Init(int paramAddr) u32 retval = param.SetPspParam(&request); - DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); - DEBUG_LOG(HLE,"Mode: %i", param.GetPspParam()->mode); + INFO_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); + INFO_LOG(HLE,"Mode: %i", param.GetPspParam()->mode); switch(param.GetPspParam()->mode) { diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index af3cb111be..ec8ee4cc7a 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -184,8 +184,20 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4); sfoFile.SetValue("CATEGORY","MS",4); sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); - sfoFile.SetValue("SAVEDATA_FILE_LIST","",3168); // This need to be filed with the save filename and a hash - sfoFile.SetValue("SAVEDATA_PARAMS","",128); // This need to be filled with a hash of the save file encrypted. + + // For each file, 32 bytes for filename, 32 bytes for file hash (0 in PPSSPP) + u8* tmpData = new u8[3168]; + memset(tmpData, 0, 3168); + sprintf((char*)tmpData,"%s",GetFileName(param).c_str()); + sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, 3168, 3168); + delete[] tmpData; + + // No crypted save, so fill with 0 + tmpData = new u8[128]; + memset(tmpData, 0, 128); + sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128); + delete[] tmpData; + u8 *sfoData; size_t sfoSize; sfoFile.WriteSFO(&sfoData,&sfoSize); @@ -222,6 +234,23 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) std::string snd0path = dirPath+"/"+snd0Name; WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); } + + // Save Encryption Data + { + int dataSize = 16+16; // key + save filename + data_ = new u8[dataSize]; + memset(data_,0,dataSize); + sprintf((char*)data_,GetFileName(param).c_str(),GetFileName(param).size()); + if(param->size > 1500) + memcpy(data_+16,param->key,16); + std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; + handle = pspFileSystem.OpenFile(encryptInfoPath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); + if (handle) + { + pspFileSystem.WriteFile(handle, data_, dataSize); + pspFileSystem.CloseFile(handle); + } + } } return true; } @@ -293,6 +322,8 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) return false; } + bool ret = true; + if (Memory::IsValidAddress(param->msFree)) { Memory::Write_U32((u32)MemoryStick_SectorSize(),param->msFree); // cluster Size @@ -317,12 +348,13 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) } else { - Memory::Write_U32(1,param->msData+36); - Memory::Write_U32(0x20,param->msData+40); + Memory::Write_U32(0,param->msData+36); + Memory::Write_U32(0,param->msData+40); Memory::Write_U8(0,param->msData+44); - Memory::Write_U32(0x20,param->msData+52); + Memory::Write_U32(0,param->msData+52); Memory::Write_U8(0,param->msData+56); - //return false; + ret = false; + // this should return SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA } } if (Memory::IsValidAddress(param->utilityData)) @@ -345,7 +377,7 @@ bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) Memory::Memset(param->utilityData+20,0,spaceTxt.size()+1); Memory::Memcpy(param->utilityData+20,spaceTxt.c_str(),spaceTxt.size()); // save size in text } - return true; + return ret; } diff --git a/Core/ELF/ParamSFO.cpp b/Core/ELF/ParamSFO.cpp index e2b423b29e..7965c1455b 100644 --- a/Core/ELF/ParamSFO.cpp +++ b/Core/ELF/ParamSFO.cpp @@ -46,23 +46,18 @@ void ParamSFOData::SetValue(std::string key, unsigned int value, int max_size) } void ParamSFOData::SetValue(std::string key, std::string value, int max_size) { - if(key == "ACCOUNT_ID" || - key == "PADDING" || - key == "PARAMS" || - key == "PARAMS2" || - key == "SAVEDATA_FILE_LIST" || - key == "SAVEDATA_PARAMS") - { - values[key].type = VT_UTF8_SPE; - } - else - { - values[key].type = VT_UTF8; - } + values[key].type = VT_UTF8; values[key].s_value = value; values[key].max_size = max_size; } +void ParamSFOData::SetValue(std::string key, const u8* value, unsigned int size, int max_size) +{ + values[key].type = VT_UTF8_SPE; + values[key].SetData(value,size); + values[key].max_size = max_size; +} + int ParamSFOData::GetValueInt(std::string key) { std::map::iterator it = values.find(key); @@ -73,10 +68,21 @@ int ParamSFOData::GetValueInt(std::string key) std::string ParamSFOData::GetValueString(std::string key) { std::map::iterator it = values.find(key); - if(it == values.end() || (it->second.type != VT_UTF8 && it->second.type != VT_UTF8_SPE)) + if(it == values.end() || (it->second.type != VT_UTF8)) return ""; return it->second.s_value; } +u8* ParamSFOData::GetValueData(std::string key, unsigned int *size) +{ + std::map::iterator it = values.find(key); + if(it == values.end() || (it->second.type != VT_UTF8_SPE)) + return 0; + if(size) + { + *size = it->second.u_size; + } + return it->second.u_value; +} // I'm so sorry Ced but this is highly endian unsafe :( bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) @@ -108,9 +114,9 @@ bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) case 0x0004: // Special format UTF-8 { - const char *utfdata = (const char *)(data_start + indexTables[i].data_table_offset); + const u8 *utfdata = (const u8 *)(data_start + indexTables[i].data_table_offset); DEBUG_LOG(LOADER, "%s %s", key, utfdata); - SetValue(key,std::string(utfdata,indexTables[i].param_len),indexTables[i].param_max_len); + SetValue(key, utfdata, indexTables[i].param_len, indexTables[i].param_max_len); } break; case 0x0204: @@ -187,10 +193,10 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) else if(it->second.type == VT_UTF8_SPE) { index_ptr->param_fmt = 0x0004; - index_ptr->param_len = it->second.s_value.size()+1; + index_ptr->param_len = it->second.u_size; - memcpy(data_ptr,it->second.s_value.c_str(),index_ptr->param_len); - data_ptr[index_ptr->param_len] = 0; + memset(data_ptr,0,index_ptr->param_max_len); + memcpy(data_ptr,it->second.u_value,index_ptr->param_len); } else if(it->second.type == VT_UTF8) { diff --git a/Core/ELF/ParamSFO.h b/Core/ELF/ParamSFO.h index 3d3441c521..fc4e07efc7 100644 --- a/Core/ELF/ParamSFO.h +++ b/Core/ELF/ParamSFO.h @@ -25,9 +25,11 @@ class ParamSFOData public: void SetValue(std::string key, unsigned int value, int max_size); void SetValue(std::string key, std::string value, int max_size); + void SetValue(std::string key, const u8* value, unsigned int size, int max_size); int GetValueInt(std::string key); std::string GetValueString(std::string key); + u8* GetValueData(std::string key, unsigned int *size); bool ReadSFO(const u8 *paramsfo, size_t size); bool WriteSFO(u8 **paramsfo, size_t *size); @@ -37,14 +39,48 @@ private: { VT_INT, VT_UTF8, - VT_UTF8_SPE + VT_UTF8_SPE // raw data in u8 }; - struct ValueData + class ValueData { + public: ValueType type; int max_size; std::string s_value; int i_value; + + u8* u_value; + unsigned int u_size; + + void SetData(const u8* data, int size) + { + if(u_value) + { + delete[] u_value; + u_value = 0; + } + if(size > 0) + { + u_value = new u8[size]; + memcpy(u_value,data,size); + } + u_size = size; + } + + ValueData() + { + u_value = 0; + u_size = 0; + type = VT_INT; + max_size = 0; + i_value = 0; + } + + ~ValueData() + { + if(u_value) + delete[] u_value; + } }; std::map values; From 020e4e7f13e37e14eed93a026392aa4c741fecbd Mon Sep 17 00:00:00 2001 From: Xele02 Date: Tue, 25 Dec 2012 13:30:10 +0100 Subject: [PATCH 237/276] Add code for sdk version info Modify Encrypt file data --- Core/Dialog/SavedataParam.cpp | 22 ++-- Core/HLE/sceKernelMemory.cpp | 190 +++++++++++++++++++++++++++++----- Core/HLE/sceKernelMemory.h | 1 + 3 files changed, 180 insertions(+), 33 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index ec8ee4cc7a..1c479f89b1 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -68,6 +68,13 @@ namespace return result != 0; } + + struct EncryptFileInfo + { + int fileVersion; + u8 key[16]; + int sdkVersion; + }; } SavedataParam::SavedataParam() @@ -237,17 +244,20 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) // Save Encryption Data { - int dataSize = 16+16; // key + save filename - data_ = new u8[dataSize]; - memset(data_,0,dataSize); - sprintf((char*)data_,GetFileName(param).c_str(),GetFileName(param).size()); + EncryptFileInfo encryptInfo; + int dataSize = sizeof(encryptInfo); // version + key + sdkVersion + memset(&encryptInfo,0,dataSize); + + encryptInfo.fileVersion = 1; + encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion(); if(param->size > 1500) - memcpy(data_+16,param->key,16); + memcpy(encryptInfo.key,param->key,16); + std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; handle = pspFileSystem.OpenFile(encryptInfoPath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); if (handle) { - pspFileSystem.WriteFile(handle, data_, dataSize); + pspFileSystem.WriteFile(handle, (u8*)&encryptInfo, dataSize); pspFileSystem.CloseFile(handle); } } diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 5513850417..0edcc83a0e 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -32,6 +32,12 @@ BlockAllocator kernelMemory(256); // STATE END ////////////////////////////////////////////////////////////////////////// +#define SCE_KERNEL_HASCOMPILEDSDKVERSION 0x1000 +#define SCE_KERNEL_HASCOMPILERVERSION 0x2000 + +int flags_ = 0; +int sdkVersion_; +int compilerVersion_; struct NativeFPL { @@ -439,6 +445,154 @@ void sceKernelPrintf() RETURN(0); } +void sceKernelSetCompiledSdkVersion(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + bool valiSDK = false; + switch(sdkMainVersion) + { + case 0x1000000: + case 0x1050000: + case 0x2000000: + case 0x2050000: + case 0x2060000: + case 0x2070000: + case 0x2080000: + case 0x3000000: + case 0x3010000: + case 0x3030000: + case 0x3040000: + case 0x3050000: + case 0x3060000: + valiSDK = true; + break; + default: + valiSDK = false; + break; + } + + if(valiSDK) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion370(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + if(sdkMainVersion == 0x3070000) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion370 unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion380_390(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + if(sdkMainVersion == 0x3080000 || sdkMainVersion == 0x3090000) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion380_390 unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion395(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFFFF00; + if(sdkMainVersion == 0x4000000 + || sdkMainVersion == 0x4000100 + || sdkMainVersion == 0x4000500 + || sdkMainVersion == 0x3090500 + || sdkMainVersion == 0x3090600) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion600_602(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + if(sdkMainVersion == 0x6010000 + || sdkMainVersion == 0x6000000 + || sdkMainVersion == 0x6020000) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion603_605(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + if(sdkMainVersion == 0x6040000 + || sdkMainVersion == 0x6030000 + || sdkMainVersion == 0x6050000) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + } + return; +} + +void sceKernelSetCompiledSdkVersion606(int sdkVersion) +{ + int sdkMainVersion = sdkVersion & 0xFFFF0000; + if(sdkMainVersion == 0x6060000) + { + sdkVersion_ = sdkVersion; + flags_ |= SCE_KERNEL_HASCOMPILEDSDKVERSION; + } + else + { + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + } + return; +} + +int sceKernelGetCompiledSdkVersion() +{ + if(!(flags_ & SCE_KERNEL_HASCOMPILEDSDKVERSION)) + return 0; + return sdkVersion_; +} + +void sceKernelSetCompilerVersion(int version) +{ + compilerVersion_ = version; + flags_ |= SCE_KERNEL_HASCOMPILERVERSION; +} // VPL = variable length memory pool @@ -657,23 +811,6 @@ u32 GetMemoryBlockPtr(u32 uid, u32 addr) { return 0; } -u32 sceKernelSetCompiledSdkVersion(u32 param) { - // pretty sure this only takes one arg - ERROR_LOG(HLE,"UNIMPL sceKernelSetCompiledSdkVersion(%08x)", param); - return 0; -} - -u32 sceKernelSetCompiledSdkVersion395(u32 param) { - // pretty sure this only takes one arg - ERROR_LOG(HLE,"UNIMPL sceKernelSetCompiledSdkVersion395(%08x)", param); - return 0; -} - -u32 sceKernelSetCompilerVersion(u32 a, u32 b, u32 c, u32 d) { - ERROR_LOG(HLE,"UNIMPL sceKernelSetCompilerVersion(%08x, %08x, %08x, %08x)", a, b, c, d); - return 0; -} - const HLEFunction SysMemUserForUser[] = { {0xA291F107,sceKernelMaxFreeMemSize, "sceKernelMaxFreeMemSize"}, {0xF919F628,sceKernelTotalFreeMemSize,"sceKernelTotalFreeMemSize"}, @@ -682,16 +819,15 @@ const HLEFunction SysMemUserForUser[] = { {0xB6D61D02,sceKernelFreePartitionMemory,"sceKernelFreePartitionMemory"}, //(void *ptr) ? {0x9D9A5BA1,sceKernelGetBlockHeadAddr,"sceKernelGetBlockHeadAddr"}, //(void *ptr) ? {0x13a5abef,sceKernelPrintf,"sceKernelPrintf 0x13a5abef"}, - {0xf77d77cb,WrapU_UUUU,"sceKernelSetCompilerVersion"}, - {0x7591c7db,WrapU_U,"sceKernelSetCompiledSdkVersion"}, - {0x342061E5,0,"sceKernelSetCompiledSdkVersion370"}, - {0x315AD3A0,0,"sceKernelSetCompiledSdkVersion380_390"}, - {0xEBD5C3E6,WrapU_U,"sceKernelSetCompiledSdkVersion395"}, - {0x91DE343C,0,"sceKernelSetCompiledSdkVersion_500_505"}, - {0x35669d4c,0,"sceKernelSetCompiledSdkVersion600_602"}, //?? - {0x1b4217bc,0,"sceKernelSetCompiledSdkVersion603_605"}, - {0x358ca1bb,0,"sceKernelSetCompiledSdkVersion606"}, - + {0x7591c7db,&WrapV_I,"sceKernelSetCompiledSdkVersion"}, + {0x342061E5,&WrapV_I,"sceKernelSetCompiledSdkVersion370"}, + {0x315AD3A0,&WrapV_I,"sceKernelSetCompiledSdkVersion380_390"}, + {0xEBD5C3E6,&WrapV_I,"sceKernelSetCompiledSdkVersion395"}, + {0xf77d77cb,&WrapV_I,"sceKernelSetCompilerVersion"}, + {0x35669d4c,&WrapV_I,"sceKernelSetCompiledSdkVersion600_602"}, //?? + {0x1b4217bc,&WrapV_I,"sceKernelSetCompiledSdkVersion603_605"}, + {0x358ca1bb,&WrapV_I,"sceKernelSetCompiledSdkVersion606"}, + {0xfc114573,&WrapI_V,"sceKernelGetCompiledSdkVersion"}, // Obscure raw block API {0xDB83A952,WrapU_UU,"SysMemUserForUser_DB83A952"}, // GetMemoryBlockAddr {0x50F61D8A,WrapU_U,"SysMemUserForUser_50F61D8A"}, // FreeMemoryBlock diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index 247f683d7f..eaf2e23f4c 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -49,5 +49,6 @@ void sceKernelFreeFpl(); void sceKernelCancelFpl(); void sceKernelReferFplStatus(); +int sceKernelGetCompiledSdkVersion(); void Register_SysMemUserForUser(); From f965fb76238654bd9d7bff2d6287b955e6560716 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Tue, 25 Dec 2012 18:20:37 +0100 Subject: [PATCH 238/276] * Add PSP Homebrew for encode/decode save between PSP and PPSSPP. --- Tools/SaveTool/Makefile | 44 ++ Tools/SaveTool/README | 77 ++++ Tools/SaveTool/decrypt.c | 164 +++++++ Tools/SaveTool/decrypt.h | 31 ++ Tools/SaveTool/encrypt.c | 233 ++++++++++ Tools/SaveTool/encrypt.h | 38 ++ Tools/SaveTool/hash.c | 129 ++++++ Tools/SaveTool/hash.h | 34 ++ Tools/SaveTool/kernelcall.prx | Bin 0 -> 2642 bytes Tools/SaveTool/kernelcall/Makefile | 24 + Tools/SaveTool/kernelcall/kernelcall.c | 84 ++++ Tools/SaveTool/kernelcall/kernelcall.h | 9 + Tools/SaveTool/main.c | 579 +++++++++++++++++++++++++ Tools/SaveTool/psf.c | 114 +++++ Tools/SaveTool/psf.h | 29 ++ 15 files changed, 1589 insertions(+) create mode 100644 Tools/SaveTool/Makefile create mode 100644 Tools/SaveTool/README create mode 100644 Tools/SaveTool/decrypt.c create mode 100644 Tools/SaveTool/decrypt.h create mode 100644 Tools/SaveTool/encrypt.c create mode 100644 Tools/SaveTool/encrypt.h create mode 100644 Tools/SaveTool/hash.c create mode 100644 Tools/SaveTool/hash.h create mode 100644 Tools/SaveTool/kernelcall.prx create mode 100644 Tools/SaveTool/kernelcall/Makefile create mode 100644 Tools/SaveTool/kernelcall/kernelcall.c create mode 100644 Tools/SaveTool/kernelcall/kernelcall.h create mode 100644 Tools/SaveTool/main.c create mode 100644 Tools/SaveTool/psf.c create mode 100644 Tools/SaveTool/psf.h diff --git a/Tools/SaveTool/Makefile b/Tools/SaveTool/Makefile new file mode 100644 index 0000000000..fc7a38f73c --- /dev/null +++ b/Tools/SaveTool/Makefile @@ -0,0 +1,44 @@ +SUBDIRS = kernelcall +release: + @for i in $(SUBDIRS); do echo "make all in $$i..."; (cd $$i; $(MAKE) release; cp $$i.prx ..); done + make all + +allclean: + make clean + @for i in $(SUBDIRS); do echo "Clearing in $$i..."; (cd $$i; $(MAKE) clean; rm -rf $$i.prx); done + +TARGET = ppssppsavetool +OBJS = main.o decrypt.o encrypt.o hash.o psf.o $(KERNELCALL_OBJS) + +BUILD_PRX=1 + + +EXTRA_TARGETS = EBOOT.PBP +PSP_EBOOT_TITLE = PPSSPP Save Tool + +PSP_FW_VERSION=350 + +INCDIR = +CFLAGS = -O0 -G0 -Wall -g +CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti +ASFLAGS = $(CFLAGS) + +KERNELCALL_OBJS = kernelcall_0000.o \ + kernelcall_0001.o \ + kernelcall_0002.o \ + kernelcall_0003.o \ + kernelcall_0004.o \ + kernelcall_0005.o \ + kernelcall_0006.o \ + kernelcall_0007.o + +$(KERNELCALL_OBJS): kernelcall/kernelcall.S + psp-gcc $(CFLAGS) -DF_$* $< -c -o $@ + +LIBDIR = +LDFLAGS = + +LIBS = -lpsputility -lpspgum -lpspgu -lm + +PSPSDK=$(shell psp-config --pspsdk-path) +include $(PSPSDK)/lib/build.mak diff --git a/Tools/SaveTool/README b/Tools/SaveTool/README new file mode 100644 index 0000000000..0581e316b8 --- /dev/null +++ b/Tools/SaveTool/README @@ -0,0 +1,77 @@ + +PSP Tool for encoding save data from PPSSPP to read on PSP and decoding +PSP save to read on PPSSPP. + +Alpha version. Was only tested on Project Dive Extend. + + +Build +===== + +Require PSP Toolchain with PSP SDK + + +make release +This will build ppssppsavetool.prx and kernelcall.prx. + +clean : make allclean + + +How to use +========== + +Require PSP Toolchain with PRX Link and usb link, pspsh to work. Seems +there is limitation for directories listing when running directly the +tool from the PSP. + +A) PREPARING DATA +================= + +1) Play the game on PPSSPP until a game save is done. This will create +the file "ENCRYPT_INFO.BIN" in the save directory. It contain the +encoding key and sdk version of the game. This file is the same for all +save of the game, so you can use it on different save folder without +the need to make them all on PPSSPP. + +2) Run usbhostfs_pc. Then mount .ppsspp/PSP/SAVEDATA directory : +mount 1 +If you enter "drives", you should see host1: mapped to the directory. + +3) Run PRX Link on the psp, and pspsh on the PC. + +B) ENCODING A SAVE FROM PPSSPP TO PSP +===================================== + +1) From pspsh, run ppssppsavetool.prx. + +2) In the menu, select "Encrypt", "host1:/". This will list the +directories in ppsspp save directory which can be encoded. +For a directory to appear, it must contain the ENCRYPT_INFO.BIN file, +and the files of a ppsspp save. + +3) After selecting the directory to encode, it will be copied into +the PSP/SAVEGAME directory and encoded. Now you can play the save on +the PSP. + +C) DECODING A SAVE FROM PSP TO PPSSPP +===================================== + +1) You should have a directory in the PPSSPP save directory with the +same name that the PSP save you want to convert. And in it, the +"ENCRYPT_INFO.BIN" file. + +Ex : You want to decrypt the save in ms0:/PSP/SAVEDATA/XXXXYYY/ +You create .ppsspp/PSP/SAVEDATA/XXXXYYY/ if not existing, and put the +"ENCRYPT_INFO.BIN" generated before in it. + +2) From pspsh, run ppssppsavetool.prx. + +3) In the menu, select "decrypt", "host1:/". You should see your +directory in the list. + +4) After selecting it, the game decode the save and save it into the +PPSSPP save directory. You can now launch your game in PPSSPP and load +the save. + + + diff --git a/Tools/SaveTool/decrypt.c b/Tools/SaveTool/decrypt.c new file mode 100644 index 0000000000..146572199d --- /dev/null +++ b/Tools/SaveTool/decrypt.c @@ -0,0 +1,164 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * decrypt.c - Decryption routines using sceChnnlsv + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: decrypt.c 1562 2005-12-10 20:52:45Z jim $ + */ + +#include "decrypt.h" +#include +#include +#include +#include +#include +#include "kernelcall/kernelcall.h" + +unsigned int align16(unsigned int v) +{ + return ((v + 0xF) >> 4) << 4; +} + +/* Read, decrypt, and write a savedata file. See main.c for example usage. */ +int decrypt_file(const char *decrypted_filename, + const char *encrypted_filename, + const unsigned char *gamekey, + const int mainSdkVersion) +{ + FILE *in, *out; + int len, aligned_len; + unsigned char *data, *cryptkey; + int retval; + + /* Open file and get size */ + + if ((in = fopen(encrypted_filename, "r")) == NULL) { + retval = -1; + goto out; + } + + fseek(in, 0, SEEK_END); + len = ftell(in); + fseek(in, 0, SEEK_SET); + + if (len <= 0) { + retval = -2; + goto out1; + } + + /* Allocate buffers */ + + aligned_len = align16(len); + + if ((data = (unsigned char *) memalign(0x10, aligned_len)) == NULL) { + retval = -3; + goto out1; + } + + if ((cryptkey = (unsigned char *) memalign(0x10, 0x10)) == NULL) { + retval = -4; + goto out2; + } + + /* Fill buffers */ + + if (gamekey != NULL) + memcpy(cryptkey, gamekey, 0x10); + + memset(data + len, 0, aligned_len - len); + if (fread(data, 1, len, in) != len) { + retval = -5; + goto out3; + } + + /* Do the decryption */ + + if ((retval = decrypt_data( gamekey ? (mainSdkVersion >= 4 ? 5 : 3) : 1, // 5 for sdk >= 4, else 3 + data, &len, &aligned_len, + gamekey ? cryptkey : NULL)) < 0) { + retval -= 100; + goto out3; + } + + /* Write the data out. decrypt_data has set len correctly. */ + + if ((out = fopen(decrypted_filename, "w")) == NULL) { + retval = -6; + goto out3; + } + + if (fwrite(data, 1, len, out) != len) { + retval = -7; + goto out4; + } + + /* All done. Return file length. */ + retval = len; + out4: + fclose(out); + out3: + free(cryptkey); + out2: + free(data); + out1: + fclose(in); + out: + return retval; +} + +/* Do the actual hardware decryption. + mode is 3 for saves with a cryptkey, or 1 otherwise + data, dataLen, and cryptkey must be multiples of 0x10. + cryptkey is NULL if mode == 1. +*/ +int decrypt_data(unsigned int mode, + unsigned char *data, + int *dataLen, + int *alignedLen, + unsigned char *cryptkey) +{ + pspChnnlsvContext1 ctx1; + pspChnnlsvContext2 ctx2; + + /* Need a 16-byte IV plus some data */ + if (*alignedLen <= 0x10) + return -1; + *dataLen -= 0x10; + *alignedLen -= 0x10; + + /* Set up buffers */ + memset(&ctx1, 0, sizeof(pspChnnlsvContext1)); + memset(&ctx2, 0, sizeof(pspChnnlsvContext2)); + + /* Perform the magic */ + if (sceChnnlsv_E7833020_(&ctx1, mode) < 0) + return -2; + if (sceChnnlsv_ABFDFC8B_(&ctx2, mode, 2, data, cryptkey) < 0) + return -3; + if (sceChnnlsv_F21A1FCA_(&ctx1, data, 0x10) < 0) + return -4; + if (sceChnnlsv_F21A1FCA_(&ctx1, data + 0x10, *alignedLen) < 0) + return -5; + if (sceChnnlsv_850A7FA1_(&ctx2, data + 0x10, *alignedLen) < 0) + return -6; + + /* Verify that it decrypted correctly */ + if (sceChnnlsv_21BE78B4_(&ctx2) < 0) + return -7; + + /* If desired, a new file hash from this PSP can be computed now: + if (sceChnnlsv_C4C494F8(ctx1, newhash, cryptkey) < 0) + return -8; + */ + + /* The decrypted data starts at data + 0x10, so shift it back. */ + memmove(data, data + 0x10, *dataLen); + + /* All done */ + return 0; +} diff --git a/Tools/SaveTool/decrypt.h b/Tools/SaveTool/decrypt.h new file mode 100644 index 0000000000..57b8881d6c --- /dev/null +++ b/Tools/SaveTool/decrypt.h @@ -0,0 +1,31 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * decrypt.h - Declarations for functions in decrypt.c + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: decrypt.h 1562 2005-12-10 20:52:45Z jim $ + */ + +#include + +/* Detect the samegame format and decrypt it. See main.c for an example. */ +int decrypt_file(const char *decrypted_filename, + const char *encrypted_filename, + const unsigned char *gamekey, + const int mainSdkVersion); + +/* Do the actual hardware decryption. + mode is 3 for saves with a cryptkey, or 1 otherwise. + data, alignedLen, and cryptkey must be multiples of 0x10. + cryptkey is NULL if mode == 1. +*/ +int decrypt_data(unsigned int mode, + unsigned char *data, + int *dataLen, + int *alignedLen, + unsigned char *cryptkey); diff --git a/Tools/SaveTool/encrypt.c b/Tools/SaveTool/encrypt.c new file mode 100644 index 0000000000..8da226e153 --- /dev/null +++ b/Tools/SaveTool/encrypt.c @@ -0,0 +1,233 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * encrypt.c - Encryption routines using sceChnnlsv + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: encrypt.c 1560 2005-12-10 01:16:32Z jim $ + */ + +#include "encrypt.h" +#include "hash.h" +#include +#include +#include +#include +#include +#include "kernelcall/kernelcall.h" + +static inline int align16(unsigned int v) +{ + return ((v + 0xF) >> 4) << 4; +} + +int fopen_getsize(const char *filename, FILE **fd, int *size) +{ + if ((*fd = fopen(filename, "r")) == NULL) + return -1; + + fseek(*fd, 0, SEEK_END); + *size = ftell(*fd); + fseek(*fd, 0, SEEK_SET); + + if (*size <= 0) { + fclose(*fd); + return -2; + } + + return 0; +} + +/* Encrypt the given plaintext file, and update the message + authentication hashes in the param.sfo. The data_filename is + usually the final component of encrypted_filename, e.g. "DATA.BIN". + See main.c for an example of usage. */ +int encrypt_file(const char *plaintext_filename, + const char *encrypted_filename, + const char *data_filename, + const char *paramsfo_filename, + const char *paramsfo_filename_out, + const unsigned char *gamekey, + const int mainSdkVersion) +{ + FILE *in = NULL, *out = NULL, *sfo = NULL; + unsigned char *data = NULL, *cryptkey = NULL, *hash = NULL; + unsigned char paramsfo[0x1330]; + int len, aligned_len, tmp; + int retval; + + /* Open plaintext and param.sfo files and get size */ + + if (fopen_getsize(plaintext_filename, &in, &len) < 0) { + retval = -1; + goto out; + } + + if (fopen_getsize(paramsfo_filename, &sfo, &tmp) < 0) { + retval = -2; + goto out; + } + + /* Verify size of param.sfo; all known saves use this size */ + + if (tmp != 0x1330) { + retval = -3; + goto out; + } + + /* Allocate buffers. data has 0x10 bytes extra for the IV. */ + + aligned_len = align16(len); + + if ((data = + (unsigned char *) memalign(0x10, aligned_len + 0x10)) == NULL) { + retval = -4; + goto out; + } + + if ((cryptkey = (unsigned char *) memalign(0x10, 0x10)) == NULL) { + retval = -5; + goto out; + } + + if ((hash = (unsigned char *) memalign(0x10, 0x10)) == NULL) { + retval = -6; + goto out; + } + + /* Fill buffers. */ + + memset(data + len, 0, aligned_len - len); + if (fread(data, 1, len, in) != len) { + retval = -7; + goto out; + } + + if (fread(paramsfo, 1, 0x1330, sfo) != 0x1330) { + retval = -8; + goto out; + } + + if (gamekey != NULL) + memcpy(cryptkey, gamekey, 0x10); + + /* Do the encryption */ + + if ((retval = encrypt_data( gamekey ? (mainSdkVersion >= 4 ? 5 : 3) : 1, // 5 for sdk >= 4, 3 otherwise + data, + &len, &aligned_len, + hash, + gamekey ? cryptkey : NULL)) < 0) { + retval -= 1000; + goto out; + } + + /* Update the param.sfo hashes */ + + if ((retval = update_hashes(paramsfo, 0x1330, + data_filename, hash, + gamekey ? 3 : 1)) < 0) { + retval -= 2000; + goto out; + } + + /* Write the data to the file. encrypt_data has already set len. */ + + if ((out = fopen(encrypted_filename, "w")) == NULL) { + retval = -9; + goto out; + } + + if (fwrite(data, 1, len, out) != len) { + retval = -10; + goto out; + } + + /* Reopen param.sfo, and write the updated copy out. */ + + fclose(sfo); + if ((sfo = fopen(paramsfo_filename_out, "w")) == NULL) { + retval = -11; + goto out; + } + + if (fwrite(paramsfo, 1, 0x1330, sfo) != 0x1330) { + retval = -12; + goto out; + } + + /* All done. Return file length. */ + + retval = len; + + out: + if(out) fclose(out); + if(hash) free(hash); + if(cryptkey) free(cryptkey); + if(data) free(data); + if(sfo) fclose(sfo); + if(in) fclose(in); + + return retval; +} + +/* Do the actual hardware encryption. + mode is 3 for saves with a cryptkey, or 1 otherwise + data, dataLen, and cryptkey must be multiples of 0x10. + cryptkey is NULL if mode == 1. +*/ +int encrypt_data(unsigned int mode, + unsigned char *data, + int *dataLen, + int *alignedLen, + unsigned char *hash, + unsigned char *cryptkey) +{ + pspChnnlsvContext1 ctx1; + pspChnnlsvContext2 ctx2; + + /* Make room for the IV in front of the data. */ + memmove(data + 0x10, data, *alignedLen); + + /* Set up buffers */ + memset(&ctx1, 0, sizeof(pspChnnlsvContext1)); + memset(&ctx2, 0, sizeof(pspChnnlsvContext2)); + memset(hash, 0, 0x10); + memset(data, 0, 0x10); + + /* Build the 0x10-byte IV and setup encryption */ + if (sceChnnlsv_ABFDFC8B_(&ctx2, mode, 1, data, cryptkey) < 0) + return -1; + if (sceChnnlsv_E7833020_(&ctx1, mode) < 0) + return -2; + if (sceChnnlsv_F21A1FCA_(&ctx1, data, 0x10) < 0) + return -3; + if (sceChnnlsv_850A7FA1_(&ctx2, data + 0x10, *alignedLen) < 0) + return -4; + + /* Clear any extra bytes left from the previous steps */ + memset(data + 0x10 + *dataLen, 0, *alignedLen - *dataLen); + + /* Encrypt the data */ + if (sceChnnlsv_F21A1FCA_(&ctx1, data + 0x10, *alignedLen) < 0) + return -5; + + /* Verify encryption */ + if (sceChnnlsv_21BE78B4_(&ctx2) < 0) + return -6; + + /* Build the file hash from this PSP */ + if (sceChnnlsv_C4C494F8_(&ctx1, hash, cryptkey) < 0) + return -7; + + /* Adjust sizes to account for IV */ + *alignedLen += 0x10; + *dataLen += 0x10; + + /* All done */ + return 0; +} diff --git a/Tools/SaveTool/encrypt.h b/Tools/SaveTool/encrypt.h new file mode 100644 index 0000000000..2b06da21e7 --- /dev/null +++ b/Tools/SaveTool/encrypt.h @@ -0,0 +1,38 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * encrypt.h - Declarations for functions in encrypt.c + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: encrypt.h 1559 2005-12-10 01:10:11Z jim $ + */ + +#include + +/* Encrypt the given plaintext file, and update the message + authentication hashes in the param.sfo. The data_filename is + usually the final component of encrypted_filename, e.g. "DATA.BIN". + See main.c for an example of usage. */ +int encrypt_file(const char *plaintext_filename, + const char *encrypted_filename, + const char *data_filename, + const char *paramsfo_filename, + const char *paramsfo_filename_out, + const unsigned char *gamekey, + const int mainSdkVersion); + +/* Do the actual hardware encryption. + mode is 3 for saves with a cryptkey, or 1 otherwise. + data, alignedLen, cryptkey, and hash must be multiples of 0x10. + cryptkey is NULL if mode == 1. +*/ +int encrypt_data(unsigned int mode, + unsigned char *data, + int *dataLen, + int *alignedLen, + unsigned char *hash, + unsigned char *cryptkey); diff --git a/Tools/SaveTool/hash.c b/Tools/SaveTool/hash.c new file mode 100644 index 0000000000..0a83a4ca3a --- /dev/null +++ b/Tools/SaveTool/hash.c @@ -0,0 +1,129 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * hash.c - Hashing routines using sceChnnlsv + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: hash.c 1560 2005-12-10 01:16:32Z jim $ + */ + +#include "hash.h" +#include "psf.h" +#include +#include +#include +#include +#include +#include "kernelcall/kernelcall.h" + +static inline int align16(unsigned int v) +{ + return ((v + 0xF) >> 4) << 4; +} + +/* Update the hashes in the param.sfo data, using + the given file hash, and by computing the param.sfo hashes. + filehash must be a multiple of 16 bytes, and is reused to + store other hashes. The filename is e.g. "DATA.BIN". */ +int update_hashes(unsigned char *data, + int len, + const char *filename, + unsigned char *filehash, + int encryptmode) +{ + int alignedLen = align16(len); + unsigned char *datafile, *savedata_params; + int listLen, paramsLen; + int ret; + + /* Locate SAVEDATA_PARAM section in the param.sfo. */ + if ((ret = find_psf_section("SAVEDATA_PARAMS", data, 0x1330, + &savedata_params, ¶msLen)) < 0) { + return ret - 100; + } + + /* Locate the pointer for this DATA.BIN equivalent */ + if ((ret = find_psf_section("SAVEDATA_FILE_LIST", data, 0x1330, + &datafile, &listLen)) < 0) { + return ret - 200; + } + + if ((ret = find_psf_datafile(filename, datafile, + listLen, &datafile)) < 0) { + return ret - 300; + } + + /* Check minimum sizes based on where we want to write */ + if ((listLen < 0x20) || (paramsLen < 0x80)) { + return -1; + } + + /* Clear params and insert file hash */ + memset(savedata_params, 0, paramsLen); + memcpy(datafile + 0x0D, filehash, 0x10); + + /* Compute 11D0 hash over entire file */ + if ((ret = build_hash(filehash, data, len, alignedLen, + (encryptmode & 2) ? 4 : 2, NULL)) < 0) { // Not sure about "2" + return ret - 400; + } + + /* Copy 11D0 hash to param.sfo and set flag indicating it's there */ + memcpy(savedata_params + 0x20, filehash, 0x10); + *savedata_params |= 0x01; + + /* If new encryption mode, compute and insert the 1220 hash. */ + if (encryptmode & 2) { + + /* Enable the hash bit first */ + *savedata_params |= 0x20; + + if ((ret = build_hash(filehash, data, len, alignedLen, + 3, 0)) < 0) { + return ret - 500; + } + memcpy(savedata_params + 0x70, filehash, 0x10); + } + + /* Compute and insert the 11C0 hash. */ + if ((ret = build_hash(filehash, data, len, alignedLen, 1, 0)) < 0) { + return ret - 600; + } + memcpy(savedata_params + 0x10, filehash, 0x10); + + /* All done. */ + return 0; +} + +/* Build a single hash using the given data and mode. + data and alignedLen must be multiples of 0x10. + cryptkey is NULL for savedata. */ +int build_hash(unsigned char *output, + unsigned char *data, + unsigned int len, + unsigned int alignedLen, + int mode, + unsigned char *cryptkey) +{ + pspChnnlsvContext1 ctx1; + + /* Set up buffers */ + memset(&ctx1, 0, sizeof(pspChnnlsvContext1)); + memset(output, 0, 0x10); + memset(data + len, 0, alignedLen - len); + + /* Perform the magic */ + if (sceChnnlsv_E7833020_(&ctx1, mode & 0xFF) < 0) + return -1; + if (sceChnnlsv_F21A1FCA_(&ctx1, data, alignedLen) < 0) + return -2; + if (sceChnnlsv_C4C494F8_(&ctx1, output, cryptkey) < 0) + return -3; + + /* All done. */ + return 0; +} diff --git a/Tools/SaveTool/hash.h b/Tools/SaveTool/hash.h new file mode 100644 index 0000000000..978627a693 --- /dev/null +++ b/Tools/SaveTool/hash.h @@ -0,0 +1,34 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * hash.h - Declarations for functions in hash.c + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: hash.h 1559 2005-12-10 01:10:11Z jim $ + */ + +#include + +/* Update the hashes in the param.sfo data, using + the given file hash, and by computing the param.sfo hashes. + filehash must be a multiple of 16 bytes, and is reused to + store other hashes. The filename is e.g. "DATA.BIN". */ +int update_hashes(unsigned char *data, + int len, + const char *filename, + unsigned char *filehash, + int encryptmode); + +/* Build a single hash using the given data and mode. + data, and alignedLen must be multiples of 0x10. + cryptkey is NULL for savedata.*/ +int build_hash(unsigned char *output, + unsigned char *data, + unsigned int len, + unsigned int alignedLen, + int mode, + unsigned char *cryptkey); diff --git a/Tools/SaveTool/kernelcall.prx b/Tools/SaveTool/kernelcall.prx new file mode 100644 index 0000000000000000000000000000000000000000..350ee401704d44b8116a5fbff33e9dec504b5f18 GIT binary patch literal 2642 zcmb_dOGs2<6h5OjokHUF9ztjaie?dmiBSs|LoW(UrP>rlYI8H`Hp44Dm}5uSE=t^-%|B&DqiaaNf6bs8{Uy z7Mq)5GxKf^`HRhqH`m@w6J}E5nZ)pWbNuTJPvO~X^4t{%HfH_joJaJgQl9z9NQPV# z8&|-!{|1>WlF@Ltb==KfC~k6GqjCznYmae2{PU=cGFaE*)|s9U_c=g4Sex!m^!Q~u zl^iotNy9wcY?_|W|LdG1>H@z9>OhBmvCJF2S^cJV-`G=rzi8O2K7Xfv`Q+E@byuiq z*^B*&;QCW<^^M&tZmsF9W_}#n2Myt+)C~hAvEhyK(jOf^!31xybv^+Z+CL4lm>Hzx-}wEt9P#AU`uD z?xTZI4t0n+lplX0^@zdo%!7*-K~+A^(+k}MpAwaC6&%dtqg&v-f~q~{s`Wao6_5Xi z5onkRB8s;Gw&Uxs2hD_p!|!qCaetekDj)x+Q?t}<@bUNz)3fjn`glAaTqp`qqWWuv z!}0akk7lZbG#{w?>%?01$Fmm2hRVTowLatHJqHipEs8TiM18j|!*+ai^Qf!(;|~|- zgNtrMRb9Sc9jx#vVIIq4sN>rTqWK-X0a*xD`95H+@@3%6Lo1miqVj!)t$2K=r=jve zb(xAc35y@El19`m;Xo0!;N3l0e07aS5C7n~5}`Q> +#include +#include +#include +#include +#include +#include +#include +#include + + + +PSP_MODULE_INFO("kernelcall", 0x1006, 2, 0); + + +u64 sceSysreg_driver_4F46EEDE(); + + +u64 GetFuseId() +{ + u64 fuseId = sceSysreg_driver_4F46EEDE(); + return fuseId; +} + +int sceChnnlsv_E7833020_(pspChnnlsvContext1 *ctx, int mode) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_E7833020(ctx,mode); + + pspSdkSetK1(k1); + return res; +} + +int sceChnnlsv_F21A1FCA_(pspChnnlsvContext1 *ctx, unsigned char *data, int len) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_F21A1FCA(ctx,data,len); + pspSdkSetK1(k1); + return res; +} + +int sceChnnlsv_C4C494F8_(pspChnnlsvContext1 *ctx, + unsigned char *hash, unsigned char *cryptkey) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_C4C494F8(ctx,hash,cryptkey); + pspSdkSetK1(k1); + return res; +} + +int sceChnnlsv_ABFDFC8B_(pspChnnlsvContext2 *ctx, int mode1, int mode2, + unsigned char *hashkey, unsigned char *cipherkey) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_ABFDFC8B(ctx,mode1,mode2,hashkey,cipherkey); + pspSdkSetK1(k1); + return res; +} + +int sceChnnlsv_850A7FA1_(pspChnnlsvContext2 *ctx, unsigned char *data, int len) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_850A7FA1(ctx,data,len); + pspSdkSetK1(k1); + return res; +} + +int sceChnnlsv_21BE78B4_(pspChnnlsvContext2 *ctx) +{ + int k1 = pspSdkSetK1(0); + int res = sceChnnlsv_21BE78B4(ctx); + pspSdkSetK1(k1); + return res; +} + +int module_start(SceSize args, void *argp) +{ + return 0; +} + +int module_stop() +{ + return 0; +} diff --git a/Tools/SaveTool/kernelcall/kernelcall.h b/Tools/SaveTool/kernelcall/kernelcall.h new file mode 100644 index 0000000000..4baf4c2ed3 --- /dev/null +++ b/Tools/SaveTool/kernelcall/kernelcall.h @@ -0,0 +1,9 @@ +u64 GetFuseId(); +int sceChnnlsv_E7833020_(pspChnnlsvContext1 *ctx, int mode); +int sceChnnlsv_F21A1FCA_(pspChnnlsvContext1 *ctx, unsigned char *data, int len); +int sceChnnlsv_C4C494F8_(pspChnnlsvContext1 *ctx, + unsigned char *hash, unsigned char *cryptkey); +int sceChnnlsv_ABFDFC8B_(pspChnnlsvContext2 *ctx, int mode1, int mode2, + unsigned char *hashkey, unsigned char *cipherkey); +int sceChnnlsv_850A7FA1_(pspChnnlsvContext2 *ctx, unsigned char *data, int len); +int sceChnnlsv_21BE78B4_(pspChnnlsvContext2 *ctx); diff --git a/Tools/SaveTool/main.c b/Tools/SaveTool/main.c new file mode 100644 index 0000000000..54a2b34e96 --- /dev/null +++ b/Tools/SaveTool/main.c @@ -0,0 +1,579 @@ +#include +#include +#include +#include +#include +#include +#include +#include "kernelcall/kernelcall.h" +#include +#include +#include +#include "encrypt.h" +#include "decrypt.h" +#include "psf.h" + +#define printf pspDebugScreenPrintf + +/* Define the module info section */ +PSP_MODULE_INFO("ppssppsavetool", 0, 1, 0); +PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); +PSP_HEAP_SIZE_KB(-64); + +#define ENCRYPT_FILE_VERSION 1 + + +int currentMenu = 0; +int selectedOption = 0; +int basePath = 0; +int workDir = 0; + +char *menuList0[] = {"Encrypt","Decrypt", "Exit", NULL}; +char *menuList1[] = {"ms0:/PSP/SAVEDATAPPSSPP/","host0:/","host1:/", "host2:/", "Back", NULL}; +char *menuList2[] = {"Back", NULL}; + +int GetSDKMainVersion(int sdkVersion) +{ + if(sdkVersion > 0x307FFFF) + return 6; + if(sdkVersion > 0x300FFFF) + return 5; + if(sdkVersion > 0x206FFFF) + return 4; + if(sdkVersion > 0x205FFFF) + return 3; + if(sdkVersion >= 0x2000000) + return 2; + if(sdkVersion >= 0x1000000) + return 1; + return 0; +}; + +int ProcessInput(int maxOption, int *selectedOption) +{ + SceCtrlData pad, oldpad; + sceCtrlReadBufferPositive(&oldpad, 1); + while(1) + { + sceCtrlReadBufferPositive(&pad, 1); + + if (pad.Buttons != 0) + { + if (!(oldpad.Buttons & PSP_CTRL_CROSS) && pad.Buttons & PSP_CTRL_CROSS) + { + return *selectedOption; + } + else if (!(oldpad.Buttons & PSP_CTRL_UP) && pad.Buttons & PSP_CTRL_UP && *selectedOption > 0) + { + *selectedOption = *selectedOption-1; + return -1; + } + else if (!(oldpad.Buttons & PSP_CTRL_DOWN) && pad.Buttons & PSP_CTRL_DOWN && *selectedOption < maxOption-1) + { + *selectedOption = *selectedOption + 1; + return -1; + } + } + oldpad = pad; + } +} + +typedef struct +{ + char name[30]; + char saveFile[30]; + int errorId; +} DirInfo; + +typedef struct +{ + int fileVersion; + u8 key[16]; + int sdkVersion; +} EncryptFileInfo; + +DirInfo dirList[128]; +int numDirList; +DirInfo invalidDirList[128]; +int numInvalidDirList; + +int FileExist(char* basePath, char* dirPath, char* fileName) +{ + SceIoStat fileStat; + char path[1024]; + sprintf(path,"%s%s/%s",basePath, dirPath, fileName); + if(sceIoGetstat(path, &fileStat) < 0) // no file + return 0; + return 1; +} + +int FileRead(char* basePath, char* dirPath, char* fileName, u8* dataout, int size) +{ + char path[1024]; + sprintf(path,"%s%s/%s",basePath, dirPath, fileName); + SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777); + if(fileId < 0) + return -1; + sceIoRead(fileId, dataout, size); + sceIoClose(fileId); + return 0; +} + +void AddErrorDir(char* dirName, int error) +{ + if(numInvalidDirList >= 128) + return; + DirInfo *inf = &invalidDirList[numInvalidDirList]; + strcpy(inf->name,dirName); + inf->errorId = error; + numInvalidDirList++; +} + +int UpdateValidDir(int isEncrypt) +{ + numDirList = 0; + numInvalidDirList = 0; + + const char* pspPath = "ms0:/PSP/SAVEDATA/"; + + char* pathSrc; + char* pathDst; + if(isEncrypt) + { + pathSrc = menuList1[basePath]; + pathDst = pspPath; + } + else + { + pathSrc = pspPath; + pathDst = menuList1[basePath]; + } + + int dfd; + dfd = sceIoDopen(menuList1[basePath]); + if(dfd >= 0) + { + SceIoDirent data; + while(sceIoDread(dfd, &data) > 0 && numDirList < 128) + { + if(!(data.d_stat.st_attr & 0x10)) // is not a directory + { + continue; + } + + if(data.d_name[0] == '.') // ignore "." and ".." + continue; + + if(FileExist(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN") < 0) + { + AddErrorDir(data.d_name,1); + continue; + } + + EncryptFileInfo encryptInfo; + if(FileRead(menuList1[basePath], data.d_name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0) + { + AddErrorDir(data.d_name,2); + continue; + } + + if(encryptInfo.fileVersion != ENCRYPT_FILE_VERSION) // Not good version + { + AddErrorDir(data.d_name,3); + continue; + } + + if(FileExist(pathSrc, data.d_name, "PARAM.SFO") < 0) + { + AddErrorDir(data.d_name,4); + continue; + } + + u8 paramsfo[0x1330]; + if(FileRead(pathSrc, data.d_name, "PARAM.SFO",(u8*)¶msfo,0x1330) < 0) + { + AddErrorDir(data.d_name,5); + continue; + } + + u8 *datafile; + int listLen; + if (find_psf_section("SAVEDATA_FILE_LIST", paramsfo, 0x1330, + &datafile, &listLen) < 0) + { + AddErrorDir(data.d_name,6); + continue; + } + if(datafile[0] == 0) + { + AddErrorDir(data.d_name,7); + continue; + } + + char filename[32]; + strcpy(filename, (char*)datafile); + + if(FileExist(pathSrc, data.d_name, filename) < 0) + { + AddErrorDir(data.d_name,8); + continue; + } + + DirInfo *inf = &dirList[numDirList]; + inf->errorId = 0; + strcpy(inf->name, data.d_name); + strcpy(inf->saveFile, filename); + + numDirList++; + + } + sceIoDclose(dfd); + if(numDirList == 0) + { + return -1; + } + } + else + { + return -2; + } + return 0; +} + +int FileCopy(char* srcPath, char* destPath, char* fileName) +{ + SceIoStat fileStat; + char path[258]; + sprintf(path,"%s/%s",srcPath, fileName); + + if(sceIoGetstat(path, &fileStat) < 0) + return -1; + u8* data = malloc(fileStat.st_size); + + SceUID fileId = sceIoOpen(path, PSP_O_RDONLY, 0777); + if(fileId < 0) + { + printf("Fail opening %s\n",path); + return -1; + } + sceIoRead(fileId, data, fileStat.st_size); + sceIoClose(fileId); + + sprintf(path,"%s/%s",destPath, fileName); + + fileId = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT, 0777); + if(fileId < 0) + { + printf("Fail opening %s\n",path); + return -1; + } + sceIoWrite(fileId, data, fileStat.st_size); + sceIoClose(fileId); + + free(data); + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + pspDebugScreenInit(); + + SceUID mod = pspSdkLoadStartModule ("flash0:/kd/chnnlsv.prx",PSP_MEMORY_PARTITION_KERNEL); + if (mod < 0) { + printf("Error 0x%08X loading/starting chnnlsv.prx.\n", mod); + } + + mod = pspSdkLoadStartModule ("kernelcall.prx",PSP_MEMORY_PARTITION_KERNEL); + if (mod < 0) { + printf("Error 0x%08X loading/starting kernelcall.prx.\n", mod); + } + + sceCtrlSetSamplingCycle(0); + sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); + for(;;) + { + printf("===================================================================="); + printf("PPSSPP Save Tool\n"); + printf("====================================================================\n\n\n"); + + switch(currentMenu) + { + + case 0: + { + int maxOption = 0; + for(i = 0; menuList0[i]; i++) + { + if(i == selectedOption) + printf(" > %s\n",menuList0[i]); + else + printf(" %s\n",menuList0[i]); + maxOption++; + } + + int input = ProcessInput(maxOption, &selectedOption); + if(input == 0) + { + currentMenu = 1; + selectedOption = 0; + } + else if(input == 1) + { + currentMenu = 4; + selectedOption = 0; + } + else if(input == 2) + { + sceKernelExitGame(); + } + } + break; + case 4: + case 1: + { + int maxOption = 0; + printf("PPSSPP Decrypted Save Directory : \n"); + for(i = 0; menuList1[i]; i++) + { + if(i == selectedOption) + printf(" > %s\n",menuList1[i]); + else + printf(" %s\n",menuList1[i]); + maxOption++; + } + + int input = ProcessInput(maxOption, &selectedOption); + if(input == maxOption-1) + { + if(currentMenu == 1) + selectedOption = 0; + else + selectedOption = 1; + currentMenu = 0; + } + else if(input >= 0) + { + basePath = selectedOption; + if(currentMenu == 1) + { + currentMenu = 2; + UpdateValidDir(1); + } + else + { + currentMenu = 5; + UpdateValidDir(0); + } + selectedOption = 0; + } + } + break; + case 5: + case 2: + { + int maxOption = 0; + if(currentMenu == 2) + printf("Save to encrypt : \n"); + else + printf("Save to decrypt : \n"); + + if(numDirList == 0) + { + printf("No compatible data, see README for help on use\n"); + } + for(i = 0; i < numDirList; i++) + { + if(i == selectedOption) + printf(" > %s\n",dirList[i].name); + else + printf(" %s\n",dirList[i].name); + maxOption++; + } + + for(i = 0; menuList2[i]; i++) + { + if((i+numDirList) == selectedOption) + printf(" > %s\n",menuList2[i]); + else + printf(" %s\n",menuList2[i]); + maxOption++; + } + + printf("\n Invalid path : \n"); + for(i = 0; i < numInvalidDirList && i < (22-numDirList); i++) + { + switch(invalidDirList[i].errorId) + { + case 1: + printf(" %s : ENCRYPT_INFO.BIN not found\n",invalidDirList[i].name); + break; + case 2: + printf(" %s : ENCRYPT_INFO.BIN read error\n",invalidDirList[i].name); + break; + case 3: + printf(" %s : ENCRYPT_INFO.BIN wrong version\n",invalidDirList[i].name); + break; + case 4: + printf(" %s : PARAM.SFO not found\n",invalidDirList[i].name); + break; + case 5: + printf(" %s : PARAM.SFO read error\n",invalidDirList[i].name); + break; + case 6: + printf(" %s : SAVEDATA_FILE_LIST not found in PARAM.SFO\n",invalidDirList[i].name); + break; + case 7: + printf(" %s : no save name in SAVEDATA_FILE_LIST\n",invalidDirList[i].name); + break; + case 8: + printf(" %s : no save found\n",invalidDirList[i].name); + break; + default: + break; + } + } + + int input = ProcessInput(maxOption, &selectedOption); + if(input == numDirList) + { + if(currentMenu == 2) + currentMenu = 1; + else + currentMenu = 4; + selectedOption = basePath; + } + else if(input >= 0) + { + if(currentMenu == 2) + currentMenu = 3; + else + currentMenu = 6; + workDir = input; + selectedOption = 0; + } + } + break; + case 6: + case 3: + { + + EncryptFileInfo encryptInfo; + if(FileRead(menuList1[basePath], dirList[workDir].name, "ENCRYPT_INFO.BIN",(u8*)&encryptInfo,sizeof(encryptInfo)) < 0) + { + printf("Can't read encrypt file\n"); + } + else + { + printf("Key : "); + for(i = 0; i < 16; i++) + printf(" %02x",(u8)encryptInfo.key[i]); + printf("\n"); + printf("SDK Version : 0x%x\n",encryptInfo.sdkVersion); + + char srcPath[128]; + char dstPath[128]; + if(currentMenu == 3) + { + sprintf(srcPath,"%s%s",menuList1[basePath], dirList[workDir].name); + sprintf(dstPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name); + sceIoMkdir(dstPath,0777); + } + else + { + sprintf(srcPath,"ms0:/PSP/SAVEDATA/%s",dirList[workDir].name); + sprintf(dstPath,"%s%s",menuList1[basePath], dirList[workDir].name); + } + + int dfd; + dfd = sceIoDopen(srcPath); + if(dfd >= 0) + { + SceIoDirent dirinfo; + while(sceIoDread(dfd, &dirinfo) > 0) + { + + if(!(dirinfo.d_stat.st_mode & 0x2000)) // is not a file + continue; + + if(strcmp(dirinfo.d_name,"ENCRYPT_INFO.BIN") == 0) // don't copy encrypt info + continue; + + FileCopy(srcPath, dstPath, dirinfo.d_name); + + } + sceIoDclose(dfd); + } + + if(currentMenu == 3) + { + + char decryptedFile[258], encryptedFile[258], srcSFO[258], dstSFO[258]; + sprintf(decryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile); + sprintf(srcSFO,"%s/PARAM.SFO",srcPath); + + sprintf(encryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile); + sprintf(dstSFO,"%s/PARAM.SFO",dstPath); + + printf("Encoding %s into %s\n",decryptedFile, encryptedFile); + + int ret = encrypt_file(decryptedFile, + encryptedFile, + dirList[workDir].saveFile, + srcSFO, + dstSFO, + encryptInfo.key[0] != 0 ? encryptInfo.key : NULL, + GetSDKMainVersion(encryptInfo.sdkVersion) + ); + + if(ret < 0) { + printf("Error: encrypt_file() returned %d\n\n", ret); + } else { + printf("Successfully wrote %d bytes to\n", ret); + printf(" %s\n", encryptedFile); + printf("and updated hashes in\n"); + printf(" %s\n\n", dstSFO); + } + } + else + { + char decryptedFile[258], encryptedFile[258]; + sprintf(encryptedFile,"%s/%s",srcPath ,dirList[workDir].saveFile); + sprintf(decryptedFile,"%s/%s",dstPath ,dirList[workDir].saveFile); + + printf("Decoding %s into %s\n",encryptedFile, decryptedFile); + + int ret = decrypt_file(decryptedFile, encryptedFile, encryptInfo.key[0] != 0 ? encryptInfo.key : NULL, GetSDKMainVersion(encryptInfo.sdkVersion)); + + if(ret < 0) { + printf("Error: decrypt_file() returned %d\n\n", ret); + } else { + printf("Successfully wrote %d bytes to\n", ret); + printf(" %s\n", decryptedFile); + } + } + printf(" > Back\n"); + + int input = ProcessInput(1, &selectedOption); + if(input >= 0) + { + if(currentMenu == 3) + currentMenu = 2; + else + currentMenu = 5; + selectedOption = 0; + } + } + } + break; + default: + sceKernelExitGame(); + break; + } + + pspDebugScreenClear(); + sceDisplayWaitVblankStart(); + sceGuSwapBuffers(); + } + return 0; +} diff --git a/Tools/SaveTool/psf.c b/Tools/SaveTool/psf.c new file mode 100644 index 0000000000..5f68b1cc74 --- /dev/null +++ b/Tools/SaveTool/psf.c @@ -0,0 +1,114 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * psf.c - PSF parsing routines + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: psf.c 1560 2005-12-10 01:16:32Z jim $ + */ + +#include "psf.h" +#include +#include +#include +#include +#include + +/* Find to the named section in the PSF file, and return an + absolute pointer to it and the section size. */ +int find_psf_section(const char *name, + unsigned char *data, + int dataLen, + unsigned char **location, + int *size) +{ + unsigned short int nameLoc; + int i, magicHead, strLoc, headLen, numSects; + int sectCurLen, sectBufLen, sectBufLoc, curPos; + + if (dataLen < 0x14) + return -1; + + /* Get the basics from the header */ + magicHead = *(unsigned int *)&data[0x00]; + strLoc = *(unsigned int *)&data[0x08]; + headLen = *(unsigned int *)&data[0x0C]; + numSects = *(unsigned int *)&data[0x10]; + + /* Do some error checking */ + if (magicHead != 0x46535000) + return -2; + + /* Verify strLoc is proper */ + if ((strLoc > headLen) || (strLoc >= dataLen)) + return -3; + + /* Verify headLen is proper */ + if (headLen >= dataLen) + return -4; + + /* Verify numSects is proper */ + if (numSects != ((strLoc - 0x14) / 0x10)) + return -5; + + /* Process all sections */ + for (i = 0; i < numSects; i++) + { + /* Get the curPos */ + curPos = 0x14 + (i * 0x10); + + /* Verify curPos is proper */ + if (curPos >= strLoc) + return -6; + + /* Get some basic info about this section */ + nameLoc = *(unsigned short *)&data[curPos]; + sectCurLen = *(unsigned short *)&data[curPos + 0x04]; + sectBufLen = *(unsigned short *)&data[curPos + 0x08]; + sectBufLoc = *(unsigned short *)&data[curPos + 0x0C]; + + /* Do some error checking */ + if ((nameLoc < dataLen) && (sectCurLen < dataLen) + && (sectBufLen < dataLen) && (sectBufLoc < dataLen)) + { + /* Check if this is the section we want */ + if (!stricmp((char *)&data[strLoc + nameLoc], name)) + { + /* Update the location and size */ + *location = &data[headLen + sectBufLoc]; + *size = sectBufLen; + return 0; + } + } + } + + /* Section was not found if it makes it here */ + return -7; +} + +/* Find the named file inside the FILE_LIST, and return + an absolute pointer to it. */ +int find_psf_datafile(const char *name, + unsigned char *filelist, + int size, + unsigned char **location) +{ + int i; + + /* Process all files */ + for (i = 0; (i + 0x0d) <= size; i += 0x20) + { + /* Check if this is the filename we want */ + if (!strncasecmp((char *)&filelist[i], name, 0x0d)) { + *location = &filelist[i]; + return 0; + } + } + + /* File was not found if it makes it here */ + return -1; +} diff --git a/Tools/SaveTool/psf.h b/Tools/SaveTool/psf.h new file mode 100644 index 0000000000..261e241e84 --- /dev/null +++ b/Tools/SaveTool/psf.h @@ -0,0 +1,29 @@ +/* + * PSP Software Development Kit - http://www.pspdev.org + * ----------------------------------------------------------------------- + * Licensed under the BSD license, see LICENSE in PSPSDK root for details. + * + * psf.h - Declarations for functions in psf.c + * + * Copyright (c) 2005 Jim Paris + * Coypright (c) 2005 psp123 + * + * $Id: psf.h 1559 2005-12-10 01:10:11Z jim $ + */ + +#include + +/* Find the named section in the PSF file, and return an + absolute pointer to it and the section size. */ +int find_psf_section(const char *name, + unsigned char *data, + int dataLen, + unsigned char **location, + int *size); + +/* Find the named file inside the FILE_LIST, and return + an absolute pointer to it. */ +int find_psf_datafile(const char *name, + unsigned char *filelist, + int size, + unsigned char **location); From 05a3574315f1fd5fe3dbb2d805897a539b788e31 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Fri, 28 Dec 2012 12:00:43 +0100 Subject: [PATCH 239/276] Add missing break --- Core/Dialog/PSPSaveDialog.cpp | 2 +- Core/Dialog/SavedataParam.cpp | 7 +------ Core/HLE/sceKernelMemory.cpp | 6 +++--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 92a0a5e398..44d110f5ab 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -665,7 +665,7 @@ int PSPSaveDialog::Update() param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; } status = SCE_UTILITY_STATUS_FINISHED; - // TODO: intentional missing break? + break; case SCE_UTILITY_SAVEDATA_TYPE_LIST: param.GetList(param.GetPspParam()); param.GetPspParam()->result = 0; diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 1c479f89b1..6fd27dd0e9 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -254,12 +254,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) memcpy(encryptInfo.key,param->key,16); std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; - handle = pspFileSystem.OpenFile(encryptInfoPath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); - if (handle) - { - pspFileSystem.WriteFile(handle, (u8*)&encryptInfo, dataSize); - pspFileSystem.CloseFile(handle); - } + WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize); } } return true; diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 0edcc83a0e..0b5a3c49b7 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -544,7 +544,7 @@ void sceKernelSetCompiledSdkVersion600_602(int sdkVersion) } else { - ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion600_602 unknown SDK : %x\n",sdkVersion); } return; } @@ -561,7 +561,7 @@ void sceKernelSetCompiledSdkVersion603_605(int sdkVersion) } else { - ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion603_605 unknown SDK : %x\n",sdkVersion); } return; } @@ -576,7 +576,7 @@ void sceKernelSetCompiledSdkVersion606(int sdkVersion) } else { - ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion395 unknown SDK : %x\n",sdkVersion); + ERROR_LOG(HLE,"sceKernelSetCompiledSdkVersion606 unknown SDK : %x\n",sdkVersion); } return; } From d251bcfc96c51c8698ea8349f42827356d492ef9 Mon Sep 17 00:00:00 2001 From: artart78 Date: Fri, 28 Dec 2012 13:49:36 +0100 Subject: [PATCH 240/276] Fix buttons for the virtual gamepad --- android/jni/GamepadEmu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/jni/GamepadEmu.cpp b/android/jni/GamepadEmu.cpp index 49ce14a09c..84e45e565b 100644 --- a/android/jni/GamepadEmu.cpp +++ b/android/jni/GamepadEmu.cpp @@ -21,8 +21,8 @@ #include "ui_atlas.h" TouchButton buttonX(&ui_atlas, I_ROUND, I_CROSS, PAD_BUTTON_A); -TouchButton buttonO(&ui_atlas, I_ROUND, I_CIRCLE, PAD_BUTTON_X); -TouchButton buttonSq(&ui_atlas, I_ROUND, I_SQUARE, PAD_BUTTON_B); +TouchButton buttonO(&ui_atlas, I_ROUND, I_CIRCLE, PAD_BUTTON_B); +TouchButton buttonSq(&ui_atlas, I_ROUND, I_SQUARE, PAD_BUTTON_X); TouchButton buttonTri(&ui_atlas, I_ROUND, I_TRIANGLE, PAD_BUTTON_Y); TouchButton buttonSelect(&ui_atlas, I_RECT, I_SELECT, PAD_BUTTON_SELECT); TouchButton buttonStart(&ui_atlas, I_RECT, I_START, PAD_BUTTON_START); From 29bc06ae32d3b7760e821c67d4a58261e9da9fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 28 Dec 2012 16:52:01 +0100 Subject: [PATCH 241/276] Possible buildfix --- Core/FileSystems/DirectoryFileSystem.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 2de2ff9e2e..e3f4bf0acc 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -31,20 +31,20 @@ typedef void * HANDLE; #if defined(__APPLE__) #if TARGET_OS_IPHONE -#define HOST_IS_CASE_SENSITIVE true +#define HOST_IS_CASE_SENSITIVE 1 #elif TARGET_IPHONE_SIMULATOR -#define HOST_IS_CASE_SENSITIVE false +#define HOST_IS_CASE_SENSITIVE 0 #else // Mac OSX case sensitivity defaults off, but is user configurable (when // creating a filesytem), so assume the worst: -#define HOST_IS_CASE_SENSITIVE true +#define HOST_IS_CASE_SENSITIVE 1 #endif #elif defined(_WIN32) || defined(__SYMBIAN32__) -#define HOST_IS_CASE_SENSITIVE false +#define HOST_IS_CASE_SENSITIVE 0 #else // Android, Linux, BSD (and the rest?) -#define HOST_IS_CASE_SENSITIVE true +#define HOST_IS_CASE_SENSITIVE 1 #endif From e407ec4314d67c27fb7830fcf1e37f7dfd125b3a Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 28 Dec 2012 23:23:42 +0800 Subject: [PATCH 242/276] User define linear filtering --- Core/Config.cpp | 2 ++ Core/Config.h | 1 + GPU/GLES/TextureCache.cpp | 15 ++++++++++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 60529a4f67..e0ea8cff4e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -60,6 +60,7 @@ void CConfig::Load(const char *iniFileName) graphics->Get("WindowZoom", &iWindowZoom, 1); graphics->Get("BufferedRendering", &bBufferedRendering, true); graphics->Get("HardwareTransform", &bHardwareTransform, false); + graphics->Get("LinearFiltering", &bLinearFiltering, false); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Get("Enable", &bEnableSound, true); @@ -98,6 +99,7 @@ void CConfig::Save() graphics->Set("WindowZoom", iWindowZoom); graphics->Set("BufferedRendering", bBufferedRendering); graphics->Set("HardwareTransform", bHardwareTransform); + graphics->Set("LinearFiltering", bLinearFiltering); IniFile::Section *sound = iniFile.GetOrCreateSection("Sound"); sound->Set("Enable", bEnableSound); diff --git a/Core/Config.h b/Core/Config.h index ae9ea5191a..030d3ea8c1 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -52,6 +52,7 @@ public: bool bHardwareTransform; bool bBufferedRendering; bool bDrawWireframe; + bool bLinearFiltering; int iWindowZoom; // for Windows // Sound diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 1b867a46d4..3e13c466e3 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -21,7 +21,7 @@ #include "../ge_constants.h" #include "../GPUState.h" #include "TextureCache.h" - +#include "../Core/Config.h" // If a texture hasn't been seen for 200 frames, get rid of it. #define TEXTURE_KILL_AGE 200 @@ -428,8 +428,17 @@ void UpdateSamplingParams() int tClamp = (gstate.texwrap>>8) & 1; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilt ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilt ? GL_LINEAR : GL_NEAREST); + // Tested mag/minFilt only work in either one case that can allow GL_LINEAR to be enable + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilt ? GL_LINEAR : GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilt ? GL_LINEAR : GL_NEAREST); + // User define linear filtering + if ( g_Config.bLinearFiltering ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } } From e2cc226d0db3f0dc21c2160a96c31db41c66dbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 28 Dec 2012 19:33:26 +0100 Subject: [PATCH 243/276] Just some cleanup of GPU code --- GPU/GLES/DisplayListInterpreter.cpp | 343 +++++----------------------- GPU/GLES/TransformPipeline.cpp | 32 ++- GPU/GLES/TransformPipeline.h | 7 +- GPU/GLES/VertexDecoder.h | 2 +- GPU/GPUState.h | 14 +- GPU/GeDisasm.cpp | 39 ++-- GPU/Null/NullGpu.cpp | 3 - GPU/ge_constants.h | 2 +- 8 files changed, 108 insertions(+), 334 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index f68fee9a43..deb384a0ed 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -441,7 +441,6 @@ void GLES_GPU::Break() { } - static void EnterClearMode(u32 data) { bool colMask = (data >> 8) & 1; bool alphaMask = (data >> 9) & 1; @@ -467,8 +466,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { u32 data = op & 0xFFFFFF; // Handle control and drawing commands here directly. The others we delegate. - switch (cmd) - { + switch (cmd) { case GE_CMD_BASE: //DEBUG_LOG(G3D,"DL BASE: %06x", data & 0xFFFFFF); break; @@ -489,19 +487,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { u32 count = data & 0xFFFF; u32 type = data >> 16; - static const char* types[7] = { - "POINTS=0,", - "LINES=1,", - "LINE_STRIP=2,", - "TRIANGLES=3,", - "TRIANGLE_STRIP=4,", - "TRIANGLE_FAN=5,", - "RECTANGLES=6,", - }; - //DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) - { + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { ERROR_LOG(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); break; } @@ -509,20 +496,18 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // on platforms where draw calls are expensive like mobile and D3D void *verts = Memory::GetPointer(gstate_c.vertexAddr); void *inds = 0; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) - { - if (!Memory::IsValidAddress(gstate_c.indexAddr)) - { + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + if (!Memory::IsValidAddress(gstate_c.indexAddr)) { ERROR_LOG(G3D, "Bad index address %08x!", gstate_c.indexAddr); break; } inds = Memory::GetPointer(gstate_c.indexAddr); } - // Seems we have to advance the vertex addr, at least in some cases. + // Seems we have to advance the vertex addr, at least in some cases. // Question: Should we also advance the index addr? int bytesRead; - transformDraw_.SubmitPrim(verts, inds, type, count, 0, -1, &bytesRead); + transformDraw_.SubmitPrim(verts, inds, type, count, gstate.vertType, 0, -1, &bytesRead); gstate_c.vertexAddr += bytesRead; } break; @@ -533,7 +518,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int bz_ucount = data & 0xFF; int bz_vcount = (data >> 8) & 0xFF; transformDraw_.DrawBezier(bz_ucount, bz_vcount); - //DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); } break; @@ -543,20 +527,22 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int sp_vcount = (data >> 8) & 0xFF; int sp_utype = (data >> 16) & 0x3; int sp_vtype = (data >> 18) & 0x3; - //drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); - //DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); + transformDraw_.DrawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); } break; - case GE_CMD_JUMP: + case GE_CMD_JUMP: { u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; - //DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target); - dcontext.pc = target - 4; // pc will be increased after we return, counteract that + if (Memory::IsValidAddress(target)) { + dcontext.pc = target - 4; // pc will be increased after we return, counteract that + } else { + ERROR_LOG(G3D, "JUMP to illegal address %08x - ignoring??", target); + } } break; - case GE_CMD_CALL: + case GE_CMD_CALL: { u32 retval = dcontext.pc + 4; if (stackptr == ARRAY_SIZE(stack)) { @@ -564,39 +550,32 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { } else { stack[stackptr++] = retval; u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF; - //DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval); dcontext.pc = target - 4; // pc will be increased after we return, counteract that } } break; - case GE_CMD_RET: - //TODO : debug! + case GE_CMD_RET: { - u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF); - //DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target); + u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF); dcontext.pc = target - 4; } break; case GE_CMD_SIGNAL: { - //DEBUG_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); - // Processed in GE_END. + // Processed in GE_END. Has data. } break; case GE_CMD_FINISH: - //DEBUG_LOG(G3D,"DL CMD FINISH"); // TODO: Should this run while interrupts are suspended? if (interruptsEnabled_) __TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; - case GE_CMD_END: - //DEBUG_LOG(G3D,"DL CMD END"); - switch (prev >> 24) - { + case GE_CMD_END: + switch (prev >> 24) { case GE_CMD_SIGNAL: { // TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935# @@ -606,10 +585,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // We should probably defer to sceGe here, no sense in implementing this stuff in every GPU switch (behaviour) { case 1: // Signal with Wait - //DEBUG_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); + ERROR_LOG(G3D, "Signal with Wait UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); break; case 2: - //DEBUG_LOG(G3D, "Signal without wait. signal/end: %04x %04x", signal, enddata); + ERROR_LOG(G3D, "Signal without wait. signal/end: %04x %04x", signal, enddata); break; case 3: ERROR_LOG(G3D, "Signal with Pause UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata); @@ -636,19 +615,17 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { finished = true; break; default: - //DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); + DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); break; } break; case GE_CMD_BJUMP: // bounding box jump. Let's just not jump, for now. - //DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); break; case GE_CMD_BOUNDINGBOX: // bounding box test. Let's do nothing. - //DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); break; case GE_CMD_ORIGIN: @@ -656,7 +633,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_VERTEXTYPE: - //DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); if (diff & GE_VTYPE_THROUGH) { // Throughmode changed, let's make the proj matrix dirty. shaderManager_->DirtyUniform(DIRTY_PROJMATRIX); @@ -673,7 +649,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int x1 = data & 0x3ff; int y1 = data >> 10; //topleft - //DEBUG_LOG(G3D,"DL Region TL: %d %d", x1, y1); } break; @@ -681,107 +656,71 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { { int x2 = data & 0x3ff; int y2 = data >> 10; - //DEBUG_LOG(G3D,"DL Region BR: %d %d", x2, y2); } break; case GE_CMD_CLIPENABLE: - //DEBUG_LOG(G3D, "DL Clip Enable: %i (ignoring)", data); //we always clip, this is opengl break; - case GE_CMD_CULLFACEENABLE: - //DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); + case GE_CMD_CULLFACEENABLE: break; - case GE_CMD_TEXTUREMAPENABLE: + case GE_CMD_TEXTUREMAPENABLE: gstate_c.textureChanged = true; - //DEBUG_LOG(G3D, "DL Texture map enable: %i", data); break; case GE_CMD_LIGHTINGENABLE: - //DEBUG_LOG(G3D, "DL Lighting enable: %i", data); - data += 1; - //We don't use OpenGL lighting break; - case GE_CMD_FOGENABLE: - //DEBUG_LOG(G3D, "DL Fog Enable: %i", data); + case GE_CMD_FOGENABLE: break; case GE_CMD_DITHERENABLE: - //DEBUG_LOG(G3D, "DL Dither Enable: %i", data); break; - case GE_CMD_OFFSETX: - //DEBUG_LOG(G3D, "DL Offset X: %i", data); + case GE_CMD_OFFSETX: break; - case GE_CMD_OFFSETY: - //DEBUG_LOG(G3D, "DL Offset Y: %i", data); + case GE_CMD_OFFSETY: break; case GE_CMD_TEXSCALEU: gstate_c.uScale = getFloat24(data); - //DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate_c.uScale); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXSCALEV: gstate_c.vScale = getFloat24(data); - //DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate_c.vScale); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETU: gstate_c.uOff = getFloat24(data); - //DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate_c.uOff); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXOFFSETV: gstate_c.vOff = getFloat24(data); - //DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate_c.vOff); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_SCISSOR1: - { - int x1 = data & 0x3ff; - int y1 = data >> 10; - //DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); - } - break; case GE_CMD_SCISSOR2: - { - int x2 = data & 0x3ff; - int y2 = data >> 10; - //DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); - } break; case GE_CMD_MINZ: gstate_c.zMin = getFloat24(data) / 65535.f; - //DEBUG_LOG(G3D, "DL MinZ: %f", gstate_c.zMin); break; case GE_CMD_MAXZ: gstate_c.zMax = getFloat24(data) / 65535.f; - //DEBUG_LOG(G3D, "DL MaxZ: %f", gstate_c.zMax); break; case GE_CMD_FRAMEBUFPTR: - { - u32 ptr = op & 0xFFE000; - //DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); - } break; case GE_CMD_FRAMEBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - //DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); - } break; case GE_CMD_FRAMEBUFPIXFORMAT: @@ -796,7 +735,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: gstate_c.textureChanged = true; - //DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); break; case GE_CMD_TEXBUFWIDTH0: @@ -808,103 +746,41 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: gstate_c.textureChanged = true; - //DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); break; case GE_CMD_CLUTADDR: - gstate_c.textureChanged = true; - ////DEBUG_LOG(G3D,"CLUT base addr: %06x", data); gstate_c.textureChanged = true; break; case GE_CMD_CLUTADDRUPPER: gstate_c.textureChanged = true; - //DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); break; case GE_CMD_LOADCLUT: gstate_c.textureChanged = true; // This could be used to "dirty" textures with clut. - { - u32 clutAddr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); - if (clutAddr) - { - //DEBUG_LOG(G3D,"DL Clut load: %08x", clutAddr); - } - else - { - //DEBUG_LOG(G3D,"DL Empty Clut load"); - } - // Should hash and invalidate all paletted textures on use - } break; case GE_CMD_TEXMAPMODE: - //DEBUG_LOG(G3D,"Tex map mode: %06x", data); break; case GE_CMD_TEXSHADELS: - //DEBUG_LOG(G3D,"Tex shade light sources: %06x", data); break; case GE_CMD_CLUTFORMAT: - { - gstate_c.textureChanged = true; - //DEBUG_LOG(G3D,"DL Clut format: %06x", data); - } + gstate_c.textureChanged = true; break; case GE_CMD_TRANSFERSRC: - { - // Nothing to do, the next one prints - } - break; - case GE_CMD_TRANSFERSRCW: - { - u32 xferSrc = gstate.transfersrc | ((data&0xFF0000)<<8); - u32 xferSrcW = gstate.transfersrcw & 1023; - //DEBUG_LOG(G3D,"Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); - break; - } - case GE_CMD_TRANSFERDST: - { - // Nothing to do, the next one prints - } - break; - case GE_CMD_TRANSFERDSTW: - { - u32 xferDst= gstate.transferdst | ((data&0xFF0000)<<8); - u32 xferDstW = gstate.transferdstw & 1023; - //DEBUG_LOG(G3D,"Block Transfer Dest: %08x W: %i", xferDst, xferDstW); - break; - } - case GE_CMD_TRANSFERSRCPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - //DEBUG_LOG(G3D, "DL Block Transfer Src Rect TL: %i, %i", x, y); - break; - } - case GE_CMD_TRANSFERDSTPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - //DEBUG_LOG(G3D, "DL Block Transfer Dest Rect TL: %i, %i", x, y); - break; - } + break; case GE_CMD_TRANSFERSIZE: - { - u32 w = (data & 1023)+1; - u32 h = ((data>>10) & 1023)+1; - //DEBUG_LOG(G3D, "DL Block Transfer Rect Size: %i x %i", w, h); - break; - } + break; case GE_CMD_TRANSFERSTART: // Orphis calls this TRXKICK { @@ -925,64 +801,43 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXSIZE5: case GE_CMD_TEXSIZE6: case GE_CMD_TEXSIZE7: - //DEBUG_LOG(G3D,"DL Texture Size %i: %06x", cmd - GE_CMD_TEXSIZE0, data); gstate_c.textureChanged = true; break; case GE_CMD_ZBUFPTR: - { - u32 ptr = op & 0xFFE000; - //DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); - } - break; - case GE_CMD_ZBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - //DEBUG_LOG(G3D,"Zbuf Width: %i", w); - } break; case GE_CMD_AMBIENTCOLOR: - //DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); - break; - case GE_CMD_AMBIENTALPHA: - //DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); break; case GE_CMD_MATERIALAMBIENT: - //DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALDIFFUSE: - //DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATDIFFUSE); break; case GE_CMD_MATERIALEMISSIVE: - //DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATEMISSIVE); break; case GE_CMD_MATERIALSPECULAR: - //DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; case GE_CMD_MATERIALALPHA: - //DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_MATAMBIENTALPHA); break; case GE_CMD_MATERIALSPECULARCOEF: - //DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); if (diff) shaderManager_->DirtyUniform(DIRTY_MATSPECULAR); break; @@ -991,7 +846,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_LIGHTTYPE1: case GE_CMD_LIGHTTYPE2: case GE_CMD_LIGHTTYPE3: - //DEBUG_LOG(G3D,"DL Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); break; case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: @@ -1002,9 +856,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int n = cmd - GE_CMD_LX0; int l = n / 3; int c = n % 3; - float val = getFloat24(data); - //DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); - gstate_c.lightpos[l][c] = val; + gstate_c.lightpos[l][c] = getFloat24(data); if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } @@ -1018,9 +870,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int n = cmd - GE_CMD_LDX0; int l = n / 3; int c = n % 3; - float val = getFloat24(data); - //DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); - gstate_c.lightdir[l][c] = val; + gstate_c.lightdir[l][c] = getFloat24(data); if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } @@ -1034,9 +884,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int n = cmd - GE_CMD_LKA0; int l = n / 3; int c = n % 3; - float val = getFloat24(data); - //DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); - gstate_c.lightatt[l][c] = val; + gstate_c.lightatt[l][c] = getFloat24(data); if (diff) shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l); } @@ -1053,7 +901,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { int l = (cmd - GE_CMD_LAC0) / 3; int t = (cmd - GE_CMD_LAC0) % 3; - //DEBUG_LOG(G3D,"DL Light color %i", l); gstate_c.lightColor[t][l][0] = r; gstate_c.lightColor[t][l][1] = g; gstate_c.lightColor[t][l][2] = b; @@ -1066,41 +913,37 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_VIEWPORTY1: case GE_CMD_VIEWPORTX2: case GE_CMD_VIEWPORTY2: - //DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); break; + case GE_CMD_VIEWPORTZ1: gstate_c.zScale = getFloat24(data) / 65535.f; - //DEBUG_LOG(G3D,"DL Z scale: %f", gstate_c.zScale); break; + case GE_CMD_VIEWPORTZ2: gstate_c.zOff = getFloat24(data) / 65535.f; - //DEBUG_LOG(G3D,"DL Z pos: %f", gstate_c.zOff); break; + case GE_CMD_LIGHTENABLE0: case GE_CMD_LIGHTENABLE1: case GE_CMD_LIGHTENABLE2: case GE_CMD_LIGHTENABLE3: - //DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); break; + case GE_CMD_CULL: - //DEBUG_LOG(G3D,"DL cull: %06x", data); break; case GE_CMD_LMODE: - //DEBUG_LOG(G3D,"DL Shade mode: %06x", data); break; case GE_CMD_PATCHDIVISION: - gstate_c.patch_div_s = data & 0xFF; - gstate_c.patch_div_t = (data >> 8) & 0xFF; - //DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate_c.patch_div_s, gstate_c.patch_div_t); + case GE_CMD_PATCHPRIMITIVE: + case GE_CMD_PATCHFACING: break; + case GE_CMD_MATERIALUPDATE: - //DEBUG_LOG(G3D,"DL Material Update: %d", data); break; - ////////////////////////////////////////////////////////////////// // CLEARING ////////////////////////////////////////////////////////////////// @@ -1110,7 +953,6 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { EnterClearMode(data); else LeaveClearMode(); - //DEBUG_LOG(G3D,"DL Clear mode: %06x", data); break; @@ -1118,98 +960,39 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { // ALPHA BLENDING ////////////////////////////////////////////////////////////////// case GE_CMD_ALPHABLENDENABLE: - //DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); - break; - case GE_CMD_BLENDMODE: - //DEBUG_LOG(G3D,"DL Blend mode: %06x", data); - break; - case GE_CMD_BLENDFIXEDA: - //DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); - break; - case GE_CMD_BLENDFIXEDB: - //DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); break; case GE_CMD_ALPHATESTENABLE: - //DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); // This is done in the shader. break; case GE_CMD_ALPHATEST: - //DEBUG_LOG(G3D,"DL Alpha test settings"); shaderManager_->DirtyUniform(DIRTY_ALPHACOLORREF); break; - case GE_CMD_TEXFUNC: - { - //DEBUG_LOG(G3D,"DL TexFunc %i", data&7); - /* - int m=GL_MODULATE; - switch (data & 7) - { - case 0: m=GL_MODULATE; break; - case 1: m=GL_DECAL; break; - case 2: m=GL_BLEND; break; - case 3: m=GL_REPLACE; break; - case 4: m=GL_ADD; break; - }*/ - - /* - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);*/ - break; - } - case GE_CMD_TEXFILTER: - { - int min = data & 7; - int mag = (data >> 8) & 1; - //DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); - } - break; case GE_CMD_TEXENVCOLOR: - //DEBUG_LOG(G3D,"DL TexEnvColor %06x", data); if (diff) shaderManager_->DirtyUniform(DIRTY_TEXENV); break; + + case GE_CMD_TEXFUNC: + case GE_CMD_TEXFILTER: case GE_CMD_TEXMODE: - //DEBUG_LOG(G3D,"DL TexMode %08x", data); - break; case GE_CMD_TEXFORMAT: - //DEBUG_LOG(G3D,"DL TexFormat %08x", data); - break; case GE_CMD_TEXFLUSH: - //DEBUG_LOG(G3D,"DL TexFlush"); - break; case GE_CMD_TEXWRAP: - //DEBUG_LOG(G3D,"DL TexWrap %08x", data); break; + ////////////////////////////////////////////////////////////////// // Z/STENCIL TESTING ////////////////////////////////////////////////////////////////// - case GE_CMD_ZTESTENABLE: - //DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); - break; - case GE_CMD_STENCILTESTENABLE: - //DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); - break; - + case GE_CMD_ZTESTENABLE: case GE_CMD_ZTEST: - { - //DEBUG_LOG(G3D,"DL Z test mode: %i", data); - } break; case GE_CMD_MORPHWEIGHT0: @@ -1220,28 +1003,20 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_MORPHWEIGHT5: case GE_CMD_MORPHWEIGHT6: case GE_CMD_MORPHWEIGHT7: - { - int index = cmd - GE_CMD_MORPHWEIGHT0; - float weight = getFloat24(data); - //DEBUG_LOG(G3D,"DL MorphWeight %i = %f", index, weight); - gstate_c.morphWeights[index] = weight; - } + gstate_c.morphWeights[cmd - GE_CMD_MORPHWEIGHT0] = getFloat24(data); break; case GE_CMD_DITH0: case GE_CMD_DITH1: case GE_CMD_DITH2: case GE_CMD_DITH3: - //DEBUG_LOG(G3D,"DL DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); break; case GE_CMD_WORLDMATRIXNUMBER: - //DEBUG_LOG(G3D,"DL World # %i", data & 0xF); gstate.worldmtxnum &= 0xFF00000F; break; case GE_CMD_WORLDMATRIXDATA: - //DEBUG_LOG(G3D,"DL World data # %f", getFloat24(data)); { int num = gstate.worldmtxnum & 0xF; if (num < 12) @@ -1252,12 +1027,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_VIEWMATRIXNUMBER: - //DEBUG_LOG(G3D,"DL VIEW # %i", data & 0xF); gstate.viewmtxnum &= 0xFF00000F; break; case GE_CMD_VIEWMATRIXDATA: - //DEBUG_LOG(G3D,"DL VIEW data # %f", getFloat24(data)); { int num = gstate.viewmtxnum & 0xF; if (num < 12) @@ -1268,12 +1041,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_PROJMATRIXNUMBER: - //DEBUG_LOG(G3D,"DL PROJECTION # %i", data & 0xF); gstate.projmtxnum &= 0xFF00000F; break; case GE_CMD_PROJMATRIXDATA: - //DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data)); { int num = gstate.projmtxnum & 0xF; gstate.projMatrix[num++] = getFloat24(data); @@ -1283,12 +1054,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_TGENMATRIXNUMBER: - //DEBUG_LOG(G3D,"DL TGEN # %i", data & 0xF); gstate.texmtxnum &= 0xFF00000F; break; case GE_CMD_TGENMATRIXDATA: - //DEBUG_LOG(G3D,"DL TGEN data # %f", getFloat24(data)); { int num = gstate.texmtxnum & 0xF; if (num < 12) @@ -1299,12 +1068,10 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_BONEMATRIXNUMBER: - //DEBUG_LOG(G3D,"DL BONE #%i", data); gstate.boneMatrixNumber &= 0xFF00007F; break; case GE_CMD_BONEMATRIXDATA: - //DEBUG_LOG(G3D,"DL BONE data #%i %f", gstate.boneMatrixNumber & 0x7f, getFloat24(data)); { int num = gstate.boneMatrixNumber & 0x7F; shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); @@ -1316,10 +1083,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; default: - //DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); + DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); break; - - //ETC... } } @@ -1348,7 +1113,7 @@ bool GLES_GPU::InterpretList() if (dumpThisFrame_) { char temp[256]; GeDisassembleOp(dcontext.pc, op, prev, temp); - NOTICE_LOG(G3D, "%s", temp); + NOTICE_LOG(G3D, "%08x: %s", dcontext.pc, temp); } gstate.cmdmem[cmd] = op; @@ -1361,17 +1126,14 @@ bool GLES_GPU::InterpretList() return true; } -void GLES_GPU::UpdateStats() -{ +void GLES_GPU::UpdateStats() { gpuStats.numVertexShaders = shaderManager_->NumVertexShaders(); gpuStats.numFragmentShaders = shaderManager_->NumFragmentShaders(); gpuStats.numShaders = shaderManager_->NumPrograms(); gpuStats.numTextures = TextureCache_NumLoadedTextures(); } - -void GLES_GPU::DoBlockTransfer() -{ +void GLES_GPU::DoBlockTransfer() { // TODO: This is used a lot to copy data around between render targets and textures, // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. @@ -1407,13 +1169,12 @@ void GLES_GPU::DoBlockTransfer() memcpy(dst, src, width * bpp); } - // TODO: Notify all overlapping textures that it's time to die/reload. + // TODO: Notify all overlapping FBOs that they need to reload. TextureCache_Invalidate(dstBasePtr + dstY * dstStride + dstX, height * dstStride + width * bpp); } -void GLES_GPU::InvalidateCache(u32 addr, int size) -{ +void GLES_GPU::InvalidateCache(u32 addr, int size) { if (size > 0) TextureCache_Invalidate(addr, size); else diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 7cbd383ebf..03c3c1901f 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -63,6 +63,8 @@ TransformDrawEngine::~TransformDrawEngine() { // Just to get something on the screen, we'll just not subdivide correctly. void TransformDrawEngine::DrawBezier(int ucount, int vcount) { u16 indices[3 * 3 * 6]; + + u32 customVertType = gstate.vertType; //(gstate.vertType & ~GE_VTYPE_TC_MASK) | GE_VTYPE_TC_FLOAT; float customUV[32]; int c = 0; for (int y = 0; y < 3; y++) { @@ -83,7 +85,12 @@ void TransformDrawEngine::DrawBezier(int ucount, int vcount) { } } - SubmitPrim(Memory::GetPointer(gstate_c.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, 3 * 3 * 6, customUV, GE_VTYPE_IDX_16BIT, 0); + int vertexCount = 3 * 3 * 6; + SubmitPrim(Memory::GetPointer(gstate_c.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, vertexCount, customVertType, customUV, GE_VTYPE_IDX_16BIT, 0); +} + +void TransformDrawEngine::DrawSpline(int ucount, int vcount, int utype, int vtype) { + // TODO } // Convenient way to do precomputation to save the parts of the lighting calculation @@ -322,7 +329,7 @@ static void RotateUVs(TransformedVertex v[4]) { // Actually again, single quads could be drawn more efficiently using GL_TRIANGLE_STRIP, no need to duplicate verts as for // GL_TRIANGLES. Still need to sw transform to compute the extra two corners though. void TransformDrawEngine::SoftwareTransformAndDraw( - int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { + int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex) { /* DEBUG_LOG(G3D, "View matrix:"); const float *m = &gstate.viewMatrix[0]; @@ -336,7 +343,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( float v2[3] = {0}; float uv2[2] = {0}; - bool throughmode = (gstate.vertType & GE_VTYPE_THROUGH_MASK) != 0; + bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. @@ -383,7 +390,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( if (reader.hasNormal()) reader.ReadNrm(nrm); - if ((gstate.vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { + if ((vertType & GE_VTYPE_WEIGHT_MASK) == GE_VTYPE_WEIGHT_NONE) { Vec3ByMatrix43(out, pos, gstate.worldMatrix); if (reader.hasNormal()) { Norm3ByMatrix43(norm, nrm, gstate.worldMatrix); @@ -396,7 +403,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // Skinning Vec3 psum(0,0,0); Vec3 nsum(0,0,0); - int nweights = ((gstate.vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT) + 1; + int nweights = ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT) + 1; for (int i = 0; i < nweights; i++) { if (weights[i] != 0.0f) { @@ -608,7 +615,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( if (program->a_color1 != -1) glDisableVertexAttribArray(program->a_color1); } -void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead) { +void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vertexCount, u32 vertType, float *customUV, int forceIndexType, int *bytesRead) { // For the future if (!indexGen.PrimCompatible(prim)) Flush(); @@ -623,17 +630,18 @@ void TransformDrawEngine::SubmitPrim(void *verts, void *inds, int prim, int vert int indexLowerBound, indexUpperBound; // If vtype has changed, setup the vertex decoder. // TODO: Simply cache the setup decoders instead. - if (gstate.vertType != lastVType) { - dec.SetVertexType(gstate.vertType); - lastVType = gstate.vertType; + if (vertType != lastVType) { + dec.SetVertexType(vertType); + lastVType = vertType; } + // Decode the verts and apply morphing dec.DecodeVerts(decoded + numVerts * (int)dec.GetDecVtxFmt().stride, verts, inds, prim, vertexCount, &indexLowerBound, &indexUpperBound); numVerts += indexUpperBound - indexLowerBound + 1; if (bytesRead) *bytesRead = vertexCount * dec.VertexSize(); - int indexType = (gstate.vertType & GE_VTYPE_IDX_MASK); + int indexType = vertType & GE_VTYPE_IDX_MASK; if (forceIndexType != -1) indexType = forceIndexType; switch (indexType) { case GE_VTYPE_IDX_NONE: @@ -680,7 +688,7 @@ void TransformDrawEngine::Flush() { #if 0 for (int i = indexLowerBound; i <= indexUpperBound; i++) { - PrintDecodedVertex(decoded[i], gstate.vertType); + PrintDecodedVertex(decoded[i], vertType); } #endif @@ -718,7 +726,7 @@ void TransformDrawEngine::Flush() { } DesetupDecFmtForDraw(program, dec.GetDecVtxFmt()); } else { - SoftwareTransformAndDraw(prim, decoded, program, indexGen.VertexCount(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), + SoftwareTransformAndDraw(prim, decoded, program, indexGen.VertexCount(), dec.VertexType(), (void *)decIndex, GE_VTYPE_IDX_16BIT, dec.GetDecVtxFmt(), indexGen.MaxIndex()); } diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 393f0dce12..3be12aaa1c 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -29,15 +29,16 @@ class TransformDrawEngine { public: TransformDrawEngine(); ~TransformDrawEngine(); - void SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead); + void SubmitPrim(void *verts, void *inds, int prim, int vertexCount, u32 vertexType, float *customUV, int forceIndexType, int *bytesRead); void DrawBezier(int ucount, int vcount); + void DrawSpline(int ucount, int vcount, int utype, int vtype); void Flush(); void SetShaderManager(ShaderManager *shaderManager) { shaderManager_ = shaderManager; } private: - void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); + void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, u32 vertexType, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); // Vertex collector state IndexGenerator indexGen; @@ -56,8 +57,6 @@ private: ShaderManager *shaderManager_; }; -// void SoftwareTransformAndDraw(int prim, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex, float *customUV); - // Only used by SW transform struct Color4 { float r, g, b, a; diff --git a/GPU/GLES/VertexDecoder.h b/GPU/GLES/VertexDecoder.h index ef34677eb1..406b668428 100644 --- a/GPU/GLES/VertexDecoder.h +++ b/GPU/GLES/VertexDecoder.h @@ -84,7 +84,7 @@ public: ~VertexDecoder() {} void SetVertexType(u32 vtype); - + u32 VertexType() const { return fmt_; } const DecVtxFormat &GetDecVtxFmt() { return decFmt; } void DecodeVerts(u8 *decoded, const void *verts, const void *inds, int prim, int count, int *indexLowerBound, int *indexUpperBound) const; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 4e271b4278..843f531006 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -73,10 +73,14 @@ struct GPUgstate boneMatrixNumber, boneMatrixData, morphwgt[8], //dont use - pad04[0x39-0x33], + pad04[2], + patchdivision, + patchprimitive, + patchfacing, + pad04_a, - worldmtxnum,//0x3A - worldmtxdata, //0x3B + worldmtxnum, //0x3A + worldmtxdata, //0x3B viewmtxnum, //0x3C viewmtxdata, projmtxnum, @@ -237,10 +241,6 @@ struct GPUStateCache float lightColor[3][4][3]; //Amtient Diffuse Specular float morphWeights[8]; - // bezier patch subdivision - int patch_div_s; - int patch_div_t; - u32 curTextureWidth; u32 curTextureHeight; diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index 3cb88d4e7d..cd41ce5d12 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -44,13 +44,13 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { u32 count = data & 0xFFFF; u32 type = data >> 16; static const char* types[7] = { - "POINTS=0,", - "LINES=1,", - "LINE_STRIP=2,", - "TRIANGLES=3,", - "TRIANGLE_STRIP=4,", - "TRIANGLE_FAN=5,", - "RECTANGLES=6,", + "POINTS", + "LINES", + "LINE_STRIP", + "TRIANGLES", + "TRIANGLE_STRIP", + "TRIANGLE_FAN", + "RECTANGLES", }; sprintf(buffer, "DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); } @@ -186,12 +186,11 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { break; case GE_CMD_CLIPENABLE: - sprintf(buffer, "Clip Enable: %i (ignoring)", data); - //we always clip, this is opengl + sprintf(buffer, "Clip Enable: %i", data); break; case GE_CMD_CULLFACEENABLE: - sprintf(buffer, "CullFace Enable: %i (ignoring)", data); + sprintf(buffer, "CullFace Enable: %i", data); break; case GE_CMD_TEXTUREMAPENABLE: @@ -272,12 +271,12 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { case GE_CMD_FRAMEBUFWIDTH: { - u32 w = data & 0xFFFFFF; - sprintf(buffer, "FramebufWidth: %i", w); + sprintf(buffer, "FramebufWidth: %i", data); } break; case GE_CMD_FRAMEBUFPIXFORMAT: + sprintf(buffer, "FramebufPixeFormat: %i", data); break; case GE_CMD_TEXADDR0: @@ -331,6 +330,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { case GE_CMD_TRANSFERSRC: { + sprintf(buffer, "Block Transfer Src: %06x", data); // Nothing to do, the next one prints } break; @@ -346,6 +346,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { case GE_CMD_TRANSFERDST: { // Nothing to do, the next one prints + sprintf(buffer, "Block Transfer Dst: %06x", data); } break; @@ -407,8 +408,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { case GE_CMD_ZBUFWIDTH: { - u32 w = data & 0xFFFFFF; - sprintf(buffer, "Zbuf Width: %i", w); + sprintf(buffer, "Zbuf Width: %06x", data); } break; @@ -490,7 +490,6 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { } break; - case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3: case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: @@ -523,12 +522,14 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { sprintf(buffer, "Z pos: %f", zOff); } break; + case GE_CMD_LIGHTENABLE0: case GE_CMD_LIGHTENABLE1: case GE_CMD_LIGHTENABLE2: case GE_CMD_LIGHTENABLE3: sprintf(buffer, "Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); break; + case GE_CMD_CULL: sprintf(buffer, "cull: %06x", data); break; @@ -545,6 +546,14 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { } break; + case GE_CMD_PATCHPRIMITIVE: + sprintf(buffer, "Patch Primitive: %d", data); + break; + + case GE_CMD_PATCHFACING: + sprintf(buffer, "Patch Facing: %d", data); + break; + case GE_CMD_MATERIALUPDATE: sprintf(buffer, "Material Update: %d", data); break; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 8502418850..80d7fc9652 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -636,9 +636,6 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_PATCHDIVISION: - gstate_c.patch_div_s = data & 0xFF; - gstate_c.patch_div_t = (data >> 8) & 0xFF; - DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate_c.patch_div_s, gstate_c.patch_div_t); break; case GE_CMD_MATERIALUPDATE: diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index 319a0c4ca9..6ae1d554e3 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -69,7 +69,7 @@ enum GECommand GE_CMD_MORPHWEIGHT6=0x32, GE_CMD_MORPHWEIGHT7=0x33, GE_CMD_PATCHDIVISION=0x36, - GE_CMD_PATCHPRIMIIVE=0x37, + GE_CMD_PATCHPRIMITIVE=0x37, GE_CMD_PATCHFACING=0x38, GE_CMD_WORLDMATRIXNUMBER=0x3A, GE_CMD_WORLDMATRIXDATA, From 75ce28721330d05b258181df2e1ab66f6f698646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 28 Dec 2012 20:53:26 +0100 Subject: [PATCH 244/276] Add more stuff to GeDisasm. Advance index pointer on indexed draws. --- GPU/GLES/DisplayListInterpreter.cpp | 18 +++++++++++++--- GPU/GeDisasm.cpp | 33 +++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index deb384a0ed..af4966ee18 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -138,6 +138,9 @@ const int flushBeforeCommandList[] = { GE_CMD_STENCILTESTENABLE, GE_CMD_STENCILOP, GE_CMD_ZTEST, + GE_CMD_FOG1, + GE_CMD_FOG2, + GE_CMD_FOGCOLOR, GE_CMD_MORPHWEIGHT0, GE_CMD_MORPHWEIGHT1, GE_CMD_MORPHWEIGHT2, @@ -492,6 +495,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { ERROR_LOG(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); break; } + // TODO: Split this so that we can collect sequences of primitives, can greatly speed things up // on platforms where draw calls are expensive like mobile and D3D void *verts = Memory::GetPointer(gstate_c.vertexAddr); @@ -504,11 +508,19 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { inds = Memory::GetPointer(gstate_c.indexAddr); } - // Seems we have to advance the vertex addr, at least in some cases. - // Question: Should we also advance the index addr? int bytesRead; transformDraw_.SubmitPrim(verts, inds, type, count, gstate.vertType, 0, -1, &bytesRead); - gstate_c.vertexAddr += bytesRead; + // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). + // Some games rely on this, they don't bother reloading VADDR and IADDR. + // Q: Are these changed reflected in the real registers? Needs testing. + if (inds) { + int indexSize = 1; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT) + indexSize = 2; + gstate_c.indexAddr += count * indexSize; + } else { + gstate_c.vertexAddr += bytesRead; + } } break; diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index cd41ce5d12..ab13ac1c51 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -52,7 +52,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { "TRIANGLE_FAN", "RECTANGLES", }; - sprintf(buffer, "DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); + sprintf(buffer, "DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type < 7 ? types[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr); } break; @@ -639,9 +639,30 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { sprintf(buffer, "TexFlush"); break; + case GE_CMD_TEXSYNC: + sprintf(buffer, "TexSync"); + break; + case GE_CMD_TEXWRAP: sprintf(buffer, "TexWrap %08x", data); break; + + case GE_CMD_FOG1: + sprintf(buffer, "Fog1 %f", getFloat24(data)); + break; + + case GE_CMD_FOG2: + sprintf(buffer, "Fog2 %f", getFloat24(data)); + break; + + case GE_CMD_FOGCOLOR: + sprintf(buffer, "FogColor %06x", data); + break; + + case GE_CMD_TEXLODSLOPE: + sprintf(buffer, "TexLodSlope %06x", data); + break; + ////////////////////////////////////////////////////////////////// // Z/STENCIL TESTING ////////////////////////////////////////////////////////////////// @@ -650,6 +671,14 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { sprintf(buffer, "Z test enable: %d", data & 1); break; + case GE_CMD_STENCILOP: + sprintf(buffer, "Stencil op: %06x", data); + break; + + case GE_CMD_STENCILTEST: + sprintf(buffer, "Stencil test: %06x", data); + break; + case GE_CMD_STENCILTESTENABLE: sprintf(buffer, "Stencil test enable: %d", data); break; @@ -737,7 +766,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer) { break; default: - sprintf(buffer, "Unknown: %08x @ %08x", op, pc); + sprintf(buffer, "Unknown: %08x", op); break; } } From a2f4c83c90d34eb9e72d780169985709494f540d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 20:15:31 -0800 Subject: [PATCH 245/276] Initial state saving for kernelObjects. --- Core/HLE/sceKernel.cpp | 35 +++++++++++++++++++++++++++++++++++ Core/HLE/sceKernel.h | 12 ++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 27d8464fb4..1883e7b64b 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -136,6 +136,18 @@ void __KernelShutdown() kernelRunning = false; } +void __KernelDoState(PointerWrap &p) +{ + kernelObjects.DoState(p); + p.DoMarker("KernelObjects"); + // TODO + // kernelObjects + // modules + // core timing + // memstick + // filesystem +} + bool __KernelIsRunning() { return kernelRunning; } @@ -304,6 +316,29 @@ int KernelObjectPool::GetCount() return count; } +void KernelObjectPool::DoState(PointerWrap &p) +{ + int _maxCount = maxCount; + p.Do(_maxCount); + p.DoArray(occupied, maxCount); + for (int i = 0; i < maxCount; ++i) + { + if (!occupied[i]) + continue; + + KernelObject *t = pool[i]; + if (!t) + { + // TODO: Pass down error? + ERROR_LOG(HLE, "Unable to save state: inconsistent kernel object pool."); + return; + } + + t->DoState(p); + } + p.DoMarker("KernelObjectPool"); +} + void sceKernelIcacheInvalidateAll() { DEBUG_LOG(CPU, "Icache invalidated - should clear JIT someday"); diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index bf5d609c10..cfb1c1cfcb 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -18,6 +18,7 @@ #pragma once #include "../../Globals.h" +#include "../../Common/ChunkFile.h" #include enum @@ -263,6 +264,7 @@ struct SceKernelLoadExecParam void __KernelInit(); void __KernelShutdown(); +void __KernelDoState(PointerWrap &p); bool __KernelIsRunning(); bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param); @@ -311,9 +313,11 @@ public: // Implement this in all subclasses: // static u32 GetMissingErrorCode() - // Future - // void Serialize(ChunkFile) - // void DeSerialize(ChunkFile) + virtual void DoState(PointerWrap &p) + { + // TODO + //_dbg_assert_msg_(HLE, false, "Bad kernel object"); + } }; @@ -325,7 +329,7 @@ public: // Allocates a UID within the range and inserts the object into the map. SceUID Create(KernelObject *obj, int rangeBottom = 16, int rangeTop = 0x7fffffff); - // TODO: How will we ever save/restore this pool? + void DoState(PointerWrap &p); template u32 Destroy(SceUID handle) From 991243fffdcdfb618fec755748bee08bbf8551f1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 20:34:10 -0800 Subject: [PATCH 246/276] Add basic DoState() to tertiary kernel objects. --- Core/HLE/sceKernel.h | 3 +-- Core/HLE/sceKernelAlarm.cpp | 26 +++++++++++++++++++++----- Core/HLE/sceKernelEventFlag.cpp | 7 +++++++ Core/HLE/sceKernelMbx.cpp | 7 +++++++ Core/HLE/sceKernelMsgPipe.cpp | 19 ++++++++++++++----- Core/HLE/sceKernelMutex.cpp | 16 ++++++++++++++++ Core/HLE/sceKernelSemaphore.cpp | 7 +++++++ Core/HLE/sceKernelVTimer.cpp | 12 ++++++++++++ 8 files changed, 85 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index cfb1c1cfcb..9ae451eb8e 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -315,8 +315,7 @@ public: virtual void DoState(PointerWrap &p) { - // TODO - //_dbg_assert_msg_(HLE, false, "Bad kernel object"); + _dbg_assert_msg_(HLE, false, "Unable to save state: bad kernel object."); } }; diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 4e378b2a49..3a26a7788b 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -37,6 +37,13 @@ struct Alarm : public KernelObject const char *GetTypeName() {return "Alarm";} static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; } int GetIDType() const { return SCE_KERNEL_TMID_Alarm; } + + virtual void DoState(PointerWrap &p) + { + p.Do(alm); + p.DoMarker("Alarm"); + } + NativeAlarm alm; }; @@ -47,7 +54,7 @@ class AlarmIntrHandler : public SubIntrHandler public: AlarmIntrHandler(Alarm *alarm) { - this->alarm = alarm; + alarmID = alarm->GetUID(); handlerAddress = alarm->alm.handlerPtr; enabled = true; } @@ -56,26 +63,35 @@ public: { SubIntrHandler::copyArgsToCPU(pend); - currentMIPS->r[MIPS_REG_A0] = alarm->alm.commonPtr; + u32 error; + Alarm *alarm = kernelObjects.Get(alarmID, error); + if (alarm) + currentMIPS->r[MIPS_REG_A0] = alarm->alm.commonPtr; + else + ERROR_LOG(HLE, "sceKernelAlarm: Unable to send interrupt args: alarm deleted?"); } virtual void handleResult(int result) { // A non-zero result means to reschedule. if (result > 0) + { + u32 error; + Alarm *alarm = kernelObjects.Get(alarmID, error); __KernelScheduleAlarm(alarm, (u64) usToCycles(result)); + } else { if (result < 0) WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); // Delete the alarm if it's not rescheduled. - __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, alarm->GetUID()); - kernelObjects.Destroy(alarm->GetUID()); + kernelObjects.Destroy(alarmID); + __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, alarmID); } } - Alarm *alarm; + SceUID alarmID; }; static int alarmTimer = 0; diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index a28c06c0d6..5a2c625117 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -63,6 +63,13 @@ public: } int GetIDType() const { return SCE_KERNEL_TMID_EventFlag; } + virtual void DoState(PointerWrap &p) + { + p.Do(nef); + p.Do(waitingThreads); + p.DoMarker("EventFlag"); + } + NativeEventFlag nef; std::vector waitingThreads; }; diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index c8c758a215..080226870e 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -153,6 +153,13 @@ struct Mbx : public KernelObject return 0; } + virtual void DoState(PointerWrap &p) + { + p.Do(nmb); + p.Do(waitingThreads); + p.DoMarker("Mbx"); + } + NativeMbx nmb; std::vector waitingThreads; diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 1521d5f188..e98786f366 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -56,11 +56,6 @@ struct MsgPipe : public KernelObject static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; } int GetIDType() const { return SCE_KERNEL_TMID_Mpipe; } - NativeMsgPipe nmp; - - std::vector sendWaitingThreads; - std::vector receiveWaitingThreads; - void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr, bool usePrio) { MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr }; @@ -150,6 +145,20 @@ struct MsgPipe : public KernelObject } } + virtual void DoState(PointerWrap &p) + { + p.Do(nmp); + p.Do(sendWaitingThreads); + p.Do(receiveWaitingThreads); + p.DoArray(buffer, nmp.bufSize); + p.DoMarker("MsgPipe"); + } + + NativeMsgPipe nmp; + + std::vector sendWaitingThreads; + std::vector receiveWaitingThreads; + u8 *buffer; }; diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index e3d048e545..b5a78afdfe 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -62,6 +62,14 @@ struct Mutex : public KernelObject const char *GetTypeName() {return "Mutex";} static u32 GetMissingErrorCode() { return PSP_MUTEX_ERROR_NO_SUCH_MUTEX; } int GetIDType() const { return SCE_KERNEL_TMID_Mutex; } + + virtual void DoState(PointerWrap &p) + { + p.Do(nm); + p.Do(waitingThreads); + p.DoMarker("Mutex"); + } + NativeMutex nm; std::vector waitingThreads; }; @@ -103,6 +111,14 @@ struct LwMutex : public KernelObject const char *GetTypeName() {return "LwMutex";} static u32 GetMissingErrorCode() { return PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; } int GetIDType() const { return SCE_KERNEL_TMID_LwMutex; } + + virtual void DoState(PointerWrap &p) + { + p.Do(nm); + p.Do(waitingThreads); + p.DoMarker("LwMutex"); + } + NativeLwMutex nm; std::vector waitingThreads; }; diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 2fd575d0d4..54c30ae831 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -57,6 +57,13 @@ struct Semaphore : public KernelObject static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_SEMID; } int GetIDType() const { return SCE_KERNEL_TMID_Semaphore; } + virtual void DoState(PointerWrap &p) + { + p.Do(ns); + p.Do(waitingThreads); + p.DoMarker("Semaphore"); + } + NativeSemaphore ns; std::vector waitingThreads; }; diff --git a/Core/HLE/sceKernelVTimer.cpp b/Core/HLE/sceKernelVTimer.cpp index 299e47fd6b..ad3d383141 100644 --- a/Core/HLE/sceKernelVTimer.cpp +++ b/Core/HLE/sceKernelVTimer.cpp @@ -30,6 +30,18 @@ struct VTimer : public KernelObject static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VTID; } int GetIDType() const { return SCE_KERNEL_TMID_VTimer; } + virtual void DoState(PointerWrap &p) + { + p.Do(size); + p.Do(name); + p.Do(startTime); + p.Do(running); + p.Do(handler); + p.Do(handlerTime); + p.Do(argument); + p.DoMarker("VTimer"); + } + SceSize size; char name[KERNELOBJECT_MAX_NAME_LENGTH+1]; u64 startTime; From d9efdf548b9f244413108395abf6618b59c68177 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 21:07:29 -0800 Subject: [PATCH 247/276] Add basic state for the memory kernel objects. Not the actual memory partitions quite yet. --- Common/ChunkFile.h | 22 +++++++++++++++++++++- Core/HLE/sceKernelMemory.cpp | 34 ++++++++++++++++++++++++++++++---- Core/Util/BlockAllocator.cpp | 10 ++++++++++ Core/Util/BlockAllocator.h | 5 ++++- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index 7228365ccd..83270c32ac 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "Common.h" #include "FileUtil.h" @@ -133,7 +134,26 @@ public: for(i = 0; i < deq_size; i++) DoVoid(&x[i],sizeof(T)); } - + + // Store STL lists. + template + void Do(std::list &x) + { + T dv; + Do(x, dv); + } + + template + void Do(std::list &x, T &default_val) + { + u32 list_size = (u32)x.size(); + x.resize(list_size, default_val); + + typename std::list::iterator itr, end; + for (itr = x.begin(), end = x.end(); itr != end; ++itr) + Do(*itr); + } + // Store strings. void Do(std::string &x) { diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 0b5a3c49b7..2b06e0108a 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -59,9 +59,6 @@ struct FPL : KernelObject const char *GetTypeName() {return "FPL";} static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_FPLID; } int GetIDType() const { return SCE_KERNEL_TMID_Fpl; } - NativeFPL nf; - bool *blocks; - u32 address; int findFreeBlock() { for (int i = 0; i < nf.numBlocks; i++) { @@ -85,6 +82,18 @@ struct FPL : KernelObject } return false; } + + virtual void DoState(PointerWrap &p) + { + p.Do(nf); + p.DoArray(blocks, nf.numBlocks); + p.Do(address); + p.DoMarker("FPL"); + } + + NativeFPL nf; + bool *blocks; + u32 address; }; struct SceKernelVplInfo @@ -103,9 +112,18 @@ struct VPL : KernelObject const char *GetTypeName() {return "VPL";} static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_VPLID; } int GetIDType() const { return SCE_KERNEL_TMID_Vpl; } + + virtual void DoState(PointerWrap &p) + { + p.Do(nv); + p.Do(size); + p.Do(address); + alloc.DoState(p); + p.DoMarker("VPL"); + } + SceKernelVplInfo nv; u32 size; - bool *freeBlocks; u32 address; BlockAllocator alloc; }; @@ -364,6 +382,14 @@ public: } bool IsValid() {return address != (u32)-1;} BlockAllocator *alloc; + + virtual void DoState(PointerWrap &p) + { + p.Do(address); + p.Do(name); + p.DoMarker("PMB"); + } + u32 address; char name[32]; }; diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index 27183cbff8..66cc8484e7 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -297,3 +297,13 @@ u32 BlockAllocator::GetTotalFreeBytes() } return sum; } + +void BlockAllocator::DoState(PointerWrap &p) +{ + Block default_value(0, 0, false); + p.Do(blocks, default_value); + p.Do(rangeStart_); + p.Do(rangeSize_); + p.Do(grain_); + p.DoMarker("BlockAllocator"); +} diff --git a/Core/Util/BlockAllocator.h b/Core/Util/BlockAllocator.h index 7ed26d3fc6..dc75a8292e 100644 --- a/Core/Util/BlockAllocator.h +++ b/Core/Util/BlockAllocator.h @@ -2,6 +2,7 @@ #pragma once #include "../../Globals.h" +#include "../../Common/ChunkFile.h" #include #include @@ -22,7 +23,7 @@ public: void ListBlocks(); - // WARNING: size can be modified upwards! + // WARNING: size can be modified upwards! u32 Alloc(u32 &size, bool fromTop = false, const char *tag = 0); u32 AllocAt(u32 position, u32 size, const char *tag = 0); @@ -42,6 +43,8 @@ public: u32 GetLargestFreeBlockSize(); u32 GetTotalFreeBytes(); + void DoState(PointerWrap &p); + private: void CheckBlocks(); From 595759ef78f0ea320335b67c5340fac87c5246ec Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 22:45:19 -0800 Subject: [PATCH 248/276] Implement a factory for kernel objects. Couldn't think of a better way to do this, maybe there's some fancy one I don't know about. Also finished up a couple left over kernel objects. Maybe a quarter the way there? --- Common/ChunkFile.h | 37 +++++++++++++++++++ Core/FileSystems/FileSystem.h | 15 ++++++++ Core/HLE/sceIo.cpp | 34 ++++++++++++++++- Core/HLE/sceIo.h | 3 ++ Core/HLE/sceKernel.cpp | 65 +++++++++++++++++++++++++++++---- Core/HLE/sceKernel.h | 8 ++++ Core/HLE/sceKernelAlarm.cpp | 6 +++ Core/HLE/sceKernelAlarm.h | 1 + Core/HLE/sceKernelEventFlag.cpp | 6 +++ Core/HLE/sceKernelEventFlag.h | 1 + Core/HLE/sceKernelMbx.cpp | 5 +++ Core/HLE/sceKernelMbx.h | 1 + Core/HLE/sceKernelMemory.cpp | 31 +++++++++++++--- Core/HLE/sceKernelMemory.h | 4 ++ Core/HLE/sceKernelModule.cpp | 16 +++++++- Core/HLE/sceKernelModule.h | 2 + Core/HLE/sceKernelMsgPipe.cpp | 5 +++ Core/HLE/sceKernelMsgPipe.h | 4 +- Core/HLE/sceKernelMutex.cpp | 10 +++++ Core/HLE/sceKernelMutex.h | 2 + Core/HLE/sceKernelSemaphore.cpp | 5 +++ Core/HLE/sceKernelSemaphore.h | 1 + Core/HLE/sceKernelThread.cpp | 50 +++++++++++++++++++++++++ Core/HLE/sceKernelThread.h | 2 + Core/HLE/sceKernelVTimer.cpp | 5 +++ Core/HLE/sceKernelVTimer.h | 2 + 26 files changed, 304 insertions(+), 17 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index 83270c32ac..00d8593000 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "Common.h" #include "FileUtil.h" @@ -147,6 +148,7 @@ public: void Do(std::list &x, T &default_val) { u32 list_size = (u32)x.size(); + Do(list_size); x.resize(list_size, default_val); typename std::list::iterator itr, end; @@ -154,6 +156,41 @@ public: Do(*itr); } + // Store STL sets. + template + void Do(std::set &x) + { + unsigned int number = (unsigned int)x.size(); + Do(number); + + switch (mode) + { + case MODE_READ: + { + x.clear(); + while (number-- > 0) + { + T it; + Do(it); + x.insert(it); + } + } + break; + case MODE_WRITE: + case MODE_MEASURE: + case MODE_VERIFY: + { + typename std::set::iterator itr = x.begin(); + while (number-- > 0) + Do(*itr++); + } + break; + + default: + ERROR_LOG(COMMON, "Savestate error: invalid mode %d.", mode); + } + } + // Store strings. void Do(std::string &x) { diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index ab1c1e48d2..d14854803e 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -18,6 +18,7 @@ #pragma once #include "../../Globals.h" +#include "../../Common/ChunkFile.h" #include enum FileAccess @@ -56,6 +57,20 @@ struct PSPFileInfo PSPFileInfo() : size(0), access(0), exists(false), type(FILETYPE_NORMAL), isOnSectorSystem(false), startSector(0), numSectors(0) {} + void DoState(PointerWrap &p) + { + p.Do(name); + p.Do(size); + p.Do(access); + p.Do(exists); + p.Do(type); + p.Do(mtime); + p.Do(isOnSectorSystem); + p.Do(startSector); + p.Do(numSectors); + p.DoMarker("PSPFileInfo"); + } + std::string name; s64 size; u32 access; //unix 777 diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 2523539a0a..801b4bf917 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -137,7 +137,18 @@ public: sprintf(ptr, "Seekpos: %08x", (u32)pspFileSystem.GetSeekPos(handle)); } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } - int GetIDType() const { return 0; } + int GetIDType() const { return PPSSPP_KERNEL_TMID_File; } + + virtual void DoState(PointerWrap &p) { + p.Do(fullpath); + p.Do(handle); + p.Do(callbackID); + p.Do(callbackArg); + p.Do(asyncResult); + p.Do(pendingAsyncResult); + p.Do(sectorBlockMode); + p.DoMarker("File"); + } std::string fullpath; u32 handle; @@ -836,7 +847,18 @@ public: const char *GetName() {return name.c_str();} const char *GetTypeName() {return "DirListing";} static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_BADF; } - int GetIDType() const { return 0; } + int GetIDType() const { return PPSSPP_KERNEL_TMID_DirList; } + + virtual void DoState(PointerWrap &p) { + p.Do(name); + + // TODO: Is this the right way for it to wake up? + size_t count = listing.size(); + for (size_t i = 0; i < count; ++i) { + listing[i].DoState(p); + } + p.DoMarker("DirListing"); + } std::string name; std::vector listing; @@ -920,6 +942,14 @@ u32 sceIoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 ou return 0; } +KernelObject *__KernelFileNodeObject() { + return new FileNode; +} + +KernelObject *__KernelDirListingObject() { + return new DirListing; +} + const HLEFunction IoFileMgrForUser[] = { { 0xb29ddf9c, &WrapU_C, "sceIoDopen" }, { 0xe3eb004c, &WrapU_IU, "sceIoDread" }, diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index 907fd6046b..8015bd93d9 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -19,9 +19,12 @@ #include #include "HLE.h" +#include "sceKernel.h" void __IoInit(); void __IoShutdown(); +KernelObject *__KernelFileNodeObject(); +KernelObject *__KernelDirListingObject(); void Register_IoFileMgrForUser(); void Register_StdioForUser(); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 1883e7b64b..947d6d3a48 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -320,25 +320,76 @@ void KernelObjectPool::DoState(PointerWrap &p) { int _maxCount = maxCount; p.Do(_maxCount); + + if (_maxCount != maxCount) + ERROR_LOG(HLE, "Unable to load state: different kernel object storage."); + + // Assumption: on load, we've already cleared. p.DoArray(occupied, maxCount); for (int i = 0; i < maxCount; ++i) { if (!occupied[i]) continue; - KernelObject *t = pool[i]; - if (!t) + int type; + if (p.mode == p.MODE_READ) { - // TODO: Pass down error? - ERROR_LOG(HLE, "Unable to save state: inconsistent kernel object pool."); - return; + p.Do(type); + pool[i] = CreateByIDType(type); } - - t->DoState(p); + else + { + type = pool[i]->GetIDType(); + p.Do(type); + } + pool[i]->DoState(p); } p.DoMarker("KernelObjectPool"); } +KernelObject *KernelObjectPool::CreateByIDType(int type) +{ + // Used for save states. This is ugly, but what other way is there? + switch (type) + { + case SCE_KERNEL_TMID_Alarm: + return __KernelAlarmObject(); + case SCE_KERNEL_TMID_EventFlag: + return __KernelEventFlagObject(); + case SCE_KERNEL_TMID_Mbox: + return __KernelMbxObject(); + case SCE_KERNEL_TMID_Fpl: + return __KernelMemoryFPLObject(); + case SCE_KERNEL_TMID_Vpl: + return __KernelMemoryVPLObject(); + case PPSSPP_KERNEL_TMID_PMB: + return __KernelMemoryPMBObject(); + case PPSSPP_KERNEL_TMID_Module: + return __KernelModuleObject(); + case SCE_KERNEL_TMID_Mpipe: + return __KernelMsgPipeObject(); + case SCE_KERNEL_TMID_Mutex: + return __KernelMutexObject(); + case SCE_KERNEL_TMID_LwMutex: + return __KernelLwMutexObject(); + case SCE_KERNEL_TMID_Semaphore: + return __KernelSemaphoreObject(); + case SCE_KERNEL_TMID_Callback: + return __KernelCallbackObject(); + case SCE_KERNEL_TMID_Thread: + return __KernelThreadObject(); + case SCE_KERNEL_TMID_VTimer: + return __KernelVTimerObject(); + case PPSSPP_KERNEL_TMID_File: + return __KernelFileNodeObject(); + case PPSSPP_KERNEL_TMID_DirList: + return __KernelDirListingObject(); + + default: + ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type); + } +} + void sceKernelIcacheInvalidateAll() { DEBUG_LOG(CPU, "Icache invalidated - should clear JIT someday"); diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index 9ae451eb8e..90835442d1 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -224,6 +224,7 @@ enum SCE_KERNEL_ERROR_ERRORMAX = 0x8002044d, }; +// If you add to this, make sure to check KernelObjectPool::CreateByIDType(). enum TMIDPurpose { SCE_KERNEL_TMID_Thread = 1, @@ -243,6 +244,12 @@ enum TMIDPurpose SCE_KERNEL_TMID_DelayThread = 65, SCE_KERNEL_TMID_SuspendThread = 66, SCE_KERNEL_TMID_DormantThread = 67, + + // Not official, but need ids for save states. + PPSSPP_KERNEL_TMID_Module = 0x100001, + PPSSPP_KERNEL_TMID_PMB = 0x100002, + PPSSPP_KERNEL_TMID_File = 0x100003, + PPSSPP_KERNEL_TMID_DirList = 0x100004, }; typedef int SceUID; @@ -329,6 +336,7 @@ public: SceUID Create(KernelObject *obj, int rangeBottom = 16, int rangeTop = 0x7fffffff); void DoState(PointerWrap &p); + static KernelObject *CreateByIDType(int type); template u32 Destroy(SceUID handle) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 3a26a7788b..ea833860ec 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -111,6 +111,12 @@ void __KernelAlarmInit() alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); } +KernelObject *__KernelAlarmObject() +{ + // Default object to load from state. + return new Alarm; +} + void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) { alarm->alm.schedule = (CoreTiming::GetTicks() + ticks) / (u64) CoreTiming::GetClockFrequencyMHz(); diff --git a/Core/HLE/sceKernelAlarm.h b/Core/HLE/sceKernelAlarm.h index 09dd2e2f82..24cc866e37 100644 --- a/Core/HLE/sceKernelAlarm.h +++ b/Core/HLE/sceKernelAlarm.h @@ -23,3 +23,4 @@ int sceKernelCancelAlarm(SceUID uid); int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); void __KernelAlarmInit(); +KernelObject *__KernelAlarmObject(); diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 5a2c625117..f0e5e16034 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -104,6 +104,12 @@ void __KernelEventFlagInit() eventFlagWaitTimer = CoreTiming::RegisterEvent("EventFlagTimeout", &__KernelEventFlagTimeout); } +KernelObject *__KernelEventFlagObject() +{ + // Default object to load from state. + return new EventFlag; +} + bool __KernelEventFlagMatches(u32 *pattern, u32 bits, u8 wait, u32 outAddr) { if ((wait & PSP_EVENT_WAITOR) diff --git a/Core/HLE/sceKernelEventFlag.h b/Core/HLE/sceKernelEventFlag.h index 4243b8d897..2eb1c659ba 100644 --- a/Core/HLE/sceKernelEventFlag.h +++ b/Core/HLE/sceKernelEventFlag.h @@ -28,3 +28,4 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr); u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr); void __KernelEventFlagInit(); +KernelObject *__KernelEventFlagObject(); diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index 080226870e..3ae6ae4f04 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -170,6 +170,11 @@ void __KernelMbxInit() mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", &__KernelMbxTimeout); } +KernelObject *__KernelMbxObject() +{ + return new Mbx; +} + bool __KernelUnlockMbxForThread(Mbx *m, MbxWaitingThread &th, u32 &error, int result, bool &wokeThreads) { SceUID waitID = __KernelGetWaitID(th.first, WAITTYPE_MBX, error); diff --git a/Core/HLE/sceKernelMbx.h b/Core/HLE/sceKernelMbx.h index 7edf6309e9..b0fb25e952 100644 --- a/Core/HLE/sceKernelMbx.h +++ b/Core/HLE/sceKernelMbx.h @@ -34,3 +34,4 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr); int sceKernelReferMbxStatus(SceUID id, u32 infoAddr); void __KernelMbxInit(); +KernelObject *__KernelMbxObject(); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 2b06e0108a..807e74a2e1 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -53,7 +53,7 @@ struct NativeFPL }; //FPL - Fixed Length Dynamic Memory Pool - every item has the same length -struct FPL : KernelObject +struct FPL : public KernelObject { const char *GetName() {return nf.name;} const char *GetTypeName() {return "FPL";} @@ -106,7 +106,7 @@ struct SceKernelVplInfo int numWaitThreads; }; -struct VPL : KernelObject +struct VPL : public KernelObject { const char *GetName() {return nv.name;} const char *GetTypeName() {return "VPL";} @@ -368,13 +368,18 @@ public: sprintf(ptr, "MemPart: %08x - %08x size: %08x", address, address + sz, sz); } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; } /// ???? - int GetIDType() const { return 0; } + int GetIDType() const { return PPSSPP_KERNEL_TMID_PMB; } PartitionMemoryBlock(BlockAllocator *_alloc, u32 size, bool fromEnd) { alloc = _alloc; - address = alloc->Alloc(size, fromEnd, "PMB"); - alloc->ListBlocks(); + + // 0 is used for save states to wake up. + if (size != 0) + { + address = alloc->Alloc(size, fromEnd, "PMB"); + alloc->ListBlocks(); + } } ~PartitionMemoryBlock() { @@ -620,6 +625,22 @@ void sceKernelSetCompilerVersion(int version) flags_ |= SCE_KERNEL_HASCOMPILERVERSION; } +KernelObject *__KernelMemoryFPLObject() +{ + return new FPL; +} + +KernelObject *__KernelMemoryVPLObject() +{ + return new VPL; +} + +KernelObject *__KernelMemoryPMBObject() +{ + // TODO: We could theoretically handle kernelMemory too, but we don't support that now anyway. + return new PartitionMemoryBlock(&userMemory, 0, true); +} + // VPL = variable length memory pool diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index eaf2e23f4c..cc5334ae89 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -18,6 +18,7 @@ #pragma once #include "../Util/BlockAllocator.h" +#include "sceKernel.h" //todo: "real" memory block allocator, @@ -30,6 +31,9 @@ extern BlockAllocator kernelMemory; void __KernelMemoryInit(); void __KernelMemoryShutdown(); +KernelObject *__KernelMemoryFPLObject(); +KernelObject *__KernelMemoryVPLObject(); +KernelObject *__KernelMemoryPMBObject(); void sceKernelCreateVpl(); void sceKernelDeleteVpl(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index a1b045bc9f..1f7b0c050c 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -117,13 +117,25 @@ public: nm.entry_addr); } static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MODULE; } - int GetIDType() const { return 0; } + int GetIDType() const { return PPSSPP_KERNEL_TMID_Module; } + + virtual void DoState(PointerWrap &p) + { + p.Do(nm); + p.Do(memoryBlockAddr); + p.DoMarker("Module"); + } NativeModule nm; u32 memoryBlockAddr; }; +KernelObject *__KernelModuleObject() +{ + return new Module; +} + ////////////////////////////////////////////////////////////////////////// // MODULES ////////////////////////////////////////////////////////////////////////// @@ -642,7 +654,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags) class AfterModuleEntryCall : public Action { public: AfterModuleEntryCall() {} - Module *module_; + SceUID moduleID_; u32 retValAddr; virtual void run(); }; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 2652e1e55f..18e3d5f036 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -20,6 +20,8 @@ #include "sceKernel.h" #include "HLE.h" +KernelObject *__KernelModuleObject(); + u32 __KernelGetModuleGP(SceUID module); bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std::string *error_string); diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index e98786f366..8d60cccf48 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -162,6 +162,11 @@ struct MsgPipe : public KernelObject u8 *buffer; }; +KernelObject *__KernelMsgPipeObject() +{ + return new MsgPipe; +} + void sceKernelCreateMsgPipe() { const char *name = Memory::GetCharPointer(PARAM(0)); diff --git a/Core/HLE/sceKernelMsgPipe.h b/Core/HLE/sceKernelMsgPipe.h index 0f262038b8..46f812f4ee 100644 --- a/Core/HLE/sceKernelMsgPipe.h +++ b/Core/HLE/sceKernelMsgPipe.h @@ -26,4 +26,6 @@ void sceKernelReceiveMsgPipe(); void sceKernelReceiveMsgPipeCB(); void sceKernelTryReceiveMsgPipe(); void sceKernelCancelMsgPipe(); -void sceKernelReferMsgPipeStatus(); \ No newline at end of file +void sceKernelReferMsgPipeStatus(); + +KernelObject *__KernelMsgPipeObject(); diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index b5a78afdfe..c0778031c7 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -137,6 +137,16 @@ void __KernelMutexInit() __KernelListenThreadEnd(&__KernelMutexThreadEnd); } +KernelObject *__KernelMutexObject() +{ + return new Mutex; +} + +KernelObject *__KernelLwMutexObject() +{ + return new LwMutex; +} + void __KernelMutexShutdown() { mutexHeldLocks.clear(); diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index de54371948..5db1f3b4d5 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -38,3 +38,5 @@ void __KernelMutexThreadEnd(SceUID thread); void __KernelMutexInit(); void __KernelMutexShutdown(); +KernelObject *__KernelMutexObject(); +KernelObject *__KernelLwMutexObject(); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 54c30ae831..0572a8d70d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -75,6 +75,11 @@ void __KernelSemaInit() semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout); } +KernelObject *__KernelSemaphoreObject() +{ + return new Semaphore; +} + // Returns whether the thread should be removed. bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int result, bool &wokeThreads) { diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index 9a8b9f2640..f816f97e41 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -29,3 +29,4 @@ int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); void __KernelSemaTimeout(u64 userdata, int cycleslate); void __KernelSemaInit(); +KernelObject *__KernelSemaphoreObject(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 8d03a17f8a..816c3f4a2c 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -113,6 +113,18 @@ public: static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_CBID; } int GetIDType() const { return SCE_KERNEL_TMID_Callback; } + virtual void DoState(PointerWrap &p) + { + p.Do(nc); + p.Do(savedPC); + p.Do(savedRA); + p.Do(savedV0); + p.Do(savedV1); + p.Do(savedIdRegister); + p.Do(forceDelete); + p.DoMarker("Callback"); + } + NativeCallback nc; u32 savedPC; @@ -297,6 +309,34 @@ public: bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; } bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; } + virtual void DoState(PointerWrap &p) + { + p.Do(nt); + p.Do(waitInfo); + p.Do(sleeping); + p.Do(moduleId); + p.Do(isProcessingCallbacks); + p.Do(currentCallbackId); + p.Do(context); + + u32 numCallbacks = THREAD_CALLBACK_NUM_TYPES; + p.Do(numCallbacks); + if (numCallbacks != THREAD_CALLBACK_NUM_TYPES) + ERROR_LOG(HLE, "Unable to load state: different kernel object storage."); + + for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i) + { + std::set::iterator it, end; + p.Do(registeredCallbacks[i]); + p.Do(readyCallbacks[i]); + } + + p.Do(pendingMipsCalls); + p.Do(stackBlock); + + p.DoMarker("Thread"); + } + NativeThread nt; ThreadWaitInfo waitInfo; @@ -409,6 +449,16 @@ void __KernelThreadingInit() __KernelListenThreadEnd(__KernelCancelWakeup); } +KernelObject *__KernelThreadObject() +{ + return new Thread; +} + +KernelObject *__KernelCallbackObject() +{ + return new Callback; +} + void __KernelListenThreadEnd(ThreadCallback callback) { threadEndListeners.push_back(callback); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 913511fe65..d11a33c17c 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -98,6 +98,8 @@ struct ThreadContext void __KernelThreadingInit(); void __KernelThreadingShutdown(); +KernelObject *__KernelThreadObject(); +KernelObject *__KernelCallbackObject(); void __KernelScheduleWakeup(int usFromNow, int threadnumber); SceUID __KernelGetCurThread(); diff --git a/Core/HLE/sceKernelVTimer.cpp b/Core/HLE/sceKernelVTimer.cpp index ad3d383141..35174f34f1 100644 --- a/Core/HLE/sceKernelVTimer.cpp +++ b/Core/HLE/sceKernelVTimer.cpp @@ -51,6 +51,11 @@ struct VTimer : public KernelObject u32 argument; }; +KernelObject *__KernelVTimerObject() +{ + return new VTimer; +} + void sceKernelCreateVTimer() { DEBUG_LOG(HLE,"sceKernelCreateVTimer"); diff --git a/Core/HLE/sceKernelVTimer.h b/Core/HLE/sceKernelVTimer.h index 260341b214..3597dfeb18 100644 --- a/Core/HLE/sceKernelVTimer.h +++ b/Core/HLE/sceKernelVTimer.h @@ -23,3 +23,5 @@ void sceKernelSetVTimerHandler(); // TODO void _sceKernelReturnFromTimerHandler(); + +KernelObject *__KernelVTimerObject(); From d6d3688c8c6d3119178b335661fb5a89ad650a6b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 26 Dec 2012 22:50:45 -0800 Subject: [PATCH 249/276] Fix a warning if loading wrong version / etc. --- Core/HLE/sceKernel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 947d6d3a48..9ef1122e45 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -336,6 +336,10 @@ void KernelObjectPool::DoState(PointerWrap &p) { p.Do(type); pool[i] = CreateByIDType(type); + + // Already logged an error. + if (pool[i] == NULL) + return; } else { @@ -387,6 +391,7 @@ KernelObject *KernelObjectPool::CreateByIDType(int type) default: ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type); + return NULL; } } From abeaaa91057abb78e3ad0e581d9e868755721128 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 10:34:22 -0800 Subject: [PATCH 250/276] Add Verify() method to quickly test states work. --- CMakeLists.txt | 2 ++ Common/ChunkFile.h | 24 ++++++++++++++++++++ Core/Core.vcxproj | 2 ++ Core/Core.vcxproj.filters | 6 +++++ Core/HLE/sceKernel.cpp | 1 - Core/SaveState.cpp | 46 +++++++++++++++++++++++++++++++++++++++ Core/SaveState.h | 33 ++++++++++++++++++++++++++++ Qt/Core.pro | 2 ++ android/jni/Android.mk | 1 + 9 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 Core/SaveState.cpp create mode 100644 Core/SaveState.h diff --git a/CMakeLists.txt b/CMakeLists.txt index caaee30936..5fd1b01c88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -765,6 +765,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/PSPLoaders.h Core/PSPMixer.cpp Core/PSPMixer.h + Core/SaveState.cpp + Core/SaveState.h Core/System.cpp Core/System.h Core/Util/BlockAllocator.cpp diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index 00d8593000..eda388211e 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -428,6 +428,30 @@ public: return true; } + template + static bool Verify(T& _class) + { + u8 *ptr = 0; + + // Step 1: Measure the space required. + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); + _class.DoState(p); + size_t const sz = (size_t)ptr; + std::vector buffer(sz); + + // Step 2: Dump the state. + ptr = &buffer[0]; + p.SetMode(PointerWrap::MODE_WRITE); + _class.DoState(p); + + // Step 3: Verify the state. + ptr = &buffer[0]; + p.SetMode(PointerWrap::MODE_VERIFY); + _class.DoState(p); + + return true; + } + private: struct SChunkHeader { diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index f10562449e..089671dfb9 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -253,6 +253,7 @@ + @@ -371,6 +372,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 0784ba189c..d6bf753d66 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -348,6 +348,9 @@ HLE\Libraries + + Core + @@ -641,6 +644,9 @@ HLE\Libraries + + Core + diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 9ef1122e45..da528027eb 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -141,7 +141,6 @@ void __KernelDoState(PointerWrap &p) kernelObjects.DoState(p); p.DoMarker("KernelObjects"); // TODO - // kernelObjects // modules // core timing // memstick diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp new file mode 100644 index 0000000000..bbf0e2328d --- /dev/null +++ b/Core/SaveState.cpp @@ -0,0 +1,46 @@ +// 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 "SaveState.h" +#include "MemMap.h" +#include "HLE/sceKernel.h" + +// TODO: Need a way to schedule via CoreTiming and actually run then. + +bool SaveState::Load(std::string &filename) +{ + SaveState state; + return CChunkFileReader::Load(filename, REVISION, state); +} + +bool SaveState::Save(std::string &filename) +{ + SaveState state; + return CChunkFileReader::Save(filename, REVISION, state); +} + +bool SaveState::Verify() +{ + SaveState state; + return CChunkFileReader::Verify(state); +} + +void SaveState::DoState(PointerWrap &p) +{ + Memory::DoState(p); + __KernelDoState(p); +} \ No newline at end of file diff --git a/Core/SaveState.h b/Core/SaveState.h new file mode 100644 index 0000000000..f0edfcf921 --- /dev/null +++ b/Core/SaveState.h @@ -0,0 +1,33 @@ +// 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 "../Common/ChunkFile.h" + +struct SaveState +{ + // TODO: Better place for this? + static const int REVISION = 1; + + // Load the specified file into the current state. + static bool Load(std::string &filename); + // Save the current state to the specified file. + static bool Save(std::string &filename); + // For testing / automated tests. Runs a save state verification pass. + static bool Verify(); + + void DoState(PointerWrap &p); +}; \ No newline at end of file diff --git a/Qt/Core.pro b/Qt/Core.pro index 2a14f42b01..6c2cada922 100755 --- a/Qt/Core.pro +++ b/Qt/Core.pro @@ -121,6 +121,7 @@ SOURCES += ../Core/CPU.cpp \ # Core ../Core/MemMapFunctions.cpp \ ../Core/PSPLoaders.cpp \ ../Core/PSPMixer.cpp \ + ../Core/SaveState.cpp \ ../Core/System.cpp \ ../Core/Util/BlockAllocator.cpp \ ../Core/Util/PPGeDraw.cpp \ @@ -227,6 +228,7 @@ HEADERS += ../Core/CPU.h \ ../Core/MemMap.h \ ../Core/PSPLoaders.h \ ../Core/PSPMixer.h \ + ../Core/SaveState.h \ ../Core/System.h \ ../Core/Util/BlockAllocator.h \ ../Core/Util/PPGeDraw.h \ diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 409fffe706..22887307ff 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -95,6 +95,7 @@ LOCAL_SRC_FILES := \ $(SRC)/Core/PSPLoaders.cpp \ $(SRC)/Core/MemMap.cpp \ $(SRC)/Core/MemMapFunctions.cpp \ + $(SRC)/Core/SaveState.cpp \ $(SRC)/Core/System.cpp \ $(SRC)/Core/PSPMixer.cpp \ $(SRC)/Core/Debugger/Breakpoints.cpp \ From 2197d9698960201de02cd23657fcd02899c56ea1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 11:28:12 -0800 Subject: [PATCH 251/276] Run save state operations at next Advance(). Should take some question marks out of things. --- Core/HLE/HLE.h | 4 -- Core/HLE/sceKernel.cpp | 2 + Core/SaveState.cpp | 146 ++++++++++++++++++++++++++++++++++------- Core/SaveState.h | 24 ++++--- 4 files changed, 139 insertions(+), 37 deletions(-) diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index fb0eefa1be..09d5fc75cd 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -94,7 +94,3 @@ void WriteSyscall(const char *module, u32 nib, u32 address); void CallSyscall(u32 op); void ResolveSyscall(const char *moduleName, u32 nib, u32 address); -// Need to be able to save entire kernel state -int GetStateSize(); -void SaveState(u8 *ptr); -void LoadState(const u8 *ptr); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index da528027eb..20f3af0997 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -24,6 +24,7 @@ #include "../FileSystems/MetaFileSystem.h" #include "../PSPLoaders.h" #include "../../Core/CoreTiming.h" +#include "../../Core/SaveState.h" #include "../../Core/System.h" #include "../../GPU/GPUInterface.h" #include "../../GPU/GPUState.h" @@ -77,6 +78,7 @@ void __KernelInit() return; } + SaveState::Init(); __KernelMemoryInit(); __KernelThreadingInit(); __KernelMutexInit(); diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index bbf0e2328d..43d181bb9b 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -15,32 +15,130 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "../Common/StdMutex.h" +#include + #include "SaveState.h" -#include "MemMap.h" +#include "CoreTiming.h" #include "HLE/sceKernel.h" +#include "MemMap.h" -// TODO: Need a way to schedule via CoreTiming and actually run then. - -bool SaveState::Load(std::string &filename) +namespace SaveState { - SaveState state; - return CChunkFileReader::Load(filename, REVISION, state); + struct SaveStart + { + void DoState(PointerWrap &p); + }; + + enum OperationType + { + SAVESTATE_SAVE, + SAVESTATE_LOAD, + SAVESTATE_VERIFY, + }; + + struct Operation + { + Operation(OperationType t, std::string &f, Callback cb) + : type(t), filename(f), callback(cb) + { + } + + OperationType type; + std::string filename; + Callback callback; + }; + + static int timer; + static std::vector pending; + static std::recursive_mutex mutex; + + // This is where the magic happens. + void SaveStart::DoState(PointerWrap &p) + { + // This save state even saves its own state. + p.Do(timer); + p.DoMarker("SaveState"); + + Memory::DoState(p); + __KernelDoState(p); + } + + void Enqueue(SaveState::Operation op) + { + std::lock_guard guard(mutex); + pending.push_back(op); + + // Don't actually run it until next CoreTiming::Advance(). + // It's possible there might be a duplicate but it won't hurt us. + // TODO: If paused, just run, don't wait? + CoreTiming::ScheduleEvent_Threadsafe(0, timer); + } + + void Load(std::string &filename, Callback callback) + { + Enqueue(Operation(SAVESTATE_LOAD, filename, callback)); + } + + void Save(std::string &filename, Callback callback) + { + Enqueue(Operation(SAVESTATE_SAVE, filename, callback)); + } + + void Verify(Callback callback) + { + Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback)); + } + + std::vector Flush() + { + std::lock_guard guard(mutex); + std::vector copy = pending; + pending.clear(); + + return copy; + } + + void Process(u64 userdata, int cyclesLate) + { + std::vector operations = Flush(); + SaveStart state; + + for (size_t i = 0, n = operations.size(); i < n; ++i) + { + Operation &op = operations[i]; + bool result; + + switch (op.type) + { + case SAVESTATE_LOAD: + INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str()); + result = CChunkFileReader::Load(op.filename, REVISION, state); + break; + + case SAVESTATE_SAVE: + INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str()); + result = CChunkFileReader::Save(op.filename, REVISION, state); + break; + + case SAVESTATE_VERIFY: + INFO_LOG(COMMON, "Verifying save state system"); + result = CChunkFileReader::Verify(state); + break; + + default: + ERROR_LOG(COMMON, "Savestate failure: unknown operation type %d", op.type); + result = false; + break; + } + + if (op.callback != NULL) + op.callback(result); + } + } + + void Init() + { + timer = CoreTiming::RegisterEvent("SaveState", Process); + } } - -bool SaveState::Save(std::string &filename) -{ - SaveState state; - return CChunkFileReader::Save(filename, REVISION, state); -} - -bool SaveState::Verify() -{ - SaveState state; - return CChunkFileReader::Verify(state); -} - -void SaveState::DoState(PointerWrap &p) -{ - Memory::DoState(p); - __KernelDoState(p); -} \ No newline at end of file diff --git a/Core/SaveState.h b/Core/SaveState.h index f0edfcf921..411ad2f88c 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -16,18 +16,24 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "../Common/ChunkFile.h" +#include -struct SaveState +namespace SaveState { + typedef void (*Callback)(bool status); + // TODO: Better place for this? - static const int REVISION = 1; + const int REVISION = 1; - // Load the specified file into the current state. - static bool Load(std::string &filename); - // Save the current state to the specified file. - static bool Save(std::string &filename); - // For testing / automated tests. Runs a save state verification pass. - static bool Verify(); + void Init(); - void DoState(PointerWrap &p); + // Load the specified file into the current state (async.) + // Warning: callback will be called on a different thread. + void Load(std::string &filename, Callback callback = NULL); + // Save the current state to the specified file (async.) + // Warning: callback will be called on a different thread. + void Save(std::string &filename, Callback callback = NULL); + // For testing / automated tests. Runs a save state verification pass (async.) + // Warning: callback will be called on a different thread. + void Verify(Callback callback = NULL); }; \ No newline at end of file From 570e8c812bde68baa4f704282c534b7dd3d890c0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 11:32:34 -0800 Subject: [PATCH 252/276] Also handle save states while paused. --- Core/SaveState.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 43d181bb9b..5e2ac11242 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -19,6 +19,7 @@ #include #include "SaveState.h" +#include "Core.h" #include "CoreTiming.h" #include "HLE/sceKernel.h" #include "MemMap.h" @@ -64,6 +65,8 @@ namespace SaveState __KernelDoState(p); } + void Process(u64 userdata, int cyclesLate); + void Enqueue(SaveState::Operation op) { std::lock_guard guard(mutex); @@ -71,8 +74,13 @@ namespace SaveState // Don't actually run it until next CoreTiming::Advance(). // It's possible there might be a duplicate but it won't hurt us. - // TODO: If paused, just run, don't wait? - CoreTiming::ScheduleEvent_Threadsafe(0, timer); + if (Core_IsStepping()) + { + // Warning: this may run on a different thread. + Process(0, 0); + } + else + CoreTiming::ScheduleEvent_Threadsafe(0, timer); } void Load(std::string &filename, Callback callback) From fbe4fd396e40c691da26a33feabb27dfad78d866 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 11:58:15 -0800 Subject: [PATCH 253/276] Add a mechanism to restore event callback ptrs. Ugh, more duplicates. Maybe can find a good way to refactor. --- Core/CoreTiming.cpp | 24 ++++++++++++++++++++---- Core/CoreTiming.h | 2 ++ Core/HW/MemoryStick.cpp | 7 +++++++ Core/HW/MemoryStick.h | 2 ++ Core/SaveState.cpp | 6 ++++++ 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index b5d40610dd..b1999015f9 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -36,6 +36,11 @@ namespace CoreTiming struct EventType { + EventType() {} + + EventType(TimedCallback cb, const char *n) + : callback(cb), name(n) {} + TimedCallback callback; const char *name; }; @@ -125,13 +130,24 @@ void FreeTsEvent(Event* ev) int RegisterEvent(const char *name, TimedCallback callback) { - EventType type; - type.name = name; - type.callback = callback; - event_types.push_back(type); + event_types.push_back(EventType(callback, name)); return (int)event_types.size() - 1; } +void AntiCrashCallback(u64 userdata, int cyclesLate) +{ + ERROR_LOG(CPU, "Savestate broken: an unregistered event was called."); + Core_Halt("invalid timing events"); +} + +void RestoreEvent(int event_type, const char *name, TimedCallback callback) +{ + if (event_type >= event_types.size()) + event_types.resize(event_type + 1, EventType(AntiCrashCallback, "INVALID EVENT")); + + event_types[event_type] = EventType(callback, name); +} + void UnregisterAllEvents() { if (first) diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index f8883d9b35..c3ec4bc1b3 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -78,6 +78,8 @@ namespace CoreTiming // Returns the event_type identifier. int RegisterEvent(const char *name, TimedCallback callback); + // For save states. + void RestoreEvent(int event_type, const char *name, TimedCallback callback); void UnregisterAllEvents(); // userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, diff --git a/Core/HW/MemoryStick.cpp b/Core/HW/MemoryStick.cpp index 4d83e4783c..b2a746b0af 100644 --- a/Core/HW/MemoryStick.cpp +++ b/Core/HW/MemoryStick.cpp @@ -4,6 +4,13 @@ static MemStickState memStickState = PSP_MEMORYSTICK_STATE_DRIVER_READY; static MemStickFatState memStickFatState = PSP_FAT_MEMORYSTICK_STATE_ASSIGNED; +void MemoryStick_DoState(PointerWrap &p) +{ + p.Do(memStickState); + p.Do(memStickFatState); + p.DoMarker("MemoryStick"); +} + MemStickState MemoryStick_State() { return memStickState; diff --git a/Core/HW/MemoryStick.h b/Core/HW/MemoryStick.h index 1ccd9b64fa..fbd42b827b 100644 --- a/Core/HW/MemoryStick.h +++ b/Core/HW/MemoryStick.h @@ -1,4 +1,5 @@ #include "../../Globals.h" +#include "../../Common/ChunkFile.h" // mscmhc0 states enum MemStickState { @@ -14,6 +15,7 @@ enum MemStickFatState { PSP_FAT_MEMORYSTICK_STATE_ASSIGNED = 1, }; +void MemoryStick_DoState(PointerWrap &p); MemStickState MemoryStick_State(); MemStickFatState MemoryStick_FatState(); diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 5e2ac11242..ce70a40df0 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -22,6 +22,7 @@ #include "Core.h" #include "CoreTiming.h" #include "HLE/sceKernel.h" +#include "HW/MemoryStick.h" #include "MemMap.h" namespace SaveState @@ -57,11 +58,16 @@ namespace SaveState // This is where the magic happens. void SaveStart::DoState(PointerWrap &p) { + // Gotta do CoreTiming first since we'll restore into it. + // TODO CoreTiming + // This save state even saves its own state. p.Do(timer); + CoreTiming::RestoreEvent(timer, "SaveState", Process); p.DoMarker("SaveState"); Memory::DoState(p); + MemoryStick_DoState(p); __KernelDoState(p); } From 91d727a65a338e34ed051cfaa6af7c32ea2dcdac Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 13:08:58 -0800 Subject: [PATCH 254/276] Add CoreTiming to save states. I hope DoLinkedList works, seems like it should. --- Core/CoreTiming.cpp | 36 ++++++++++++++++++++++++++++-------- Core/CoreTiming.h | 6 +++++- Core/SaveState.cpp | 8 ++++---- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index b1999015f9..31b9bbb0ad 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -24,6 +24,7 @@ #include "CoreTiming.h" #include "Core.h" #include "HLE/sceKernelThread.h" +#include "../Common/ChunkFile.h" int CPU_HZ = 222000000; @@ -55,12 +56,6 @@ struct BaseEvent // Event *next; }; -template -struct LinkedListItem : public T -{ - LinkedListItem *next; -}; - typedef LinkedListItem Event; Event *first; @@ -79,6 +74,7 @@ s64 idledCycles; static std::recursive_mutex externalEventSection; +// Warning: not included in save state. void (*advanceCallback)(int cyclesExecuted) = NULL; void SetClockFrequencyMHz(int cpuMhz) @@ -140,9 +136,9 @@ void AntiCrashCallback(u64 userdata, int cyclesLate) Core_Halt("invalid timing events"); } -void RestoreEvent(int event_type, const char *name, TimedCallback callback) +void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback) { - if (event_type >= event_types.size()) + if (event_type >= (int) event_types.size()) event_types.resize(event_type + 1, EventType(AntiCrashCallback, "INVALID EVENT")); event_types[event_type] = EventType(callback, name); @@ -311,6 +307,7 @@ u64 UnscheduleEvent(int event_type, u64 userdata) return result; } +// Warning: not included in save state. void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted)) { advanceCallback = callback; @@ -546,4 +543,27 @@ std::string GetScheduledEventsSummary() return text; } +void Event_DoState(PointerWrap &p, BaseEvent *ev) +{ + p.Do(*ev); +} + +void DoState(PointerWrap &p) +{ + size_t n = event_types.size(); + p.Do(n); + // These (should) be filled in later by the modules. + event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT")); + + p.DoLinkedList(first, (Event **) NULL); + p.DoLinkedList(tsFirst, &tsLast); + + p.Do(CPU_HZ); + p.Do(downcount); + p.Do(slicelength); + p.Do(globalTimer); + p.Do(idledCycles); + p.DoMarker("CoreTiming"); +} + } // namespace diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index c3ec4bc1b3..e5aa8f8772 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -32,6 +32,7 @@ // ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever") #include "../Globals.h" +#include "../Common/ChunkFile.h" #include @@ -79,7 +80,7 @@ namespace CoreTiming // Returns the event_type identifier. int RegisterEvent(const char *name, TimedCallback callback); // For save states. - void RestoreEvent(int event_type, const char *name, TimedCallback callback); + void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback); void UnregisterAllEvents(); // userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, @@ -105,10 +106,13 @@ namespace CoreTiming void LogPendingEvents(); + // Warning: not included in save states. void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted)); std::string GetScheduledEventsSummary(); + void DoState(PointerWrap &p); + void SetClockFrequencyMHz(int cpuMhz); int GetClockFrequencyMHz(); extern int downcount; diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index ce70a40df0..bbf8717b9f 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -55,15 +55,17 @@ namespace SaveState static std::vector pending; static std::recursive_mutex mutex; + void Process(u64 userdata, int cyclesLate); + // This is where the magic happens. void SaveStart::DoState(PointerWrap &p) { // Gotta do CoreTiming first since we'll restore into it. - // TODO CoreTiming + CoreTiming::DoState(p); // This save state even saves its own state. p.Do(timer); - CoreTiming::RestoreEvent(timer, "SaveState", Process); + CoreTiming::RestoreRegisterEvent(timer, "SaveState", Process); p.DoMarker("SaveState"); Memory::DoState(p); @@ -71,8 +73,6 @@ namespace SaveState __KernelDoState(p); } - void Process(u64 userdata, int cyclesLate); - void Enqueue(SaveState::Operation op) { std::lock_guard guard(mutex); From 3ed2045f6b312102db2bb63069fbd7d353df0ec7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 14:21:39 -0800 Subject: [PATCH 255/276] Add state saving to tertiary kernel modules. --- Common/ChunkFile.h | 37 +++++++++++++++++++++++++++++++++ Core/HLE/sceKernel.cpp | 21 +++++++++++-------- Core/HLE/sceKernelAlarm.cpp | 7 +++++++ Core/HLE/sceKernelAlarm.h | 1 + Core/HLE/sceKernelEventFlag.cpp | 9 +++++++- Core/HLE/sceKernelEventFlag.h | 1 + Core/HLE/sceKernelMbx.cpp | 9 +++++++- Core/HLE/sceKernelMbx.h | 1 + Core/HLE/sceKernelMemory.cpp | 7 +++++++ Core/HLE/sceKernelMemory.h | 1 + Core/HLE/sceKernelModule.cpp | 6 ++++++ Core/HLE/sceKernelModule.h | 1 + Core/HLE/sceKernelMutex.cpp | 14 +++++++++++-- Core/HLE/sceKernelMutex.h | 1 + Core/HLE/sceKernelSemaphore.cpp | 9 +++++++- Core/HLE/sceKernelSemaphore.h | 1 + 16 files changed, 112 insertions(+), 14 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index eda388211e..c6dd5d6de0 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -114,6 +114,43 @@ public: } } + template + void Do(std::multimap &x) + { + unsigned int number = (unsigned int)x.size(); + Do(number); + switch (mode) { + case MODE_READ: + { + x.clear(); + while (number > 0) + { + K first; + Do(first); + T second; + Do(second); + x.insert(std::make_pair(first, second)); + --number; + } + } + break; + case MODE_WRITE: + case MODE_MEASURE: + case MODE_VERIFY: + { + typename std::multimap::iterator itr = x.begin(); + while (number > 0) + { + Do(itr->first); + Do(itr->second); + --number; + ++itr; + } + } + break; + } + } + // Store vectors. template void Do(std::vector &x) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 20f3af0997..67f6b073db 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -59,8 +59,6 @@ #include "../Util/PPGeDraw.h" -extern MetaFileSystem pspFileSystem; - /* 17: [MIPS32 R4K 00000000 ]: Loader: Type: 1 Vaddr: 00000000 Filesz: 2856816 Memsz: 2856816 18: [MIPS32 R4K 00000000 ]: Loader: Loadable Segment Copied to 0898dab0, size 002b9770 @@ -69,6 +67,7 @@ extern MetaFileSystem pspFileSystem; */ static bool kernelRunning = false; +KernelObjectPool kernelObjects; void __KernelInit() { @@ -140,13 +139,19 @@ void __KernelShutdown() void __KernelDoState(PointerWrap &p) { + p.Do(kernelRunning); kernelObjects.DoState(p); p.DoMarker("KernelObjects"); - // TODO - // modules - // core timing - // memstick - // filesystem + + // TODO: Put these in the correct order... + __KernelAlarmDoState(p); + __KernelEventFlagDoState(p); + __KernelMbxDoState(p); + __KernelMemoryDoState(p); + __KernelModuleDoState(p); + __KernelMutexDoState(p); + __KernelSemaDoState(p); + // TODO: more modules } bool __KernelIsRunning() { @@ -232,8 +237,6 @@ void sceKernelDcacheWritebackInvalidateAll() gpu->InvalidateCache(0, -1); } -KernelObjectPool kernelObjects; - KernelObjectPool::KernelObjectPool() { memset(occupied, 0, sizeof(bool)*maxCount); diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index ea833860ec..baf4ddbf38 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -111,6 +111,13 @@ void __KernelAlarmInit() alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); } +void __KernelAlarmDoState(PointerWrap &p) +{ + p.Do(alarmTimer); + CoreTiming::RestoreRegisterEvent(alarmTimer, "Alarm", __KernelTriggerAlarm); + p.DoMarker("sceKernelAlarm"); +} + KernelObject *__KernelAlarmObject() { // Default object to load from state. diff --git a/Core/HLE/sceKernelAlarm.h b/Core/HLE/sceKernelAlarm.h index 24cc866e37..4b286eb87a 100644 --- a/Core/HLE/sceKernelAlarm.h +++ b/Core/HLE/sceKernelAlarm.h @@ -23,4 +23,5 @@ int sceKernelCancelAlarm(SceUID uid); int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); void __KernelAlarmInit(); +void __KernelAlarmDoState(PointerWrap &p); KernelObject *__KernelAlarmObject(); diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index f0e5e16034..80471c4c4d 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -101,7 +101,14 @@ int eventFlagWaitTimer = 0; void __KernelEventFlagInit() { - eventFlagWaitTimer = CoreTiming::RegisterEvent("EventFlagTimeout", &__KernelEventFlagTimeout); + eventFlagWaitTimer = CoreTiming::RegisterEvent("EventFlagTimeout", __KernelEventFlagTimeout); +} + +void __KernelEventFlagDoState(PointerWrap &p) +{ + p.Do(eventFlagWaitTimer); + CoreTiming::RestoreRegisterEvent(eventFlagWaitTimer, "EventFlagTimeout", __KernelEventFlagTimeout); + p.DoMarker("sceKernelEventFlag"); } KernelObject *__KernelEventFlagObject() diff --git a/Core/HLE/sceKernelEventFlag.h b/Core/HLE/sceKernelEventFlag.h index 2eb1c659ba..151efa25f7 100644 --- a/Core/HLE/sceKernelEventFlag.h +++ b/Core/HLE/sceKernelEventFlag.h @@ -28,4 +28,5 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr); u32 sceKernelCancelEventFlag(SceUID uid, u32 pattern, u32 numWaitThreadsPtr); void __KernelEventFlagInit(); +void __KernelEventFlagDoState(PointerWrap &p); KernelObject *__KernelEventFlagObject(); diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index 3ae6ae4f04..34aea59532 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -167,7 +167,14 @@ struct Mbx : public KernelObject void __KernelMbxInit() { - mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", &__KernelMbxTimeout); + mbxWaitTimer = CoreTiming::RegisterEvent("MbxTimeout", __KernelMbxTimeout); +} + +void __KernelMbxDoState(PointerWrap &p) +{ + p.Do(mbxWaitTimer); + CoreTiming::RestoreRegisterEvent(mbxWaitTimer, "MbxTimeout", __KernelMbxTimeout); + p.DoMarker("sceKernelMbx"); } KernelObject *__KernelMbxObject() diff --git a/Core/HLE/sceKernelMbx.h b/Core/HLE/sceKernelMbx.h index b0fb25e952..c171461a8f 100644 --- a/Core/HLE/sceKernelMbx.h +++ b/Core/HLE/sceKernelMbx.h @@ -34,4 +34,5 @@ int sceKernelCancelReceiveMbx(SceUID id, u32 numWaitingThreadsAddr); int sceKernelReferMbxStatus(SceUID id, u32 infoAddr); void __KernelMbxInit(); +void __KernelMbxDoState(PointerWrap &p); KernelObject *__KernelMbxObject(); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 807e74a2e1..97ce91136b 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -135,6 +135,13 @@ void __KernelMemoryInit() INFO_LOG(HLE, "Kernel and user memory pools initialized"); } +void __KernelMemoryDoState(PointerWrap &p) +{ + kernelMemory.DoState(p); + userMemory.DoState(p); + p.DoMarker("sceKernelMemory"); +} + void __KernelMemoryShutdown() { INFO_LOG(HLE,"Shutting down user memory pool: "); diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index cc5334ae89..0b6602d756 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -30,6 +30,7 @@ extern BlockAllocator userMemory; extern BlockAllocator kernelMemory; void __KernelMemoryInit(); +void __KernelMemoryDoState(PointerWrap &p); void __KernelMemoryShutdown(); KernelObject *__KernelMemoryFPLObject(); KernelObject *__KernelMemoryVPLObject(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 1f7b0c050c..d35e5d5138 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -172,6 +172,12 @@ static SceUID mainModuleID; // hack // STATE END ////////////////////////////////////////////////////////////////////////// +void __KernelModuleDoState(PointerWrap &p) +{ + p.Do(mainModuleID); + p.DoMarker("sceKernelModule"); +} + Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string) { Module *module = new Module; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 18e3d5f036..732bd43173 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -21,6 +21,7 @@ #include "HLE.h" KernelObject *__KernelModuleObject(); +void __KernelModuleDoState(PointerWrap &p); u32 __KernelGetModuleGP(SceUID module); bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std::string *error_string); diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index c0778031c7..a6243fff08 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -131,12 +131,22 @@ static MutexMap mutexHeldLocks; void __KernelMutexInit() { - mutexWaitTimer = CoreTiming::RegisterEvent("MutexTimeout", &__KernelMutexTimeout); - lwMutexWaitTimer = CoreTiming::RegisterEvent("LwMutexTimeout", &__KernelLwMutexTimeout); + mutexWaitTimer = CoreTiming::RegisterEvent("MutexTimeout", __KernelMutexTimeout); + lwMutexWaitTimer = CoreTiming::RegisterEvent("LwMutexTimeout", __KernelLwMutexTimeout); __KernelListenThreadEnd(&__KernelMutexThreadEnd); } +void __KernelMutexDoState(PointerWrap &p) +{ + p.Do(mutexWaitTimer); + CoreTiming::RestoreRegisterEvent(mutexWaitTimer, "MutexTimeout", __KernelMutexTimeout); + p.Do(lwMutexWaitTimer); + CoreTiming::RestoreRegisterEvent(lwMutexWaitTimer, "LwMutexTimeout", __KernelLwMutexTimeout); + p.Do(mutexHeldLocks); + p.DoMarker("sceKernelMutex"); +} + KernelObject *__KernelMutexObject() { return new Mutex; diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index 5db1f3b4d5..18eeb4fafb 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -37,6 +37,7 @@ void __KernelLwMutexTimeout(u64 userdata, int cyclesLate); void __KernelMutexThreadEnd(SceUID thread); void __KernelMutexInit(); +void __KernelMutexDoState(PointerWrap &p); void __KernelMutexShutdown(); KernelObject *__KernelMutexObject(); KernelObject *__KernelLwMutexObject(); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 0572a8d70d..6e213ff31d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -72,7 +72,14 @@ static int semaWaitTimer = 0; void __KernelSemaInit() { - semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", &__KernelSemaTimeout); + semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", __KernelSemaTimeout); +} + +void __KernelSemaDoState(PointerWrap &p) +{ + p.Do(semaWaitTimer); + CoreTiming::RestoreRegisterEvent(semaWaitTimer, "SemaphoreTimeout", __KernelSemaTimeout); + p.DoMarker("sceKernelSema"); } KernelObject *__KernelSemaphoreObject() diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index f816f97e41..14df34cbed 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -29,4 +29,5 @@ int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); void __KernelSemaTimeout(u64 userdata, int cycleslate); void __KernelSemaInit(); +void __KernelSemaDoState(PointerWrap &p); KernelObject *__KernelSemaphoreObject(); From db787d266d557c87ea02d27faebca95c61818ff2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 15:56:46 -0800 Subject: [PATCH 256/276] Require interrupt handlers to be registered. This allows it to be save stated sanely. --- Core/HLE/sceKernel.cpp | 19 ++-- Core/HLE/sceKernelAlarm.cpp | 26 +++++- Core/HLE/sceKernelInterrupt.cpp | 159 +++++++++++++++++++++++++------- Core/HLE/sceKernelInterrupt.h | 42 +++++---- 4 files changed, 183 insertions(+), 63 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 67f6b073db..76e690465c 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -78,18 +78,18 @@ void __KernelInit() } SaveState::Init(); + __InterruptsInit(); __KernelMemoryInit(); __KernelThreadingInit(); - __KernelMutexInit(); - __KernelSemaInit(); __KernelAlarmInit(); __KernelEventFlagInit(); __KernelMbxInit(); + __KernelMutexInit(); + __KernelSemaInit(); __IoInit(); __AudioInit(); __SasInit(); __DisplayInit(); - __InterruptsInit(); __GeInit(); __PowerInit(); __UtilityInit(); @@ -126,10 +126,10 @@ void __KernelShutdown() __DisplayShutdown(); __AudioShutdown(); __IoShutdown(); - __InterruptsShutdown(); __KernelMutexShutdown(); __KernelThreadingShutdown(); __KernelMemoryShutdown(); + __InterruptsShutdown(); CoreTiming::ClearPendingEvents(); CoreTiming::UnregisterAllEvents(); @@ -144,14 +144,17 @@ void __KernelDoState(PointerWrap &p) p.DoMarker("KernelObjects"); // TODO: Put these in the correct order... + __InterruptsDoState(p); + __KernelMemoryDoState(p); + // TODO: __KernelThreadingDoState(p); __KernelAlarmDoState(p); __KernelEventFlagDoState(p); __KernelMbxDoState(p); - __KernelMemoryDoState(p); __KernelModuleDoState(p); __KernelMutexDoState(p); __KernelSemaDoState(p); - // TODO: more modules + // TODO: non-kernel modules + // TODO: PPGe } bool __KernelIsRunning() { @@ -328,7 +331,9 @@ void KernelObjectPool::DoState(PointerWrap &p) if (_maxCount != maxCount) ERROR_LOG(HLE, "Unable to load state: different kernel object storage."); - // Assumption: on load, we've already cleared. + if (p.mode == p.MODE_READ) + kernelObjects.Clear(); + p.DoArray(occupied, maxCount); for (int i = 0; i < maxCount; ++i) { diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index baf4ddbf38..bb29e077e6 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -52,7 +52,12 @@ void __KernelScheduleAlarm(Alarm *alarm, u64 ticks); class AlarmIntrHandler : public SubIntrHandler { public: - AlarmIntrHandler(Alarm *alarm) + static SubIntrHandler *Create() + { + return new AlarmIntrHandler(); + } + + void setAlarm(Alarm *alarm) { alarmID = alarm->GetUID(); handlerAddress = alarm->alm.handlerPtr; @@ -87,10 +92,17 @@ public: // Delete the alarm if it's not rescheduled. kernelObjects.Destroy(alarmID); - __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, alarmID); + __ReleaseSubIntrHandler(PSP_SYSTIMER0_INTR, alarmID); } } + virtual void DoState(PointerWrap &p) + { + SubIntrHandler::DoState(p); + p.Do(alarmID); + p.DoMarker("AlarmIntrHandler"); + } + SceUID alarmID; }; @@ -109,6 +121,7 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) void __KernelAlarmInit() { alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); + __RegisterSubIntrCreator(PSP_SYSTIMER0_INTR, AlarmIntrHandler::Create); } void __KernelAlarmDoState(PointerWrap &p) @@ -142,10 +155,15 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) alarm->alm.handlerPtr = handlerPtr; alarm->alm.commonPtr = commonPtr; - u32 error = __RegisterSubInterruptHandler(PSP_SYSTIMER0_INTR, uid, new AlarmIntrHandler(alarm)); + u32 error; + AlarmIntrHandler *handler = (AlarmIntrHandler *) __RegisterSubIntrHandler(PSP_SYSTIMER0_INTR, uid, error); if (error != 0) + { + kernelObjects.Destroy(uid); return error; + } + handler->setAlarm(alarm); __KernelScheduleAlarm(alarm, ticks); return uid; } @@ -174,7 +192,7 @@ int sceKernelCancelAlarm(SceUID uid) DEBUG_LOG(HLE, "sceKernelCancelAlarm(%08x)", uid); CoreTiming::UnscheduleEvent(alarmTimer, uid); - __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, uid); + __ReleaseSubIntrHandler(PSP_SYSTIMER0_INTR, uid); return kernelObjects.Destroy(uid); } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index bc00c82254..445546f349 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -28,11 +28,6 @@ #include "sceKernelInterrupt.h" #include "sceKernelMutex.h" -struct Interrupt -{ - PSPInterrupt intno; -}; - void __DisableInterrupts(); void __EnableInterrupts(); bool __InterruptsEnabled(); @@ -92,9 +87,21 @@ void sceKernelCpuResumeIntrWithSync(u32 enable) class IntrHandler { public: - void add(int subIntrNum, SubIntrHandler *handler) + IntrHandler() + : subIntrCreator(NULL) { + } + + SubIntrHandler *add(int subIntrNum) + { + SubIntrHandler *handler; + if (subIntrCreator != NULL) + handler = subIntrCreator(); + else + handler = new SubIntrHandler(); + subIntrHandlers[subIntrNum] = handler; + return handler; } void remove(int subIntrNum) { @@ -113,8 +120,7 @@ public: if (has(subIntrNum)) return subIntrHandlers[subIntrNum]; else - return 0; - // what to do, what to do... + return NULL; } void clear() { @@ -146,7 +152,49 @@ public: } } + void setCreator(SubIntrCreator creator) + { + subIntrCreator = creator; + } + + void DoState(PointerWrap &p) + { + // We assume that the same creator has already been registered. + bool hasCreator = subIntrCreator != NULL; + p.Do(hasCreator); + if (hasCreator != (subIntrCreator != NULL)) + { + ERROR_LOG(HLE, "Savestate failure: incompatible sub interrupt handler."); + return; + } + + size_t n = subIntrHandlers.size(); + p.Do(n); + + if (p.mode == p.MODE_READ) + { + clear(); + for (size_t i = 0; i < n; ++i) + { + int subIntrNum; + p.Do(subIntrNum); + SubIntrHandler *handler = add(subIntrNum); + handler->DoState(p); + } + } + else + { + std::map::iterator it, end; + for (it = subIntrHandlers.begin(), end = subIntrHandlers.end(); it != end; ++it) + { + p.Do(it->first); + it->second->DoState(p); + } + } + } + private: + SubIntrCreator subIntrCreator; std::map subIntrHandlers; }; @@ -157,6 +205,13 @@ public: void restore(); void clear(); + void DoState(PointerWrap &p) + { + p.Do(insideInterrupt); + p.Do(savedCpu); + p.DoMarker("InterruptState"); + } + bool insideInterrupt; ThreadContext savedCpu; // Action afterInterruptAction; @@ -181,6 +236,25 @@ void __InterruptsInit() intState.clear(); } +void __InterruptsDoState(PointerWrap &p) +{ + int numInterrupts = PSP_NUMBER_INTERRUPTS; + p.Do(numInterrupts); + if (numInterrupts != PSP_NUMBER_INTERRUPTS) + { + ERROR_LOG(HLE, "Savestate failure: wrong number of interrupts, can't load."); + return; + } + + intState.DoState(p); + for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) + intrHandlers[i].DoState(p); + p.Do(pendingInterrupts, PendingInterrupt(0, 0)); + p.Do(interruptsEnabled); + p.Do(inInterrupt); + p.DoMarker("sceKernelInterrupt"); +} + void __InterruptsShutdown() { for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) @@ -238,25 +312,16 @@ void SubIntrHandler::queueUp() { if (!enabled) return; - PendingInterrupt pend; - pend.handler = this; - pend.hasArg = false; - pend.intr = intrNumber; - pend.subintr = number; - pendingInterrupts.push_back(pend); + + pendingInterrupts.push_back(PendingInterrupt(intrNumber, number)); }; void SubIntrHandler::queueUpWithArg(int arg) { if (!enabled) return; - PendingInterrupt pend; - pend.handler = this; - pend.arg = arg; - pend.hasArg = true; - pend.intr = intrNumber; - pend.subintr = number; - pendingInterrupts.push_back(pend); + + pendingInterrupts.push_back(PendingInterrupt(intrNumber, number, arg)); } void SubIntrHandler::copyArgsToCPU(const PendingInterrupt &pend) @@ -278,6 +343,7 @@ bool __RunOnePendingInterrupt() return false; } // Can easily prioritize between different kinds of interrupts if necessary. +retry: if (pendingInterrupts.size()) { // If we came from CoreTiming::Advance(), we might've come from a waiting thread's callback. @@ -285,8 +351,16 @@ bool __RunOnePendingInterrupt() __KernelSwitchOffThread("interrupt"); PendingInterrupt pend = pendingInterrupts.front(); + SubIntrHandler *handler = intrHandlers[pend.intr].get(pend.subintr); + if (handler == NULL) + { + WARN_LOG(HLE, "Ignoring interrupt, already been released."); + pendingInterrupts.pop_front(); + goto retry; + } + intState.save(); - pend.handler->copyArgsToCPU(pend); + handler->copyArgsToCPU(pend); currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); inInterrupt = true; @@ -340,7 +414,12 @@ void __KernelReturnFromInterrupt() // This is what we just ran. PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); - pend.handler->handleResult(currentMIPS->r[MIPS_REG_V0]); + + SubIntrHandler *handler = intrHandlers[pend.intr].get(pend.subintr); + if (handler != NULL) + handler->handleResult(currentMIPS->r[MIPS_REG_V0]); + else + ERROR_LOG(HLE, "Interrupt released itself? Should not happen."); // Restore context after running the interrupt. intState.restore(); @@ -351,15 +430,21 @@ void __KernelReturnFromInterrupt() __KernelReSchedule("return from interrupt"); } -u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler) +void __RegisterSubIntrCreator(u32 intrNumber, SubIntrCreator creator) { - subIntrHandler->number = subIntrNumber; - subIntrHandler->intrNumber = intrNumber; - intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); - return 0; + intrHandlers[intrNumber].setCreator(creator); } -u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber) +SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 &error) +{ + SubIntrHandler *subIntrHandler = intrHandlers[intrNumber].add(subIntrNumber); + subIntrHandler->number = subIntrNumber; + subIntrHandler->intrNumber = intrNumber; + error = 0; + return subIntrHandler; +} + +u32 __ReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) { if (!intrHandlers[intrNumber].has(subIntrNumber)) return -1; @@ -383,11 +468,15 @@ u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handl if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - SubIntrHandler *subIntrHandler = new SubIntrHandler(); - subIntrHandler->enabled = false; - subIntrHandler->handlerAddress = handler; - subIntrHandler->handlerArg = handlerArg; - return __RegisterSubInterruptHandler(intrNumber, subIntrNumber, subIntrHandler); + u32 error; + SubIntrHandler *subIntrHandler = __RegisterSubIntrHandler(intrNumber, subIntrNumber, error); + if (subIntrHandler) + { + subIntrHandler->enabled = false; + subIntrHandler->handlerAddress = handler; + subIntrHandler->handlerArg = handlerArg; + } + return error; } u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) @@ -397,7 +486,7 @@ u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber) if (intrNumber >= PSP_NUMBER_INTERRUPTS) return -1; - return __ReleaseSubInterruptHandler(intrNumber, subIntrNumber); + return __ReleaseSubIntrHandler(intrNumber, subIntrNumber); } u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber) diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index af57d6f3f4..3a298b955b 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -17,6 +17,8 @@ #pragma once +#include "../../Common/ChunkFile.h" + enum PSPInterrupt { PSP_GPIO_INTR = 4, PSP_ATA_INTR = 5, @@ -63,36 +65,38 @@ enum PSPInterruptTriggerType { PSP_INTR_ONLY_IF_ENABLED = 0x2, }; -class AllegrexInterruptHandler; - struct PendingInterrupt { - AllegrexInterruptHandler *handler; + PendingInterrupt(int intr_, int subintr_) + : intr(intr_), subintr(subintr_), hasArg(false) {} + PendingInterrupt(int intr_, int subintr_, int arg_) + : intr(intr_), subintr(subintr_), hasArg(true), arg(arg_) {} + int arg; bool hasArg; int intr; int subintr; }; - -class AllegrexInterruptHandler -{ -public: - virtual ~AllegrexInterruptHandler() {} - virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; - virtual void queueUp() = 0; - virtual void queueUpWithArg(int arg) = 0; - virtual void handleResult(int result) = 0; -}; - -class SubIntrHandler : public AllegrexInterruptHandler +class SubIntrHandler { public: SubIntrHandler() {} + virtual ~SubIntrHandler() {} virtual void queueUp(); virtual void queueUpWithArg(int arg); virtual void copyArgsToCPU(const PendingInterrupt &pend); virtual void handleResult(int result) {} + virtual void DoState(PointerWrap &p) + { + p.Do(enabled); + p.Do(intrNumber); + p.Do(number); + p.Do(handlerAddress); + p.Do(handlerArg); + p.DoMarker("SubIntrHandler"); + } + bool enabled; int intrNumber; int number; @@ -100,16 +104,20 @@ public: u32 handlerArg; }; +typedef SubIntrHandler *(*SubIntrCreator)(); + bool __IsInInterrupt(); void __InterruptsInit(); +void __InterruptsDoState(PointerWrap &p); void __InterruptsShutdown(); void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1); void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int arg); // For GE "callbacks" bool __RunOnePendingInterrupt(); void __KernelReturnFromInterrupt(); -u32 __RegisterSubInterruptHandler(u32 intrNumber, u32 subIntrNumber, SubIntrHandler *subIntrHandler); -u32 __ReleaseSubInterruptHandler(u32 intrNumber, u32 subIntrNumber); +void __RegisterSubIntrCreator(u32 intrNumber, SubIntrCreator creator); +SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 &error); +u32 __ReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber); u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber); From f5dd7f03e8baca183f460072a70bb5ba6ed9586c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 17:43:44 -0800 Subject: [PATCH 257/276] Change threadqueue and currentThread to be SceUIDs. hmm, kind of a big change. Tried to add some checks to be safe. --- Core/HLE/sceKernelThread.cpp | 228 ++++++++++++++++++++++------------- 1 file changed, 141 insertions(+), 87 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 816c3f4a2c..66a9172675 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -368,12 +368,12 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force); //STATE BEGIN ////////////////////////////////////////////////////////////////////////// int g_inCbCount = 0; -Thread *currentThread; +SceUID currentThread; u32 idleThreadHackAddr; u32 threadReturnHackAddr; u32 cbReturnHackAddr; u32 intReturnHackAddr; -std::vector threadqueue; //Change to SceUID +std::vector threadqueue; std::vector threadEndListeners; SceUID threadIdleID[2]; @@ -395,7 +395,11 @@ SceUID curModule; // TODO: Should move to this wrapper so we can keep the current thread as a SceUID instead // of a dangerous raw pointer. Thread *__GetCurrentThread() { - return currentThread; + u32 error; + if (currentThread != 0) + return kernelObjects.Get(currentThread, error); + else + return NULL; } u32 __KernelMipsCallReturnAddress() @@ -492,7 +496,7 @@ bool __KernelSwitchOffThread(const char *reason) if (!reason) reason = "switch off thread"; - SceUID threadID = currentThread->GetUID(); + SceUID threadID = currentThread; if (threadID != threadIdleID[0] && threadID != threadIdleID[1]) { @@ -666,7 +670,7 @@ u32 sceKernelGetThreadmanIdList(u32 type, u32 readBufPtr, u32 readBufSize, u32 i for (size_t i = 0; i < std::min((size_t)readBufSize, threadqueue.size()); i++) { - Memory::Write_U32(threadqueue[i]->GetUID(), readBufPtr + i * 4); + Memory::Write_U32(threadqueue[i], readBufPtr + i * 4); } Memory::Write_U32(threadqueue.size(), idCountPtr); return 0; @@ -762,10 +766,11 @@ bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool { bool doneAnything = false; - for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) + u32 error; + for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { - Thread *t = *iter; - if (t->isWaitingFor(type, id)) + Thread *t = kernelObjects.Get(*iter, error); + if (t && t->isWaitingFor(type, id)) { // This thread was waiting for the triggered object. t->resumeFromWait(); @@ -805,12 +810,13 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time if (g_inCbCount > 0) WARN_LOG(HLE, "UNTESTED - waiting within a callback, probably bad mojo."); - currentThread->nt.waitID = waitID; - currentThread->nt.waitType = type; - __KernelChangeThreadState(currentThread, THREADSTATUS_WAIT); - currentThread->nt.numReleases++; - currentThread->waitInfo.waitValue = waitValue; - currentThread->waitInfo.timeoutPtr = timeoutPtr; + Thread *thread = __GetCurrentThread(); + thread->nt.waitID = waitID; + thread->nt.waitType = type; + __KernelChangeThreadState(thread, THREADSTATUS_WAIT); + thread->nt.numReleases++; + thread->waitInfo.waitValue = waitValue; + thread->waitInfo.timeoutPtr = timeoutPtr; // TODO: Remove this once all callers are cleaned up. RETURN(0); //pretend all went OK @@ -843,7 +849,7 @@ void __KernelRemoveFromThreadQueue(Thread *t) { for (size_t i = 0; i < threadqueue.size(); i++) { - if (threadqueue[i] == t) + if (threadqueue[i] == t->GetUID()) { DEBUG_LOG(HLE, "Deleted thread %p (%i) from thread queue", t, t->GetUID()); threadqueue.erase(threadqueue.begin() + i); @@ -869,12 +875,13 @@ Thread *__KernelNextThread() { } } + u32 error; for (size_t i = 0; i < threadqueue.size(); i++) { next = (next + 1) % threadqueue.size(); - Thread *t = threadqueue[next]; - if (t->nt.currentPriority < prio) + Thread *t = kernelObjects.Get(threadqueue[next], error); + if (t && t->nt.currentPriority < prio) { if (t->nt.status & THREADSTATUS_READY) { @@ -885,7 +892,7 @@ Thread *__KernelNextThread() { } if (bestthread != -1) - return threadqueue[bestthread]; + return kernelObjects.Get(threadqueue[bestthread], error); else return 0; } @@ -933,14 +940,14 @@ retry: void __KernelReSchedule(bool doCallbacks, const char *reason) { - Thread *thread = currentThread; + Thread *thread = __GetCurrentThread(); if (doCallbacks) { if (thread) thread->isProcessingCallbacks = doCallbacks; } __KernelReSchedule(reason); - if (doCallbacks && thread != NULL && thread == currentThread) { + if (doCallbacks && thread != NULL && thread->GetUID() == currentThread) { if (thread->isRunning()) { thread->isProcessingCallbacks = false; } @@ -1020,7 +1027,7 @@ Thread *__KernelCreateThread(SceUID &id, SceUID moduleId, const char *name, u32 Thread *t = new Thread; id = kernelObjects.Create(t); - threadqueue.push_back(t); + threadqueue.push_back(id); memset(&t->nt, 0xCD, sizeof(t->nt)); @@ -1052,13 +1059,15 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr curModule = moduleID; //grab mips regs SceUID id; - currentThread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr); - __KernelResetThread(currentThread); - currentThread->nt.status = THREADSTATUS_READY; // do not schedule + Thread *thread = __KernelCreateThread(id, moduleID, "root", currentMIPS->pc, prio, stacksize, attr); + __KernelResetThread(thread); - strcpy(currentThread->nt.name, "root"); + currentThread = id; + thread->nt.status = THREADSTATUS_READY; // do not schedule - __KernelLoadContext(¤tThread->context); + strcpy(thread->nt.name, "root"); + + __KernelLoadContext(&thread->context); mipsr4k.r[MIPS_REG_A0] = args; mipsr4k.r[MIPS_REG_SP] -= 256; u32 location = mipsr4k.r[MIPS_REG_SP]; @@ -1082,7 +1091,7 @@ int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stack // int sceKernelStartThread(SceUID threadToStartID, SceSize argSize, void *argBlock) int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) { - if (threadToStartID != currentThread->GetUID()) + if (threadToStartID != currentThread) { u32 error; Thread *startThread = kernelObjects.Get(threadToStartID, error); @@ -1144,7 +1153,7 @@ void sceKernelGetThreadStackFreeSize() INFO_LOG(HLE,"sceKernelGetThreadStackFreeSize(%i)", threadID); if (threadID == 0) - thread = currentThread; + thread = __GetCurrentThread(); else { u32 error; @@ -1172,15 +1181,18 @@ void sceKernelGetThreadStackFreeSize() // Internal function void __KernelReturnFromThread() { - INFO_LOG(HLE,"__KernelReturnFromThread : %s", currentThread->GetName()); + Thread *thread = __GetCurrentThread(); + _dbg_assert_msg_(HLE, thread != NULL, "Returned from a NULL thread."); + + INFO_LOG(HLE,"__KernelReturnFromThread : %s", thread->GetName()); // TEMPORARY HACK: kill the stack of the root thread early: - if (!strcmp(currentThread->GetName(), "root")) { - currentThread->FreeStack(); + if (!strcmp(thread->GetName(), "root")) { + thread->FreeStack(); } - currentThread->nt.exitStatus = currentThread->context.r[2]; - currentThread->nt.status = THREADSTATUS_DORMANT; - __KernelFireThreadEnd(currentThread); + thread->nt.exitStatus = thread->context.r[2]; + thread->nt.status = THREADSTATUS_DORMANT; + __KernelFireThreadEnd(thread); // TODO: Need to remove the thread from any ready queues. @@ -1194,10 +1206,13 @@ void __KernelReturnFromThread() void sceKernelExitThread() { + Thread *thread = __GetCurrentThread(); + _dbg_assert_msg_(HLE, thread != NULL, "Exited from a NULL thread."); + ERROR_LOG(HLE,"sceKernelExitThread FAKED"); - currentThread->nt.status = THREADSTATUS_DORMANT; - currentThread->nt.exitStatus = PARAM(0); - __KernelFireThreadEnd(currentThread); + thread->nt.status = THREADSTATUS_DORMANT; + thread->nt.exitStatus = PARAM(0); + __KernelFireThreadEnd(thread); //Find threads that waited for me // Wake them @@ -1209,15 +1224,18 @@ void sceKernelExitThread() void _sceKernelExitThread() { + Thread *thread = __GetCurrentThread(); + _dbg_assert_msg_(HLE, thread != NULL, "_Exited from a NULL thread."); + ERROR_LOG(HLE,"_sceKernelExitThread FAKED"); - currentThread->nt.status = THREADSTATUS_DORMANT; - currentThread->nt.exitStatus = PARAM(0); - __KernelFireThreadEnd(currentThread); + thread->nt.status = THREADSTATUS_DORMANT; + thread->nt.exitStatus = PARAM(0); + __KernelFireThreadEnd(thread); //Find threads that waited for this one // Wake them if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - hleReSchedule("exit-deleted thread"); + hleReSchedule("_exit thread"); // The stack will be deallocated when the thread is deleted. } @@ -1230,11 +1248,11 @@ void sceKernelExitDeleteThread() if (t) { INFO_LOG(HLE,"sceKernelExitDeleteThread()"); - currentThread->nt.status = THREADSTATUS_DORMANT; - currentThread->nt.exitStatus = PARAM(0); - __KernelFireThreadEnd(currentThread); + t->nt.status = THREADSTATUS_DORMANT; + t->nt.exitStatus = PARAM(0); + __KernelFireThreadEnd(t); //userMemory.Free(currentThread->stackBlock); - currentThread->stackBlock = 0; + t->stackBlock = 0; __KernelRemoveFromThreadQueue(t); currentThread = 0; @@ -1274,7 +1292,7 @@ void sceKernelRotateThreadReadyQueue() int sceKernelDeleteThread(int threadHandle) { - if (threadHandle != currentThread->GetUID()) + if (threadHandle != currentThread) { //TODO: remove from threadqueue! DEBUG_LOG(HLE,"sceKernelDeleteThread(%i)",threadHandle); @@ -1299,14 +1317,14 @@ int sceKernelDeleteThread(int threadHandle) } else { - ERROR_LOG(HLE, "Thread \"%s\" tries to delete itself! :(",currentThread->GetName()); + ERROR_LOG(HLE, "Thread \"%s\" tries to delete itself! :(", __GetCurrentThread() ? __GetCurrentThread()->GetName() : "NULL"); return -1; } } int sceKernelTerminateDeleteThread(int threadno) { - if (threadno != currentThread->GetUID()) + if (threadno != currentThread) { //TODO: remove from threadqueue! INFO_LOG(HLE, "sceKernelTerminateDeleteThread(%i)", threadno); @@ -1315,18 +1333,19 @@ int sceKernelTerminateDeleteThread(int threadno) if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadno)) hleReSchedule("termdeletethread"); + // TODO: Why not delete? return 0; //kernelObjects.Destroy(threadno)); } else { - ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName()); + ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", __GetCurrentThread() ? __GetCurrentThread()->GetName() : "NULL"); return -1; } } int sceKernelTerminateThread(u32 threadID) { - if (threadID != currentThread->GetUID()) + if (threadID != currentThread) { INFO_LOG(HLE, "sceKernelTerminateThread(%i)", threadID); @@ -1343,25 +1362,28 @@ int sceKernelTerminateThread(u32 threadID) } else { - ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName()); + ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", __GetCurrentThread() ? __GetCurrentThread()->GetName() : "NULL"); return -1; } } SceUID __KernelGetCurThread() { - return currentThread->GetUID(); + return currentThread; } SceUID __KernelGetCurThreadModuleId() { - return currentThread->moduleId; + Thread *t = __GetCurrentThread(); + if (t) + return t->moduleId; + return 0; } void sceKernelGetThreadId() { - u32 retVal = currentThread->GetUID(); + u32 retVal = currentThread; DEBUG_LOG(HLE,"%i = sceKernelGetThreadId()", retVal); RETURN(retVal); } @@ -1378,14 +1400,18 @@ void sceKernelChangeCurrentThreadAttr() int clearAttr = PARAM(0); int setAttr = PARAM(1); DEBUG_LOG(HLE,"0 = sceKernelChangeCurrentThreadAttr(clear = %08x, set = %08x", clearAttr, setAttr); - currentThread->nt.attr = (currentThread->nt.attr & ~clearAttr) | setAttr; + Thread *t = __GetCurrentThread(); + if (t) + t->nt.attr = (t->nt.attr & ~clearAttr) | setAttr; + else + ERROR_LOG(HLE, "%s(): No current thread?", __FUNCTION__); RETURN(0); } void sceKernelChangeThreadPriority() { int id = PARAM(0); - if (id == 0) id = currentThread->GetUID(); //special + if (id == 0) id = currentThread; //special u32 error; Thread *thread = kernelObjects.Get(id, error); @@ -1476,9 +1502,16 @@ void sceKernelCancelWakeupThread() } static void __KernelSleepThread(bool doCallbacks) { - DEBUG_LOG(HLE,"sceKernelSleepThread() - wakeupCount decremented to %i", currentThread->nt.wakeupCount); - if (currentThread->nt.wakeupCount > 0) { - currentThread->nt.wakeupCount--; + Thread *thread = __GetCurrentThread(); + if (!thread) + { + ERROR_LOG(HLE, "sceKernelSleepThread*(): bad current thread"); + return; + } + + DEBUG_LOG(HLE,"sceKernelSleepThread() - wakeupCount decremented to %i", thread->nt.wakeupCount); + if (thread->nt.wakeupCount > 0) { + thread->nt.wakeupCount--; RETURN(0); } else { RETURN(0); @@ -1679,7 +1712,7 @@ void ActionAfterMipsCall::run() { ActionAfterMipsCall *Thread::getRunningCallbackAction() { - if (this == currentThread && g_inCbCount > 0) + if (this->GetUID() == currentThread && g_inCbCount > 0) { MipsCall *call = mipsCalls.get(this->currentCallbackId); ActionAfterMipsCall *action; @@ -1700,7 +1733,7 @@ ActionAfterMipsCall *Thread::getRunningCallbackAction() void Thread::setReturnValue(u32 retval) { - if (this == currentThread) { + if (this->GetUID() == currentThread) { if (g_inCbCount) { int callId = this->currentCallbackId; MipsCall *call = mipsCalls.get(callId); @@ -1790,23 +1823,25 @@ void __KernelSwitchContext(Thread *target, const char *reason) u32 oldPC = 0; u32 oldUID = 0; const char *oldName = "(none)"; - if (currentThread) // It might just have been deleted. + + Thread *cur = __GetCurrentThread(); + if (cur) // It might just have been deleted. { - __KernelSaveContext(¤tThread->context); + __KernelSaveContext(&cur->context); oldPC = currentMIPS->pc; - oldUID = currentThread->GetUID(); - oldName = currentThread->GetName(); + oldUID = cur->GetUID(); + oldName = cur->GetName(); } - currentThread = target; - __KernelLoadContext(¤tThread->context); + currentThread = target->GetUID(); + __KernelLoadContext(&target->context); DEBUG_LOG(HLE,"Context switched: %s -> %s (%s) (%i - pc: %08x -> %i - pc: %08x)", - oldName, currentThread->GetName(), + oldName, target->GetName(), reason, - oldUID, oldPC, currentThread->GetUID(), currentMIPS->pc); + oldUID, oldPC, target->GetUID(), currentMIPS->pc); // No longer waiting. - currentThread->nt.waitType = WAITTYPE_NONE; - currentThread->nt.waitID = 0; + target->nt.waitType = WAITTYPE_NONE; + target->nt.waitID = 0; __KernelExecutePendingMipsCalls(true); } @@ -1815,7 +1850,7 @@ void __KernelChangeThreadState(Thread *thread, ThreadStatus newStatus) { if (!thread || thread->nt.status == newStatus) return; - if (!dispatchEnabled && thread == currentThread && newStatus != THREADSTATUS_RUNNING) { + if (!dispatchEnabled && thread == __GetCurrentThread() && newStatus != THREADSTATUS_RUNNING) { ERROR_LOG(HLE, "Dispatching suspended, not changing thread state"); return; } @@ -1871,9 +1906,9 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo int callId = mipsCalls.add(call); bool called = false; - if (!thread || thread == currentThread) { + if (!thread || thread == __GetCurrentThread()) { if (__CanExecuteCallbackNow(thread)) { - thread = currentThread; + thread = __GetCurrentThread(); __KernelChangeThreadState(thread, THREADSTATUS_RUNNING); __KernelExecuteMipsCallOnCurrentThread(callId, reschedAfter); called = true; @@ -1892,8 +1927,15 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) { + Thread *cur = __GetCurrentThread(); + if (cur == NULL) + { + ERROR_LOG(HLE, "__KernelExecuteMipsCallOnCurrentThread(): Bad current thread"); + return; + } + if (g_inCbCount > 0) { - WARN_LOG(HLE, "__KernelExecuteMipsCallOnCurrentThread: Already in a callback!"); + WARN_LOG(HLE, "__KernelExecuteMipsCallOnCurrentThread(): Already in a callback!"); } DEBUG_LOG(HLE, "Executing mipscall %i", callId); MipsCall *call = mipsCalls.get(callId); @@ -1904,7 +1946,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) call->savedV0 = currentMIPS->r[MIPS_REG_V0]; call->savedV1 = currentMIPS->r[MIPS_REG_V1]; call->savedIdRegister = currentMIPS->r[MIPS_REG_CALL_ID]; - call->savedId = currentThread->currentCallbackId; + call->savedId = cur->currentCallbackId; call->returnVoid = false; call->reschedAfter = reschedAfter; @@ -1914,7 +1956,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) // We put this two places in case the game overwrites it. // We may want it later to "inject" return values. currentMIPS->r[MIPS_REG_CALL_ID] = callId; - currentThread->currentCallbackId = callId; + cur->currentCallbackId = callId; for (int i = 0; i < call->numArgs; i++) { currentMIPS->r[MIPS_REG_A0 + i] = call->args[i]; } @@ -1924,7 +1966,14 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) void __KernelReturnFromMipsCall() { - int callId = currentThread->currentCallbackId; + Thread *cur = __GetCurrentThread(); + if (cur == NULL) + { + ERROR_LOG(HLE, "__KernelReturnFromMipsCall(): Bad current thread"); + return; + } + + int callId = cur->currentCallbackId; if (currentMIPS->r[MIPS_REG_CALL_ID] != callId) WARN_LOG(HLE, "__KernelReturnFromMipsCall(): s0 is %08x != %08x", currentMIPS->r[MIPS_REG_CALL_ID], callId); @@ -1943,16 +1992,16 @@ void __KernelReturnFromMipsCall() currentMIPS->r[MIPS_REG_V0] = call->savedV0; currentMIPS->r[MIPS_REG_V1] = call->savedV1; currentMIPS->r[MIPS_REG_CALL_ID] = call->savedIdRegister; - currentThread->currentCallbackId = call->savedId; + cur->currentCallbackId = call->savedId; g_inCbCount--; // yeah! back in the real world, let's keep going. Should we process more callbacks? - __KernelCheckThreadCallbacks(currentThread, !call->reschedAfter); + __KernelCheckThreadCallbacks(cur, !call->reschedAfter); if (!__KernelExecutePendingMipsCalls(call->reschedAfter)) { // Sometimes, we want to stay on the thread. - int threadReady = currentThread->nt.status & (THREADSTATUS_READY | THREADSTATUS_RUNNING); + int threadReady = cur->nt.status & (THREADSTATUS_READY | THREADSTATUS_RUNNING); if (call->reschedAfter || threadReady == 0) __KernelReSchedule("return from callback"); } @@ -2062,13 +2111,14 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force) // Checks for callbacks on all threads bool __KernelCheckCallbacks() { // SceUID currentThread = __KernelGetCurThread(); - // currentThread->isProcessingCallbacks = true; + // __GetCurrentThread()->isProcessingCallbacks = true; // do { bool processed = false; - for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { - Thread *thread = *iter; - if (__KernelCheckThreadCallbacks(thread, false)) { + u32 error; + for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { + Thread *thread = kernelObjects.Get(*iter, error); + if (thread && __KernelCheckThreadCallbacks(thread, false)) { processed = true; } } @@ -2153,8 +2203,12 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notify // TODO: If cbId == -1, notify the callback ID on all threads that have it. u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int notifyArg) { - for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { - Thread *t = *iter; + u32 error; + for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { + Thread *t = kernelObjects.Get(*iter, error); + if (!t) + continue; + for (std::set::iterator citer = t->registeredCallbacks[type].begin(); citer != t->registeredCallbacks[type].end(); citer++) { if (cbId == -1 || cbId == *citer) { __KernelNotifyCallback(type, *citer, notifyArg); From a8c9c31e167433e091a04571605fe0f196c43f12 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 19:30:36 -0800 Subject: [PATCH 258/276] Add a registry for actions so they can be stated. Also add late loaders to ensure things are hooked up properly. --- Common/Action.h | 3 + Core/HLE/sceKernel.cpp | 6 +- Core/HLE/sceKernelInterrupt.cpp | 10 +- Core/HLE/sceKernelInterrupt.h | 1 + Core/HLE/sceKernelModule.cpp | 40 ++++-- Core/HLE/sceKernelThread.cpp | 222 +++++++++++++++++++++++++++++--- Core/HLE/sceKernelThread.h | 10 +- 7 files changed, 257 insertions(+), 35 deletions(-) diff --git a/Common/Action.h b/Common/Action.h index dbe7fb3759..ae3524b923 100644 --- a/Common/Action.h +++ b/Common/Action.h @@ -1,6 +1,7 @@ #pragma once #include +#include "ChunkFile.h" // Sometimes you want to set something to happen later, without that later place really needing // to know about all the things that might happen. That's when you use an Action, and add it @@ -17,4 +18,6 @@ class Action public: virtual ~Action() {} virtual void run() = 0; + virtual void DoState(PointerWrap &p) = 0; + int actionTypeID; }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 76e690465c..3e18b4c6b8 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -143,10 +143,9 @@ void __KernelDoState(PointerWrap &p) kernelObjects.DoState(p); p.DoMarker("KernelObjects"); - // TODO: Put these in the correct order... __InterruptsDoState(p); __KernelMemoryDoState(p); - // TODO: __KernelThreadingDoState(p); + __KernelThreadingDoState(p); __KernelAlarmDoState(p); __KernelEventFlagDoState(p); __KernelMbxDoState(p); @@ -155,6 +154,9 @@ void __KernelDoState(PointerWrap &p) __KernelSemaDoState(p); // TODO: non-kernel modules // TODO: PPGe + + __InterruptsDoStateLate(p); + __KernelThreadingDoStateLate(p); } bool __KernelIsRunning() { diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 445546f349..ecb1bef957 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -247,14 +247,20 @@ void __InterruptsDoState(PointerWrap &p) } intState.DoState(p); - for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) - intrHandlers[i].DoState(p); p.Do(pendingInterrupts, PendingInterrupt(0, 0)); p.Do(interruptsEnabled); p.Do(inInterrupt); p.DoMarker("sceKernelInterrupt"); } +void __InterruptsDoStateLate(PointerWrap &p) +{ + // We do these later to ensure the handlers have been registered. + for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) + intrHandlers[i].DoState(p); + p.DoMarker("sceKernelInterrupt Late"); +} + void __InterruptsShutdown() { for (int i = 0; i < PSP_NUMBER_INTERRUPTS; ++i) diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index 3a298b955b..6b60a7870f 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -109,6 +109,7 @@ typedef SubIntrHandler *(*SubIntrCreator)(); bool __IsInInterrupt(); void __InterruptsInit(); void __InterruptsDoState(PointerWrap &p); +void __InterruptsDoStateLate(PointerWrap &p); void __InterruptsShutdown(); void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1); void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int arg); // For GE "callbacks" diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index d35e5d5138..701b51297c 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -136,6 +136,25 @@ KernelObject *__KernelModuleObject() return new Module; } +class AfterModuleEntryCall : public Action { +public: + AfterModuleEntryCall() {} + SceUID moduleID_; + u32 retValAddr; + virtual void run(); + virtual void DoState(PointerWrap &p) { + p.Do(moduleID_); + p.Do(retValAddr); + } + static Action *Create() { + return new AfterModuleEntryCall; + } +}; + +void AfterModuleEntryCall::run() { + Memory::Write_U32(retValAddr, currentMIPS->r[2]); +} + ////////////////////////////////////////////////////////////////////////// // MODULES ////////////////////////////////////////////////////////////////////////// @@ -168,13 +187,21 @@ struct SceKernelSMOption { ////////////////////////////////////////////////////////////////////////// // STATE BEGIN +static int actionAfterModule; static SceUID mainModuleID; // hack // STATE END ////////////////////////////////////////////////////////////////////////// +void __KernelModuleInit() +{ + actionAfterModule = __KernelRegisterActionType(AfterModuleEntryCall::Create); +} + void __KernelModuleDoState(PointerWrap &p) { p.Do(mainModuleID); + p.Do(actionAfterModule); + __KernelRestoreActionType(actionAfterModule, AfterModuleEntryCall::Create); p.DoMarker("sceKernelModule"); } @@ -533,6 +560,7 @@ bool __KernelLoadExec(const char *filename, SceKernelLoadExecParam *param, std:: if (__KernelIsRunning()) __KernelShutdown(); + __KernelModuleInit(); __KernelInit(); PSPFileInfo info = pspFileSystem.GetFileInfo(filename); @@ -657,18 +685,6 @@ u32 sceKernelLoadModule(const char *name, u32 flags) return module->GetUID(); } -class AfterModuleEntryCall : public Action { -public: - AfterModuleEntryCall() {} - SceUID moduleID_; - u32 retValAddr; - virtual void run(); -}; - -void AfterModuleEntryCall::run() { - Memory::Write_U32(retValAddr, currentMIPS->r[2]); -} - void sceKernelStartModule(u32 moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, u32 optionAddr) { ERROR_LOG(HLE,"UNIMPL sceKernelStartModule(%d,asize=%08x,aptr=%08x,retptr=%08x,%08x)", diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 66a9172675..3743bb2a4b 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -193,13 +193,62 @@ public: return temp; } void clear() { + // TODO: Should this delete them? (it should probably just own them.) calls_.clear(); idGen_ = 0; } + int registerType(ActionCreator creator) { + types_.push_back(creator); + return types_.size() - 1; + } + + void restoreType(int actionType, ActionCreator creator) { + if (actionType >= (int) types_.size()) + types_.resize(actionType + 1, NULL); + types_[actionType] = creator; + } + + Action *createByType(int actionType) { + if (actionType < (int) types_.size() && types_[actionType] != NULL) { + Action *a = types_[actionType](); + a->actionTypeID = actionType; + return a; + } + return NULL; + } + + void DoState(PointerWrap &p) { + p.Do(idGen_); + + size_t n = (int) calls_.size(); + p.Do(n); + + if (p.mode == p.MODE_READ) { + // TODO: Delete them? + calls_.clear(); + for (size_t i = 0; i < n; ++i) { + int k; + p.Do(k); + // TODO: Presumably leaks? MipsCallManager may need to own these. + MipsCall *call = new MipsCall(); + call->DoState(p); + calls_[k] = call; + } + } else { + std::map::iterator it, end; + for (it = calls_.begin(), end = calls_.end(); it != end; ++it) { + p.Do(it->first); + it->second->DoState(p); + } + } + p.DoMarker("MipsCallManager"); + } + private: int genId() { return ++idGen_; } std::map calls_; + std::vector types_; int idGen_; }; @@ -207,7 +256,37 @@ class ActionAfterMipsCall : public Action { public: virtual void run(); - Thread *thread; + + static Action *Create() + { + return new ActionAfterMipsCall; + } + + virtual void DoState(PointerWrap &p) + { + p.Do(threadID); + p.Do(status); + p.Do(waitType); + p.Do(waitID); + p.Do(waitInfo); + p.Do(isProcessingCallbacks); + + p.DoMarker("ActionAfterMipsCall"); + + int chainedActionType = 0; + if (chainedAction != NULL) + chainedActionType = chainedAction->actionTypeID; + p.Do(chainedActionType); + + if (chainedActionType != 0) + { + if (p.mode == p.MODE_READ) + chainedAction = __KernelCreateAction(chainedActionType); + chainedAction->DoState(p); + } + } + + SceUID threadID; // Saved thread state int status; @@ -219,6 +298,31 @@ public: Action *chainedAction; }; +class ActionAfterCallback : public Action +{ +public: + ActionAfterCallback() {} + virtual void run(); + + static Action *Create() + { + return new ActionAfterCallback; + } + + void setCallback(SceUID cbId_) + { + cbId = cbId_; + } + + void DoState(PointerWrap &p) + { + p.Do(cbId); + p.DoMarker("ActionAfterCallback"); + } + + SceUID cbId; +}; + class Thread : public KernelObject { public: @@ -383,6 +487,8 @@ int eventScheduledWakeup; bool dispatchEnabled = true; MipsCallManager mipsCalls; +int actionAfterCallback; +int actionAfterMipsCall; // This seems nasty SceUID curModule; @@ -391,6 +497,50 @@ SceUID curModule; //STATE END ////////////////////////////////////////////////////////////////////////// +int __KernelRegisterActionType(ActionCreator creator) +{ + return mipsCalls.registerType(creator); +} + +void __KernelRestoreActionType(int actionType, ActionCreator creator) +{ + mipsCalls.restoreType(actionType, creator); +} + +Action *__KernelCreateAction(int actionType) +{ + return mipsCalls.createByType(actionType); +} + +void MipsCall::DoState(PointerWrap &p) +{ + p.Do(entryPoint); + p.Do(cbId); + p.DoArray(args, ARRAY_SIZE(args)); + p.Do(numArgs); + p.Do(savedIdRegister); + p.Do(savedRa); + p.Do(savedPc); + p.Do(savedV0); + p.Do(savedV1); + p.Do(returnVoid); + p.Do(tag); + p.Do(savedId); + p.Do(reschedAfter); + + p.DoMarker("MipsCall"); + + int actionTypeID = 0; + if (doAfter != NULL) + actionTypeID = doAfter->actionTypeID; + p.Do(actionTypeID); + if (actionTypeID != 0) + { + if (p.mode == p.MODE_READ) + doAfter = __KernelCreateAction(actionTypeID); + doAfter->DoState(p); + } +} // TODO: Should move to this wrapper so we can keep the current thread as a SceUID instead // of a dangerous raw pointer. @@ -443,6 +593,8 @@ void __KernelThreadingInit() WriteSyscall("FakeSysCalls", NID_INTERRUPTRETURN, intReturnHackAddr); eventScheduledWakeup = CoreTiming::RegisterEvent("ScheduledWakeup", &hleScheduledWakeup); + actionAfterMipsCall = __KernelRegisterActionType(ActionAfterMipsCall::Create); + actionAfterCallback = __KernelRegisterActionType(ActionAfterCallback::Create); // Create the two idle threads, as well. With the absolute minimal possible priority. // 4096 stack size - don't know what the right value is. Hm, if callbacks are ever to run on these threads... @@ -453,6 +605,37 @@ void __KernelThreadingInit() __KernelListenThreadEnd(__KernelCancelWakeup); } +void __KernelThreadingDoState(PointerWrap &p) +{ + p.Do(g_inCbCount); + p.Do(idleThreadHackAddr); + p.Do(threadReturnHackAddr); + p.Do(cbReturnHackAddr); + p.Do(intReturnHackAddr); + + p.Do(currentThread); + p.Do(threadqueue); + p.DoArray(threadIdleID, ARRAY_SIZE(threadIdleID)); + p.Do(dispatchEnabled); + p.Do(curModule); + + p.Do(eventScheduledWakeup); + CoreTiming::RestoreRegisterEvent(eventScheduledWakeup, "ScheduledWakeup", &hleScheduledWakeup); + p.Do(actionAfterMipsCall); + __KernelRestoreActionType(actionAfterMipsCall, ActionAfterMipsCall::Create); + p.Do(actionAfterCallback); + __KernelRestoreActionType(actionAfterCallback, ActionAfterCallback::Create); + + p.DoMarker("sceKernelThread"); +} + +void __KernelThreadingDoStateLate(PointerWrap &p) +{ + // We do this late to give modules time to register actions. + mipsCalls.DoState(p); + p.DoMarker("sceKernelThread Late"); +} + KernelObject *__KernelThreadObject() { return new Thread; @@ -1698,11 +1881,15 @@ void sceKernelReferCallbackStatus() } void ActionAfterMipsCall::run() { - thread->nt.status = status; - thread->nt.waitType = waitType; - thread->nt.waitID = waitID; - thread->waitInfo = waitInfo; - thread->isProcessingCallbacks = isProcessingCallbacks; + u32 error; + Thread *thread = kernelObjects.Get(threadID, error); + if (thread) { + thread->nt.status = status; + thread->nt.waitType = waitType; + thread->nt.waitID = waitID; + thread->waitInfo = waitInfo; + thread->isProcessingCallbacks = isProcessingCallbacks; + } if (chainedAction) { chainedAction->run(); @@ -1877,9 +2064,9 @@ bool __CanExecuteCallbackNow(Thread *thread) { void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bool returnVoid, std::vector args, bool reschedAfter) { if (thread) { - ActionAfterMipsCall *after = new ActionAfterMipsCall(); + ActionAfterMipsCall *after = (ActionAfterMipsCall *) __KernelCreateAction(actionAfterMipsCall); after->chainedAction = afterAction; - after->thread = thread; + after->threadID = thread->GetUID(); after->status = thread->nt.status; after->waitType = thread->nt.waitType; after->waitID = thread->nt.waitID; @@ -1986,6 +2173,7 @@ void __KernelReturnFromMipsCall() // Should also save/restore wait state here. if (call->doAfter) call->doAfter->run(); + // TODO: Do we need to delete call->doAfter? currentMIPS->pc = call->savedPc; currentMIPS->r[MIPS_REG_RA] = call->savedRa; @@ -2005,6 +2193,8 @@ void __KernelReturnFromMipsCall() if (call->reschedAfter || threadReady == 0) __KernelReSchedule("return from callback"); } + + // TODO: Do we need to delete call? } bool __KernelExecutePendingMipsCalls(bool reschedAfter) @@ -2027,15 +2217,6 @@ bool __KernelExecutePendingMipsCalls(bool reschedAfter) return false; } - -class ActionAfterCallback : public Action -{ -public: - ActionAfterCallback(SceUID cbId_) : cbId(cbId_) {} - virtual void run(); - SceUID cbId; -}; - // Executes the callback, when it next is context switched to. void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread, bool reschedAfter) { @@ -2060,7 +2241,12 @@ void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread, bool reschedAfter) cb->nc.notifyCount = 0; cb->nc.notifyArg = 0; - Action *action = new ActionAfterCallback(cbId); + ActionAfterCallback *action = (ActionAfterCallback *) __KernelCreateAction(actionAfterCallback); + if (action != NULL) + action->setCallback(cbId); + else + ERROR_LOG(HLE, "Something went wrong creating a restore action for a callback."); + __KernelCallAddress(thread, cb->nc.entrypoint, action, false, args, reschedAfter); } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index d11a33c17c..b63fe58312 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -97,6 +97,8 @@ struct ThreadContext // Internal API, used by implementations of kernel functions void __KernelThreadingInit(); +void __KernelThreadingDoState(PointerWrap &p); +void __KernelThreadingDoStateLate(PointerWrap &p); void __KernelThreadingShutdown(); KernelObject *__KernelThreadObject(); KernelObject *__KernelCallbackObject(); @@ -184,6 +186,10 @@ bool __KernelSwitchOffThread(const char *reason); // A call into game code. These can be pending on a thread. // Similar to Callback-s (NOT CallbackInfos) in JPCSP. class Action; +typedef Action *(*ActionCreator)(); +Action *__KernelCreateAction(int actionType); +int __KernelRegisterActionType(ActionCreator creator); +void __KernelRestoreActionType(int actionType, ActionCreator creator); struct MipsCall { u32 entryPoint; u32 cbId; @@ -196,9 +202,11 @@ struct MipsCall { u32 savedV0; u32 savedV1; bool returnVoid; - const char *tag; + std::string tag; u32 savedId; bool reschedAfter; + + void DoState(PointerWrap &p); }; enum ThreadStatus { From b81899876f04f6f30ff9150b538049adda789e97 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 19:45:00 -0800 Subject: [PATCH 259/276] Don't leak MipsCall objects. --- Core/HLE/sceKernelThread.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 3743bb2a4b..9cfecf7874 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -175,7 +175,6 @@ struct ThreadWaitInfo { }; // Owns outstanding MIPS calls and provides a way to get them by ID. -// TODO: MipsCall structs are kinda big, try to cut down on the copying by owning pointers instead. class MipsCallManager { public: MipsCallManager() : idGen_(0) {} @@ -193,23 +192,26 @@ public: return temp; } void clear() { - // TODO: Should this delete them? (it should probably just own them.) + std::map::iterator it, end; + for (it = calls_.begin(), end = calls_.end(); it != end; ++it) { + delete it->second; + } calls_.clear(); idGen_ = 0; } - int registerType(ActionCreator creator) { + int registerActionType(ActionCreator creator) { types_.push_back(creator); return types_.size() - 1; } - void restoreType(int actionType, ActionCreator creator) { + void restoreActionType(int actionType, ActionCreator creator) { if (actionType >= (int) types_.size()) types_.resize(actionType + 1, NULL); types_[actionType] = creator; } - Action *createByType(int actionType) { + Action *createActionByType(int actionType) { if (actionType < (int) types_.size() && types_[actionType] != NULL) { Action *a = types_[actionType](); a->actionTypeID = actionType; @@ -219,18 +221,15 @@ public: } void DoState(PointerWrap &p) { - p.Do(idGen_); size_t n = (int) calls_.size(); p.Do(n); if (p.mode == p.MODE_READ) { - // TODO: Delete them? - calls_.clear(); + clear(); for (size_t i = 0; i < n; ++i) { int k; p.Do(k); - // TODO: Presumably leaks? MipsCallManager may need to own these. MipsCall *call = new MipsCall(); call->DoState(p); calls_[k] = call; @@ -242,6 +241,8 @@ public: it->second->DoState(p); } } + + p.Do(idGen_); p.DoMarker("MipsCallManager"); } @@ -499,17 +500,17 @@ SceUID curModule; int __KernelRegisterActionType(ActionCreator creator) { - return mipsCalls.registerType(creator); + return mipsCalls.registerActionType(creator); } void __KernelRestoreActionType(int actionType, ActionCreator creator) { - mipsCalls.restoreType(actionType, creator); + mipsCalls.restoreActionType(actionType, creator); } Action *__KernelCreateAction(int actionType) { - return mipsCalls.createByType(actionType); + return mipsCalls.createActionByType(actionType); } void MipsCall::DoState(PointerWrap &p) @@ -2172,8 +2173,10 @@ void __KernelReturnFromMipsCall() // Should also save/restore wait state here. if (call->doAfter) + { call->doAfter->run(); - // TODO: Do we need to delete call->doAfter? + delete call->doAfter; + } currentMIPS->pc = call->savedPc; currentMIPS->r[MIPS_REG_RA] = call->savedRa; @@ -2194,7 +2197,7 @@ void __KernelReturnFromMipsCall() __KernelReSchedule("return from callback"); } - // TODO: Do we need to delete call? + delete call; } bool __KernelExecutePendingMipsCalls(bool reschedAfter) From e3e6f81dfa9f0156ea124927d205b9f824c93d9a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 20:33:10 -0800 Subject: [PATCH 260/276] Snapshot the CPU state as well. --- Core/MIPS/MIPS.cpp | 27 +++++++++++++++++++++++++++ Core/MIPS/MIPS.h | 8 ++++++++ Core/SaveState.cpp | 3 +++ 3 files changed, 38 insertions(+) diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index e4fa5549fe..d784419212 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -99,6 +99,33 @@ void MIPSState::Reset() rng.Init(0x1337); } +void MIPSState::DoState(PointerWrap &p) +{ + // Reset the jit if we're loading. + if (p.mode == p.MODE_READ) + Reset(); + + p.DoArray(r, sizeof(r) / sizeof(r[0])); + p.DoArray(f, sizeof(f) / sizeof(f[0])); + p.DoArray(v, sizeof(v) / sizeof(v[0])); + p.DoArray(vfpuCtrl, sizeof(vfpuCtrl) / sizeof(vfpuCtrl[0])); + p.DoArray(vfpuWriteMask, sizeof(vfpuWriteMask) / sizeof(vfpuWriteMask[0])); + p.Do(pc); + p.Do(nextPC); + p.Do(hi); + p.Do(lo); + p.Do(fpcond); + p.Do(fcr0); + p.Do(fcr31); + rng.DoState(p); + p.Do(inDelaySlot); + p.Do(llBit); + p.Do(cpuType); + p.Do(exceptions); + p.Do(debugCount); + p.DoMarker("MIPSState"); +} + void MIPSState::SetWriteMask(const bool wm[4]) { for (int i = 0; i < 4; i++) diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index cbab48edba..1e8bd29a6f 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -18,6 +18,7 @@ #pragma once #include "../../Globals.h" +#include "../../Common/ChunkFile.h" #include "../CPU.h" enum @@ -92,6 +93,12 @@ public: return (m_z << 16) + m_w; } + void DoState(PointerWrap &p) { + p.Do(m_w); + p.Do(m_z); + p.DoMarker("GMRng"); + } + private: u32 m_w; u32 m_z; @@ -104,6 +111,7 @@ public: ~MIPSState(); void Reset(); + void DoState(PointerWrap &p); u32 r[32]; float f[32]; diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index bbf8717b9f..69ba1a517c 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -24,6 +24,7 @@ #include "HLE/sceKernel.h" #include "HW/MemoryStick.h" #include "MemMap.h" +#include "MIPS/MIPS.h" namespace SaveState { @@ -70,7 +71,9 @@ namespace SaveState Memory::DoState(p); MemoryStick_DoState(p); + currentMIPS->DoState(p); __KernelDoState(p); + // TODO: filesystem, HLE? } void Enqueue(SaveState::Operation op) From 4b39e39455b3806c1fffb72aa016be3cf7dccda4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 22:14:31 -0800 Subject: [PATCH 261/276] Start save stating the filesystem state. Plus minor fixes and at least an attempt to make states the same on both 32 and 64 bit. --- Common/ChunkFile.h | 3 +- Core/CoreTiming.cpp | 2 +- Core/FileSystems/DirectoryFileSystem.cpp | 5 ++ Core/FileSystems/DirectoryFileSystem.h | 1 + Core/FileSystems/FileSystem.h | 2 + Core/FileSystems/ISOFileSystem.cpp | 70 ++++++++++++++++++++++++ Core/FileSystems/ISOFileSystem.h | 5 +- Core/FileSystems/MetaFileSystem.cpp | 19 +++++++ Core/FileSystems/MetaFileSystem.h | 2 + Core/HLE/HLE.cpp | 6 ++ Core/HLE/HLE.h | 1 + Core/HLE/sceIo.cpp | 6 +- Core/HLE/sceKernelInterrupt.cpp | 4 +- Core/HLE/sceKernelThread.cpp | 4 +- Core/SaveState.cpp | 5 +- 15 files changed, 125 insertions(+), 10 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index c6dd5d6de0..f6e3f0a0ce 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -158,7 +158,8 @@ public: u32 vec_size = (u32)x.size(); Do(vec_size); x.resize(vec_size); - DoArray(&x[0], vec_size); + if (vec_size > 0) + DoArray(&x[0], vec_size); } // Store deques. diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 31b9bbb0ad..504d28fb5b 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -550,7 +550,7 @@ void Event_DoState(PointerWrap &p, BaseEvent *ev) void DoState(PointerWrap &p) { - size_t n = event_types.size(); + int n = (int) event_types.size(); p.Do(n); // These (should) be filled in later by the modules. event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT")); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 51dbcc7979..e57be86eb2 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -546,3 +546,8 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { return myVector; } +void DirectoryFileSystem::DoState(PointerWrap &p) { + if (!entries.empty()) { + ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly."); + } +} diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index e3f4bf0acc..6cb334fc53 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -53,6 +53,7 @@ public: DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath); ~DirectoryFileSystem(); + void DoState(PointerWrap &p); std::vector GetDirListing(std::string path); u32 OpenFile(std::string filename, FileAccess access); void CloseFile(u32 handle); diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index d14854803e..4d8670effd 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -90,6 +90,7 @@ class IFileSystem public: virtual ~IFileSystem() {} + virtual void DoState(PointerWrap &p) = 0; virtual std::vector GetDirListing(std::string path) = 0; virtual u32 OpenFile(std::string filename, FileAccess access) = 0; virtual void CloseFile(u32 handle) = 0; @@ -108,6 +109,7 @@ public: class EmptyFileSystem : public IFileSystem { public: + virtual void DoState(PointerWrap &p) {} std::vector GetDirListing(std::string path) {std::vector vec; return vec;} u32 OpenFile(std::string filename, FileAccess access) {return 0;} void CloseFile(u32 handle) {} diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index a7e7bf01f6..712a10e953 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -131,6 +131,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic entireISO.size = _blockDevice->GetNumBlocks() * _blockDevice->GetBlockSize(); entireISO.isBlockSectorMode = true; entireISO.flags = 0; + entireISO.parent = NULL; if (!memcmp(desc.cd001, "CD001", 5)) { @@ -142,6 +143,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic } treeroot = new TreeEntry; + treeroot->parent = NULL; u32 rootSector = desc.root.firstDataSectorLE; u32 rootSize = desc.root.dataLengthLE; @@ -211,6 +213,7 @@ nextblock: e->isDirectory = !isFile; e->flags = dir.flags; e->isBlockSectorMode = false; + e->parent = root; // 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); @@ -540,3 +543,70 @@ std::vector ISOFileSystem::GetDirListing(std::string path) } return myVector; } + +std::string ISOFileSystem::EntryFullPath(TreeEntry *e) +{ + size_t fullLen = 0; + TreeEntry *cur = e; + while (cur != NULL && cur != treeroot) + { + // For the "/". + fullLen += 1 + cur->name.size(); + cur = cur->parent; + } + + std::string path; + path.resize(fullLen); + + cur = e; + while (cur != NULL && cur != treeroot) + { + path.replace(fullLen - cur->name.size(), cur->name.size(), cur->name); + path.replace(fullLen - cur->name.size() - 1, 1, "/"); + fullLen -= 1 + cur->name.size(); + cur = cur->parent; + } + + return path; +} + +void ISOFileSystem::DoState(PointerWrap &p) +{ + int n = (int) entries.size(); + p.Do(n); + + if (p.mode == p.MODE_READ) + { + entries.clear(); + for (int i = 0; i < n; ++i) + { + u32 fd; + p.Do(fd); + std::string path; + p.Do(path); + OpenFileEntry of; + of.file = path.empty() ? NULL : GetFromPath(path); + p.Do(of.seekPos); + p.Do(of.isRawSector); + p.Do(of.sectorStart); + p.Do(of.openSize); + entries[fd] = of; + } + } + else + { + for (EntryMap::iterator it = entries.begin(), end = entries.end(); it != end; ++it) + { + p.Do(it->first); + std::string path = ""; + if (it->second.file != NULL) + path = EntryFullPath(it->second.file); + p.Do(path); + p.Do(it->second.seekPos); + p.Do(it->second.isRawSector); + p.Do(it->second.sectorStart); + p.Do(it->second.openSize); + } + } + p.DoMarker("ISOFileSystem"); +} diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 61f30016f1..96e88e0710 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -42,8 +42,9 @@ class ISOFileSystem : public IFileSystem u32 startingPosition; s64 size; bool isDirectory; - bool isBlockSectorMode; // "umd:" mode: all sizes and offsets are in 2048 byte chunks + bool isBlockSectorMode; // "umd:" mode: all sizes and offsets are in 2048 byte chunks + TreeEntry *parent; std::vector children; }; @@ -67,10 +68,12 @@ class ISOFileSystem : public IFileSystem void ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root); TreeEntry *GetFromPath(std::string path); + std::string EntryFullPath(TreeEntry *e); public: ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice); ~ISOFileSystem(); + void DoState(PointerWrap &p); std::vector GetDirListing(std::string path); u32 OpenFile(std::string filename, FileAccess access); void CloseFile(u32 handle); diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index ed18b31a07..58ae33fae1 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -367,3 +367,22 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) return 0; } +void MetaFileSystem::DoState(PointerWrap &p) +{ + p.Do(current); + p.Do(currentDirectory); + + int n = (int) fileSystems.size(); + p.Do(n); + if (n != fileSystems.size()) + { + ERROR_LOG(FILESYS, "Savestate failure: number of filesystems doesn't match."); + return; + } + + for (int i = 0; i < n; ++i) + fileSystems[i].system->DoState(p); + + p.DoMarker("MetaFileSystem"); +} + diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index b0b63d9b97..7fd0a96db2 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -36,6 +36,8 @@ public: u32 GetNewHandle() {return current++;} void FreeHandle(u32 handle) {} + virtual void DoState(PointerWrap &p); + IFileSystem *GetHandleOwner(u32 handle); bool MapFilePath(const std::string &inpath, std::string &outpath, IFileSystem **system); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index f58a2aca4f..7d5c426c49 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -58,6 +58,12 @@ void HLEInit() RegisterAllModules(); } +void HLEDoState(PointerWrap &p) +{ + p.Do(unresolvedSyscalls); + p.DoMarker("HLE"); +} + void HLEShutdown() { hleAfterSyscall = HLE_AFTER_NOTHING; diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 09d5fc75cd..8ff39c328c 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -87,6 +87,7 @@ void hleRunInterrupts(); void hleDebugBreak(); void HLEInit(); +void HLEDoState(PointerWrap &p); void HLEShutdown(); u32 GetNibByName(const char *module, const char *function); u32 GetSyscallOp(const char *module, u32 nib); diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 801b4bf917..70af694f7b 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -853,8 +853,10 @@ public: p.Do(name); // TODO: Is this the right way for it to wake up? - size_t count = listing.size(); - for (size_t i = 0; i < count; ++i) { + int count = listing.size(); + p.Do(count); + listing.resize(count); + for (int i = 0; i < count; ++i) { listing[i].DoState(p); } p.DoMarker("DirListing"); diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index ecb1bef957..7c8c9d2544 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -168,13 +168,13 @@ public: return; } - size_t n = subIntrHandlers.size(); + int n = (int) subIntrHandlers.size(); p.Do(n); if (p.mode == p.MODE_READ) { clear(); - for (size_t i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { int subIntrNum; p.Do(subIntrNum); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 9cfecf7874..7732c558ce 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -222,12 +222,12 @@ public: void DoState(PointerWrap &p) { - size_t n = (int) calls_.size(); + int n = (int) calls_.size(); p.Do(n); if (p.mode == p.MODE_READ) { clear(); - for (size_t i = 0; i < n; ++i) { + for (int i = 0; i < n; ++i) { int k; p.Do(k); MipsCall *call = new MipsCall(); diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 69ba1a517c..35f91ce900 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -21,10 +21,12 @@ #include "SaveState.h" #include "Core.h" #include "CoreTiming.h" +#include "HLE/HLE.h" #include "HLE/sceKernel.h" #include "HW/MemoryStick.h" #include "MemMap.h" #include "MIPS/MIPS.h" +#include "System.h" namespace SaveState { @@ -72,8 +74,9 @@ namespace SaveState Memory::DoState(p); MemoryStick_DoState(p); currentMIPS->DoState(p); + pspFileSystem.DoState(p); + HLEDoState(p); __KernelDoState(p); - // TODO: filesystem, HLE? } void Enqueue(SaveState::Operation op) From 1768365c13df95b56b8c39add91b4afed13ba74a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 22:16:23 -0800 Subject: [PATCH 262/276] Fix a memory leak in the ISO filesystem. --- Core/FileSystems/ISOFileSystem.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/FileSystems/ISOFileSystem.cpp b/Core/FileSystems/ISOFileSystem.cpp index 712a10e953..b054b6bf72 100644 --- a/Core/FileSystems/ISOFileSystem.cpp +++ b/Core/FileSystems/ISOFileSystem.cpp @@ -143,6 +143,11 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic } treeroot = new TreeEntry; + treeroot->isDirectory = true; + treeroot->startingPosition = 0; + treeroot->size = 0; + treeroot->isBlockSectorMode = false; + treeroot->flags = 0; treeroot->parent = NULL; u32 rootSector = desc.root.firstDataSectorLE; @@ -154,6 +159,7 @@ ISOFileSystem::ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevic ISOFileSystem::~ISOFileSystem() { delete blockDevice; + delete treeroot; } void ISOFileSystem::ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root) From cd1d4367bfa3c1bfbb12b32a36e8e7521908fc77 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 23:00:04 -0800 Subject: [PATCH 263/276] Save state of a bunch of small modules. --- Core/HLE/sceCtrl.cpp | 24 +++++++++++++++++++++++ Core/HLE/sceCtrl.h | 3 +++ Core/HLE/sceFont.cpp | 35 ++++++++++++++++++++++------------ Core/HLE/sceFont.h | 5 +++++ Core/HLE/sceImpose.cpp | 8 ++++++++ Core/HLE/sceImpose.h | 3 +++ Core/HLE/sceKernel.cpp | 13 ++++++++++++- Core/HLE/scePower.cpp | 6 ++++++ Core/HLE/scePower.h | 3 +++ Core/HLE/sceSsl.cpp | 8 ++++++++ Core/HLE/sceSsl.h | 5 ++++- Core/HLE/sceUmd.cpp | 23 ++++++++++++++++------ Core/HLE/sceUmd.h | 1 + Core/HLE/sceUsb.cpp | 6 ++++++ Core/HLE/sceUsb.h | 1 + Core/Util/PPGeDraw.cpp | 43 ++++++++++++++++++++++++++++++++---------- Core/Util/PPGeDraw.h | 4 ++++ 17 files changed, 161 insertions(+), 30 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 5874ae2865..fbaac32477 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -284,6 +284,30 @@ void __CtrlInit() memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data)); } +void __CtrlDoState(PointerWrap &p) +{ + p.Do(analogEnabled); + p.Do(ctrlLatchBufs); + p.Do(ctrlOldButtons); + + p.DoVoid(ctrlBufs, sizeof(ctrlBufs)); + p.Do(ctrlCurrent); + p.Do(ctrlBuf); + p.Do(ctrlBufRead); + p.Do(latch); + + p.Do(ctrlIdleReset); + p.Do(ctrlIdleBack); + + p.Do(ctrlCycle); + + p.Do(waitingThreads); + + p.Do(ctrlTimer); + CoreTiming::RestoreRegisterEvent(ctrlTimer, "CtrlSampleTimer", __CtrlTimerUpdate); + p.DoMarker("sceCtrl"); +} + void __CtrlShutdown() { waitingThreads.clear(); diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index 62dff53bcc..5f9b4e3e05 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -17,6 +17,8 @@ #pragma once +#include "../../Common/ChunkFile.h" + void Register_sceCtrl(); #define CTRL_SQUARE 0x8000 @@ -33,6 +35,7 @@ void Register_sceCtrl(); #define CTRL_RTRIGGER 0x0200 void __CtrlInit(); +void __CtrlDoState(PointerWrap &p); void __CtrlShutdown(); void __CtrlButtonDown(u32 buttonBit); diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index 294b092a2d..8c026e1913 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -12,19 +12,19 @@ typedef u32 FontLibraryHandle; typedef u32 FontHandle; typedef struct { - u32* userDataAddr; - u32 numFonts; - u32* cacheDataAddr; + u32 userDataAddr; + u32 numFonts; + u32 cacheDataAddr; // Driver callbacks. - void *(*allocFuncAddr)(void *, u32); - void (*freeFuncAddr )(void *, void *); - u32* openFuncAddr; - u32* closeFuncAddr; - u32* readFuncAddr; - u32* seekFuncAddr; - u32* errorFuncAddr; - u32* ioFinishFuncAddr; + u32 allocFuncAddr; + u32 freeFuncAddr; + u32 openFuncAddr; + u32 closeFuncAddr; + u32 readFuncAddr; + u32 seekFuncAddr; + u32 errorFuncAddr; + u32 ioFinishFuncAddr; } FontNewLibParams; typedef enum { @@ -138,11 +138,22 @@ typedef struct { u16 bufHeight; u16 bytesPerLine; u16 pad; - void *buffer; + u32 bufferPtr; } GlyphImage; FontNewLibParams fontLib; +void __FontInit() +{ + memset(&fontLib, 0, sizeof(fontLib)); +} + +void __FontDoState(PointerWrap &p) +{ + p.Do(fontLib); + p.DoMarker("sceFont"); +} + u32 sceFontNewLib(u32 FontNewLibParamsPtr, u32 errorCodePtr) { ERROR_LOG(HLE, "sceFontNewLib %x, %x", FontNewLibParamsPtr, errorCodePtr); diff --git a/Core/HLE/sceFont.h b/Core/HLE/sceFont.h index d5ff49a150..9ca1bcd6d6 100644 --- a/Core/HLE/sceFont.h +++ b/Core/HLE/sceFont.h @@ -1,3 +1,8 @@ #pragma once +#include "../../Common/ChunkFile.h" + void Register_sceFont(); + +void __FontInit(); +void __FontDoState(PointerWrap &p); diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 8e098f3d70..2f201c0bcf 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -44,6 +44,14 @@ void __ImposeInit() umdPopup = 0; } +void __ImposeDoState(PointerWrap &p) +{ + p.Do(language); + p.Do(buttonValue); + p.Do(umdPopup); + p.DoMarker("sceImpose"); +} + u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) { DEBUG_LOG(HLE, "sceImposeGetBatteryIconStatus(%08x, %08x)", chargingPtr, iconStatusPtr); diff --git a/Core/HLE/sceImpose.h b/Core/HLE/sceImpose.h index 86eabedcec..f340cd5722 100644 --- a/Core/HLE/sceImpose.h +++ b/Core/HLE/sceImpose.h @@ -17,5 +17,8 @@ #pragma once +#include "../../Common/ChunkFile.h" + void Register_sceImpose(); void __ImposeInit(); +void __ImposeDoState(PointerWrap &p); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 3e18b4c6b8..ff3f9202f6 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -34,6 +34,7 @@ #include "sceAudio.h" #include "sceCtrl.h" #include "sceDisplay.h" +#include "sceFont.h" #include "sceGe.h" #include "sceIo.h" #include "sceKernel.h" @@ -98,6 +99,7 @@ void __KernelInit() __SslInit(); __ImposeInit(); __UsbInit(); + __FontInit(); // "Internal" PSP libraries __PPGeInit(); @@ -152,8 +154,17 @@ void __KernelDoState(PointerWrap &p) __KernelModuleDoState(p); __KernelMutexDoState(p); __KernelSemaDoState(p); + // TODO: non-kernel modules - // TODO: PPGe + __CtrlDoState(p); + __FontDoState(p); + __ImposeDoState(p); + __PowerDoState(p); + __SslDoState(p); + __UmdDoState(p); + __UsbDoState(p); + + __PPGeDoState(p); __InterruptsDoStateLate(p); __KernelThreadingDoStateLate(p); diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index 68fd2215d7..f486c064f9 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -33,6 +33,12 @@ void __PowerInit() { volatileMemLocked = false; } +void __PowerDoState(PointerWrap &p) { + p.DoArray(powerCbSlots, ARRAY_SIZE(powerCbSlots)); + p.Do(volatileMemLocked); + p.DoMarker("scePower"); +} + int scePowerGetBatteryLifePercent() { DEBUG_LOG(HLE, "100=scePowerGetBatteryLifePercent"); return 100; diff --git a/Core/HLE/scePower.h b/Core/HLE/scePower.h index ac99c6a769..49a1b8b444 100644 --- a/Core/HLE/scePower.h +++ b/Core/HLE/scePower.h @@ -17,7 +17,10 @@ #pragma once +#include "../../Common/ChunkFile.h" + void __PowerInit(); +void __PowerDoState(PointerWrap &p); void Register_scePower(); void Register_sceSuspendForUser(); diff --git a/Core/HLE/sceSsl.cpp b/Core/HLE/sceSsl.cpp index 0a762af122..b588135b88 100644 --- a/Core/HLE/sceSsl.cpp +++ b/Core/HLE/sceSsl.cpp @@ -35,6 +35,14 @@ void __SslInit() currentMemSize = 0; } +void __SslDoState(PointerWrap &p) +{ + p.Do(isSslInit); + p.Do(maxMemSize); + p.Do(currentMemSize); + p.DoMarker("sceSsl"); +} + int sceSslInit(int heapSize) { DEBUG_LOG(HLE, "sceSslInit %d", heapSize); diff --git a/Core/HLE/sceSsl.h b/Core/HLE/sceSsl.h index c8e46f976b..6a1239f892 100644 --- a/Core/HLE/sceSsl.h +++ b/Core/HLE/sceSsl.h @@ -17,6 +17,9 @@ #pragma once +#include "../../Common/ChunkFile.h" + void Register_sceSsl(); -void __SslInit(); \ No newline at end of file +void __SslInit(); +void __SslDoState(PointerWrap &p); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 3e358d36a3..4d3b425b51 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -31,11 +31,11 @@ const int PSP_ERROR_UMD_INVALID_PARAM = 0x80010016; #define UMD_READABLE 0x20 -u8 umdActivated = 1; -u32 umdStatus = 0; -u32 umdErrorStat = 0; -static int driveCBId= -1; -int umdStatTimer = 0; +static u8 umdActivated = 1; +static u32 umdStatus = 0; +static u32 umdErrorStat = 0; +static int driveCBId = -1; +static int umdStatTimer = 0; #define PSP_UMD_TYPE_GAME 0x10 @@ -51,13 +51,24 @@ void __UmdStatTimeout(u64 userdata, int cyclesLate); void __UmdInit() { - umdStatTimer = CoreTiming::RegisterEvent("UmdTimeout", &__UmdStatTimeout); + umdStatTimer = CoreTiming::RegisterEvent("UmdTimeout", __UmdStatTimeout); umdActivated = 1; umdStatus = 0; umdErrorStat = 0; driveCBId = -1; } +void __UmdDoState(PointerWrap &p) +{ + p.Do(umdActivated); + p.Do(umdStatus); + p.Do(umdErrorStat); + p.Do(driveCBId); + p.Do(umdStatTimer); + CoreTiming::RestoreRegisterEvent(umdStatTimer, "UmdTimeout", __UmdStatTimeout); + p.DoMarker("sceUmd"); +} + u8 __KernelUmdGetState() { u8 state = UMD_PRESENT; diff --git a/Core/HLE/sceUmd.h b/Core/HLE/sceUmd.h index ceaa832a42..b0026e6eb0 100644 --- a/Core/HLE/sceUmd.h +++ b/Core/HLE/sceUmd.h @@ -27,5 +27,6 @@ enum pspUmdState { }; void __UmdInit(); +void __UmdDoState(PointerWrap &p); void Register_sceUmdUser(); diff --git a/Core/HLE/sceUsb.cpp b/Core/HLE/sceUsb.cpp index 1d1ebc2189..a76751cf2e 100644 --- a/Core/HLE/sceUsb.cpp +++ b/Core/HLE/sceUsb.cpp @@ -27,6 +27,12 @@ void __UsbInit() usbActivated = false; } +void __UsbDoState(PointerWrap &p) +{ + p.Do(usbActivated); + p.DoMarker("sceUsb"); +} + u32 sceUsbActivate() { ERROR_LOG(HLE, "UNIMPL sceUsbActivate"); usbActivated = true; diff --git a/Core/HLE/sceUsb.h b/Core/HLE/sceUsb.h index d521a0a9da..d1b280be76 100644 --- a/Core/HLE/sceUsb.h +++ b/Core/HLE/sceUsb.h @@ -20,3 +20,4 @@ void Register_sceUsb(); void __UsbInit(); +void __UsbDoState(PointerWrap &p); diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index f7655f0cbc..bd8032dd0b 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -39,21 +39,21 @@ struct PPGeVertex { s16 x, y; u16 z; }; -u32 savedContextPtr; -u32 savedContextSize = 512 * 4; +static u32 savedContextPtr; +static u32 savedContextSize = 512 * 4; // Display list writer -u32 dlPtr; -u32 dlWritePtr; -u32 dlSize = 0x10000; // should be enough for a frame of gui... +static u32 dlPtr; +static u32 dlWritePtr; +static u32 dlSize = 0x10000; // should be enough for a frame of gui... -u32 dataPtr; -u32 dataWritePtr; -u32 dataSize = 0x10000; // should be enough for a frame of gui... +static u32 dataPtr; +static u32 dataWritePtr; +static u32 dataSize = 0x10000; // should be enough for a frame of gui... // Vertex collector -u32 vertexStart; -u32 vertexCount; +static u32 vertexStart; +static u32 vertexCount; //only 0xFFFFFF of data is used static void WriteCmd(u8 cmd, u32 data) { @@ -141,6 +141,29 @@ void __PPGeInit() dlPtr, dataPtr, atlasPtr, atlasSize, savedContextPtr); } +void __PPGeDoState(PointerWrap &p) +{ + p.Do(atlasPtr); + p.Do(atlasWidth); + p.Do(atlasHeight); + + p.Do(savedContextPtr); + p.Do(savedContextSize); + + p.Do(dlPtr); + p.Do(dlWritePtr); + p.Do(dlSize); + + p.Do(dataPtr); + p.Do(dataWritePtr); + p.Do(dataSize); + + p.Do(vertexStart); + p.Do(vertexCount); + + p.DoMarker("PPGeDraw"); +} + void __PPGeShutdown() { if (atlasPtr) diff --git a/Core/Util/PPGeDraw.h b/Core/Util/PPGeDraw.h index e77a53cd89..48f23bca4b 100644 --- a/Core/Util/PPGeDraw.h +++ b/Core/Util/PPGeDraw.h @@ -18,6 +18,7 @@ #pragma once #include "../../Globals.h" +#include "../../Common/ChunkFile.h" #include "ppge_atlas.h" ///////////////////////////////////////////////////////////////////////////////////////////// @@ -29,6 +30,9 @@ // space for the display list. The PSP must be inited. void __PPGeInit(); +// Saves to and restores from savestates (kernel RAM pointers, etc.) +void __PPGeDoState(PointerWrap &p); + // Just frees up the allocated kernel memory. void __PPGeShutdown(); From 042e515037de4ce9e6620c88c2ef7e75b6ac5903 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Dec 2012 23:08:38 -0800 Subject: [PATCH 264/276] Warniof the sceIo defAction is used when stating. This is broken anyway so skipping for now. --- Core/HLE/sceIo.cpp | 8 ++++++++ Core/HLE/sceIo.h | 1 + Core/HLE/sceKernel.cpp | 1 + 3 files changed, 10 insertions(+) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 70af694f7b..afe2c8615c 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -204,6 +204,14 @@ void __IoInit() { pspFileSystem.Mount("flash1:", flash); } +void __IoDoState(PointerWrap &p) { + // TODO: defAction is hard to save, and not the right way anyway. + // Should probbly be an enum and on the FileNode anyway. + if (defAction != NULL) { + WARN_LOG(HLE, "FIXME: Savestate failure: deferred IO not saved yet."); + } +} + void __IoShutdown() { defAction = 0; defParam = 0; diff --git a/Core/HLE/sceIo.h b/Core/HLE/sceIo.h index 8015bd93d9..0f87cde613 100644 --- a/Core/HLE/sceIo.h +++ b/Core/HLE/sceIo.h @@ -22,6 +22,7 @@ #include "sceKernel.h" void __IoInit(); +void __IoDoState(PointerWrap &p); void __IoShutdown(); KernelObject *__KernelFileNodeObject(); KernelObject *__KernelDirListingObject(); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index ff3f9202f6..00904fd152 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -163,6 +163,7 @@ void __KernelDoState(PointerWrap &p) __SslDoState(p); __UmdDoState(p); __UsbDoState(p); + __IoDoState(p); __PPGeDoState(p); From 19aaca2705e62f3bb1dd554f62925d281637929f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 00:05:54 -0800 Subject: [PATCH 265/276] Start save stating audio, plus minor fixes. --- Common/FixedSizeQueue.h | 21 ++++++-- Core/CoreTiming.cpp | 2 + Core/HLE/__sceAudio.cpp | 27 ++++++++++ Core/HLE/__sceAudio.h | 1 + Core/HLE/sceAudio.h | 46 ++++++++++------ Core/HLE/sceCtrl.cpp | 2 + Core/HLE/sceKernel.cpp | 2 + Core/HLE/sceKernelMsgPipe.cpp | 5 +- Core/HLE/sceSas.cpp | 7 +++ Core/HLE/sceSas.h | 1 + Core/HW/SasAudio.cpp | 98 +++++++++++++++++++++++++++++++++-- Core/HW/SasAudio.h | 11 +++- 12 files changed, 196 insertions(+), 27 deletions(-) diff --git a/Common/FixedSizeQueue.h b/Common/FixedSizeQueue.h index 55bf3015ae..b7c9b4d458 100644 --- a/Common/FixedSizeQueue.h +++ b/Common/FixedSizeQueue.h @@ -95,9 +95,24 @@ public: return N - count_; } - bool empty() { - return count_; - } + bool empty() { + return count_ == 0; + } + + void DoState(PointerWrap &p) { + int size = N; + p.Do(size); + if (size != N) + { + ERROR_LOG(HLE, "Savestate failure: Incompatible queue size."); + return; + } + p.DoArray(storage_, N); + p.Do(head_); + p.Do(tail_); + p.Do(count_); + p.DoMarker("FixedSizeQueue"); + } private: T *storage_; diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 504d28fb5b..01f6627a3b 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -550,6 +550,8 @@ void Event_DoState(PointerWrap &p, BaseEvent *ev) void DoState(PointerWrap &p) { + std::lock_guard lk(externalEventSection); + int n = (int) event_types.size(); p.Do(n); // These (should) be filled in later by the modules. diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 7676ac0ea6..48261e457b 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -73,6 +73,33 @@ void __AudioInit() chans[i].clear(); } +void __AudioDoState(PointerWrap &p) +{ + section.lock(); + + p.Do(eventAudioUpdate); + CoreTiming::RestoreRegisterEvent(eventAudioUpdate, "AudioUpdate", &hleAudioUpdate); + p.Do(eventHostAudioUpdate); + CoreTiming::RestoreRegisterEvent(eventHostAudioUpdate, "AudioUpdateHost", &hleAudioUpdate); + + p.Do(mixFrequency); + outAudioQueue.DoState(p); + + int chanCount = ARRAY_SIZE(chans); + p.Do(chanCount); + if (chanCount != ARRAY_SIZE(chans)) + { + ERROR_LOG(HLE, "Savestate failure: different number of audio channels."); + section.unlock(); + return; + } + for (int i = 0; i < chanCount; ++i) + chans[i].DoState(p); + + section.unlock(); + p.DoMarker("sceAudio"); +} + void __AudioShutdown() { for (int i = 0; i < 8; i++) diff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h index 196c16a7b8..21a83ef953 100644 --- a/Core/HLE/__sceAudio.h +++ b/Core/HLE/__sceAudio.h @@ -22,6 +22,7 @@ // Easy interface for sceAudio to write to, to keep the complexity in check. void __AudioInit(); +void __AudioDoState(PointerWrap &p); void __AudioUpdate(); void __AudioShutdown(); void __AudioSetOutputFrequency(int freq); diff --git a/Core/HLE/sceAudio.h b/Core/HLE/sceAudio.h index ba37523c36..013b818bde 100644 --- a/Core/HLE/sceAudio.h +++ b/Core/HLE/sceAudio.h @@ -40,41 +40,53 @@ enum PspAudioFrequencies { PSP_AUDIO_FREQ_44K = 44100, PSP_AUDIO_FREQ_48K = 48 struct AudioChannel { - AudioChannel() { + AudioChannel() { clear(); } - // PSP side + // PSP side - bool reserved; + bool reserved; - // last sample address - u32 sampleAddress; - u32 sampleCount; // Number of samples written in each OutputBlocking + // last sample address + u32 sampleAddress; + u32 sampleCount; // Number of samples written in each OutputBlocking - int leftVolume; - int rightVolume; + int leftVolume; + int rightVolume; - int format; + int format; SceUID waitingThread; - // PC side - should probably split out + // PC side - should probably split out - // We copy samples as they are written into this simple ring buffer. - // Might try something more efficient later. - FixedSizeQueue sampleQueue; + // We copy samples as they are written into this simple ring buffer. + // Might try something more efficient later. + FixedSizeQueue sampleQueue; - void clear() { - reserved = false; + void DoState(PointerWrap &p) { + p.Do(reserved); + p.Do(sampleAddress); + p.Do(sampleCount); + p.Do(leftVolume); + p.Do(rightVolume); + p.Do(format); + p.Do(waitingThread); + sampleQueue.DoState(p); + p.DoMarker("AudioChannel"); + } + + void clear() { + reserved = false; waitingThread = 0; leftVolume = 0; rightVolume = 0; format = 0; sampleAddress = 0; sampleCount = 0; - sampleQueue.clear(); - } + sampleQueue.clear(); + } }; extern AudioChannel chans[8]; diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index fbaac32477..4fbc8bb455 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -286,6 +286,8 @@ void __CtrlInit() void __CtrlDoState(PointerWrap &p) { + std::lock_guard guard(ctrlMutex); + p.Do(analogEnabled); p.Do(ctrlLatchBufs); p.Do(ctrlOldButtons); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 00904fd152..0c450708cb 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -156,10 +156,12 @@ void __KernelDoState(PointerWrap &p) __KernelSemaDoState(p); // TODO: non-kernel modules + __AudioDoState(p); __CtrlDoState(p); __FontDoState(p); __ImposeDoState(p); __PowerDoState(p); + __SasDoState(p); __SslDoState(p); __UmdDoState(p); __UsbDoState(p); diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 8d60cccf48..80c99cd623 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -150,7 +150,10 @@ struct MsgPipe : public KernelObject p.Do(nmp); p.Do(sendWaitingThreads); p.Do(receiveWaitingThreads); - p.DoArray(buffer, nmp.bufSize); + bool hasBuffer = buffer != NULL; + p.Do(hasBuffer); + if (hasBuffer) + p.DoArray(buffer, nmp.bufSize); p.DoMarker("MsgPipe"); } diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 7693592688..45693a80e5 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -50,6 +50,13 @@ void __SasInit() { sas = new SasInstance(); } +void __SasDoState(PointerWrap &p) { + if (sas != NULL) { + sas->DoState(p); + } + p.DoMarker("sceSas"); +} + void __SasShutdown() { delete sas; sas = 0; diff --git a/Core/HLE/sceSas.h b/Core/HLE/sceSas.h index 58efddd75b..bf798dee45 100644 --- a/Core/HLE/sceSas.h +++ b/Core/HLE/sceSas.h @@ -18,6 +18,7 @@ #pragma once void __SasInit(); +void __SasDoState(PointerWrap &p); void __SasShutdown(); void Register_sceSasCore(); diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index ed17365368..1da73af6be 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -27,14 +27,14 @@ static const double f[5][2] = { 98.0 / 64.0, -55.0 / 64.0 }, { 122.0 / 64.0, -60.0 / 64.0 } }; -void VagDecoder::Start(u8 *data, int vagSize, bool loopEnabled) { +void VagDecoder::Start(u32 dataPtr, int vagSize, bool loopEnabled) { loopEnabled_ = loopEnabled; loopAtNextBlock_ = false; loopStartBlock_ = 0; numBlocks_ = vagSize / 16; end_ = false; - data_ = data; - read_ = data; + data_ = Memory::GetPointer(dataPtr); + read_ = Memory::GetPointer(dataPtr); curSample = 28; curBlock_ = -1; s_1 = 0.0; // per block? @@ -99,6 +99,28 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { } } +void VagDecoder::DoState(PointerWrap &p) { + p.DoArray(samples, ARRAY_SIZE(samples)); + p.Do(curSample); + p.Do(dataPtr_); + int diff = read_ - data_; + p.Do(diff); + if (p.mode == p.MODE_READ) { + data_ = Memory::GetPointer(dataPtr_); + read_ = data_ + diff; + } + p.Do(curBlock_); + p.Do(loopStartBlock_); + p.Do(numBlocks_); + + p.Do(s_1); + p.Do(s_2); + p.Do(loopEnabled_); + p.Do(loopAtNextBlock_); + p.Do(end_); + p.DoMarker("VagDecoder"); +} + // http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java int simpleRate(int n) { @@ -190,6 +212,7 @@ SasInstance::~SasInstance() { void SasInstance::SetGrainSize(int newGrainSize) { grainSize = newGrainSize; + // If you change the sizes here, don't forget DoState(). if (mixBuffer) delete [] mixBuffer; if (sendBuffer) @@ -303,6 +326,40 @@ void SasInstance::Mix(u32 outAddr) { } } +void SasInstance::DoState(PointerWrap &p) { + p.Do(grainSize); + if (p.mode == p.MODE_READ) { + SetGrainSize(grainSize); + } + + p.Do(maxVoices); + p.Do(sampleRate); + p.Do(outputMode); + + if (mixBuffer != NULL) { + p.DoArray(mixBuffer, grainSize * 2); + } + if (sendBuffer != NULL) { + p.DoArray(sendBuffer, grainSize * 2); + } + if (resampleBuffer != NULL) { + p.DoArray(resampleBuffer, grainSize * 4 + 2); + } + + int n = PSP_SAS_VOICES_MAX; + p.Do(n); + if (n != PSP_SAS_VOICES_MAX) + { + ERROR_LOG(HLE, "Savestate failure: wrong number of SAS voices"); + return; + } + for (int i = 0; i < n; ++i) + voices[i].DoState(p); + p.Do(waveformEffect); + + p.DoMarker("SasInstance"); +} + void SasVoice::Reset() { resampleHist[0] = 0; resampleHist[1] = 0; @@ -313,7 +370,7 @@ void SasVoice::KeyOn() { switch (type) { case VOICETYPE_VAG: if (Memory::IsValidAddress(vagAddr)) { - vag.Start(Memory::GetPointer(vagAddr), vagSize, loop); + vag.Start(vagAddr, vagSize, loop); } else { ERROR_LOG(SAS, "Invalid VAG address %08x", vagAddr); return; @@ -336,11 +393,42 @@ void SasVoice::ChangedParams(bool changedVag) { if (!playing && on) { playing = true; if (changedVag) - vag.Start(Memory::GetPointer(vagAddr), vagSize, loop); + vag.Start(vagAddr, vagSize, loop); } // TODO: restart VAG somehow } +void SasVoice::DoState(PointerWrap &p) { + p.Do(playing); + p.Do(paused); + p.Do(on); + p.Do(type); + + p.Do(vagAddr); + p.Do(vagSize); + p.Do(pcmAddr); + p.Do(pcmSize); + p.Do(sampleRate); + + p.Do(sampleFrac); + p.Do(pitch); + p.Do(loop); + + p.Do(noiseFreq); + + p.Do(volumeLeft); + p.Do(volumeRight); + p.Do(volumeLeftSend); + p.Do(volumeRightSend); + p.DoArray(resampleHist, ARRAY_SIZE(resampleHist)); + + p.Do(envelope); + + vag.DoState(p); + + p.DoMarker("SasVoice"); +} + // This is horribly stolen from JPCSP. // Need to find a real solution. static const short expCurve[] = { diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index b32ba7d347..71103c6386 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -23,6 +23,7 @@ #pragma once #include "../Globals.h" +#include "../../Common/ChunkFile.h" enum { PSP_SAS_VOICES_MAX = 32, @@ -77,7 +78,7 @@ enum VoiceType { class VagDecoder { public: VagDecoder() : data_(0), read_(0) {} - void Start(u8 *data, int vagSize, bool loopEnabled); + void Start(u32 dataPtr, int vagSize, bool loopEnabled); void GetSamples(s16 *outSamples, int numSamples); @@ -88,10 +89,14 @@ public: return *read_++; } + void DoState(PointerWrap &p); + private: double samples[28]; int curSample; + // Original pointer, for save states. + u32 dataPtr_; u8 *data_; u8 *read_; int curBlock_; @@ -180,6 +185,8 @@ struct SasVoice void KeyOff(); void ChangedParams(bool changedVag); + void DoState(PointerWrap &p); + bool playing; bool paused; // a voice can be playing AND paused. In that case, it won't play. bool on; // key-on, key-off. @@ -228,6 +235,8 @@ public: void Mix(u32 outAddr); + void DoState(PointerWrap &p); + SasVoice voices[PSP_SAS_VOICES_MAX]; WaveformEffect waveformEffect; From 7a2adfd8a578266971edc8316461e1b7cf389be8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 02:09:44 -0800 Subject: [PATCH 266/276] Don't store pointers in VagDecoder directly. I'm assuming it's fine to not fix read_ when end_ happens. Shouldn't be any performance penality, really. --- Core/HW/SasAudio.cpp | 76 +++++++++----------------------------------- Core/HW/SasAudio.h | 16 ++-------- 2 files changed, 18 insertions(+), 74 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 1da73af6be..3977537af5 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -27,25 +27,25 @@ static const double f[5][2] = { 98.0 / 64.0, -55.0 / 64.0 }, { 122.0 / 64.0, -60.0 / 64.0 } }; -void VagDecoder::Start(u32 dataPtr, int vagSize, bool loopEnabled) { +void VagDecoder::Start(u32 data, int vagSize, bool loopEnabled) { loopEnabled_ = loopEnabled; loopAtNextBlock_ = false; loopStartBlock_ = 0; numBlocks_ = vagSize / 16; end_ = false; - data_ = Memory::GetPointer(dataPtr); - read_ = Memory::GetPointer(dataPtr); + data_ = data; + read_ = data; curSample = 28; curBlock_ = -1; s_1 = 0.0; // per block? s_2 = 0.0; } -void VagDecoder::DecodeBlock() { - int predict_nr = GetByte(); +void VagDecoder::DecodeBlock(u8 *&readp) { + int predict_nr = *readp++; int shift_factor = predict_nr & 0xf; predict_nr >>= 4; - int flags = GetByte(); + int flags = *readp++; if (flags == 7) { end_ = true; return; @@ -57,7 +57,7 @@ void VagDecoder::DecodeBlock() { loopAtNextBlock_ = true; } for (int i = 0; i < 28; i += 2) { - int d = GetByte(); + int d = *readp++; int s = (short)((d & 0xf) << 12); samples[i] = (double)(s >> shift_factor); s = (short)((d & 0xf0) << 8); @@ -80,15 +80,19 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { memset(outSamples, 0, numSamples * sizeof(s16)); return; } + u8 *readp = Memory::GetPointer(read_); + u8 *origp = readp; for (int i = 0; i < numSamples; i++) { if (curSample == 28) { if (loopAtNextBlock_) { read_ = data_ + 16 * loopStartBlock_; + readp = Memory::GetPointer(read_); + origp = readp; curBlock_ = loopStartBlock_; s_1 = 0.0; s_2 = 0.0; } - DecodeBlock(); + DecodeBlock(readp); if (end_) { // Clear the rest of the buffer and return. memset(&outSamples[i], 0, (numSamples - i) * sizeof(s16)); @@ -97,28 +101,10 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { } outSamples[i] = end_ ? 0 : samples[curSample++]; } -} -void VagDecoder::DoState(PointerWrap &p) { - p.DoArray(samples, ARRAY_SIZE(samples)); - p.Do(curSample); - p.Do(dataPtr_); - int diff = read_ - data_; - p.Do(diff); - if (p.mode == p.MODE_READ) { - data_ = Memory::GetPointer(dataPtr_); - read_ = data_ + diff; + if (readp > origp) { + read_ += readp - origp; } - p.Do(curBlock_); - p.Do(loopStartBlock_); - p.Do(numBlocks_); - - p.Do(s_1); - p.Do(s_2); - p.Do(loopEnabled_); - p.Do(loopAtNextBlock_); - p.Do(end_); - p.DoMarker("VagDecoder"); } // http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java @@ -353,8 +339,7 @@ void SasInstance::DoState(PointerWrap &p) { ERROR_LOG(HLE, "Savestate failure: wrong number of SAS voices"); return; } - for (int i = 0; i < n; ++i) - voices[i].DoState(p); + p.DoArray(voices, ARRAY_SIZE(voices)); p.Do(waveformEffect); p.DoMarker("SasInstance"); @@ -398,37 +383,6 @@ void SasVoice::ChangedParams(bool changedVag) { // TODO: restart VAG somehow } -void SasVoice::DoState(PointerWrap &p) { - p.Do(playing); - p.Do(paused); - p.Do(on); - p.Do(type); - - p.Do(vagAddr); - p.Do(vagSize); - p.Do(pcmAddr); - p.Do(pcmSize); - p.Do(sampleRate); - - p.Do(sampleFrac); - p.Do(pitch); - p.Do(loop); - - p.Do(noiseFreq); - - p.Do(volumeLeft); - p.Do(volumeRight); - p.Do(volumeLeftSend); - p.Do(volumeRightSend); - p.DoArray(resampleHist, ARRAY_SIZE(resampleHist)); - - p.Do(envelope); - - vag.DoState(p); - - p.DoMarker("SasVoice"); -} - // This is horribly stolen from JPCSP. // Need to find a real solution. static const short expCurve[] = { diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 71103c6386..c2da15a969 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -82,23 +82,15 @@ public: void GetSamples(s16 *outSamples, int numSamples); - void DecodeBlock(); + void DecodeBlock(u8 *&readp); bool End() const { return end_; } - u8 GetByte() { - return *read_++; - } - - void DoState(PointerWrap &p); - private: double samples[28]; int curSample; - // Original pointer, for save states. - u32 dataPtr_; - u8 *data_; - u8 *read_; + u32 data_; + u32 read_; int curBlock_; int loopStartBlock_; int numBlocks_; @@ -185,8 +177,6 @@ struct SasVoice void KeyOff(); void ChangedParams(bool changedVag); - void DoState(PointerWrap &p); - bool playing; bool paused; // a voice can be playing AND paused. In that case, it won't play. bool on; // key-on, key-off. From 5999fac10dc983128b81c03f6fe63e359fcf6f71 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 02:22:39 -0800 Subject: [PATCH 267/276] Start saving the state of the GPU. Not 100% sure this is all that's needed, but let's try it. --- Common/ChunkFile.h | 9 ++++++++- Core/HLE/sceDisplay.cpp | 39 ++++++++++++++++++++++++++++++--------- Core/HLE/sceDisplay.h | 2 ++ Core/HLE/sceGe.cpp | 11 +++++++++++ Core/HLE/sceGe.h | 1 + Core/HLE/sceKernel.cpp | 2 ++ 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Common/ChunkFile.h b/Common/ChunkFile.h index f6e3f0a0ce..1671cecc8a 100644 --- a/Common/ChunkFile.h +++ b/Common/ChunkFile.h @@ -154,10 +154,17 @@ public: // Store vectors. template void Do(std::vector &x) + { + T dv; + Do(x, dv); + } + + template + void Do(std::vector &x, T &default_val) { u32 vec_size = (u32)x.size(); Do(vec_size); - x.resize(vec_size); + x.resize(vec_size, default_val); if (vec_size > 0) DoArray(&x[0], vec_size); } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index ac780633a2..2eaa41f069 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -52,6 +52,13 @@ struct FrameBufferState { int pspFramebufLinesize; }; +struct WaitVBlankInfo +{ + WaitVBlankInfo(u32 tid) : threadID(tid), vcountUnblock(0) {} + u32 threadID; + int vcountUnblock; // what was this for again? +}; + // STATE BEGIN static FrameBufferState framebuf; static FrameBufferState latchedFramebuf; @@ -67,8 +74,11 @@ static int isVblank; static bool hasSetMode; double lastFrameTime; +std::vector vblankWaitingThreads; + // STATE END +// Called when vblank happens (like an internal interrupt.) Not part of state, should be static. std::vector vblankListeners; // The vblank period is 731.5 us (0.7315 ms) @@ -80,15 +90,6 @@ enum { PSP_DISPLAY_SETBUF_NEXTFRAME = 1 }; -struct WaitVBlankInfo -{ - WaitVBlankInfo(u32 tid) : threadID(tid), vcountUnblock(0) {} - u32 threadID; - int vcountUnblock; // what was this for again? -}; - -std::vector vblankWaitingThreads; - void hleEnterVblank(u64 userdata, int cyclesLate); void hleLeaveVblank(u64 userdata, int cyclesLate); @@ -114,6 +115,26 @@ void __DisplayInit() { InitGfxState(); } +void __DisplayDoState(PointerWrap &p) { + p.Do(framebuf); + p.Do(latchedFramebuf); + p.Do(framebufIsLatched); + p.Do(hCount); + p.Do(hCountTotal); + p.Do(vCount); + p.Do(isVblank); + p.Do(hasSetMode); + p.Do(lastFrameTime); + p.Do(vblankWaitingThreads, WaitVBlankInfo(0)); + + p.Do(enterVblankEvent); + CoreTiming::RestoreRegisterEvent(enterVblankEvent, "EnterVBlank", &hleEnterVblank); + p.Do(leaveVblankEvent); + CoreTiming::RestoreRegisterEvent(leaveVblankEvent, "LeaveVBlank", &hleLeaveVblank); + + p.DoMarker("sceDisplay"); +} + void __DisplayShutdown() { vblankListeners.clear(); vblankWaitingThreads.clear(); diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index c7b1afc8ff..c75faf93f7 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -18,6 +18,7 @@ #pragma once void __DisplayInit(); +void __DisplayDoState(PointerWrap &p); void __DisplayShutdown(); void Register_sceDisplay(); @@ -26,4 +27,5 @@ void Register_sceDisplay(); bool __DisplayFrameDone(); typedef void (*VblankCallback)(); +// Listen for vblank events. Only register during init. void __DisplayListenVblank(VblankCallback callback); diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 8cbff40b80..023ac3aaa0 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -33,6 +33,17 @@ void __GeInit() state = 0; } +void __GeDoState(PointerWrap &p) +{ + p.Do(state); + p.Do(gstate); + p.Do(gstate_c); + + ReapplyGfxState(); + gpu->InvalidateCache(0, -1); + p.DoMarker("sceGe"); +} + void __GeShutdown() { diff --git a/Core/HLE/sceGe.h b/Core/HLE/sceGe.h index 7b92c863b8..d6a19a0767 100644 --- a/Core/HLE/sceGe.h +++ b/Core/HLE/sceGe.h @@ -37,6 +37,7 @@ typedef struct PspGeCallbackData void Register_sceGe_user(); void __GeInit(); +void __GeDoState(PointerWrap &p); void __GeShutdown(); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 0c450708cb..b9edf154cc 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -158,7 +158,9 @@ void __KernelDoState(PointerWrap &p) // TODO: non-kernel modules __AudioDoState(p); __CtrlDoState(p); + __DisplayDoState(p); __FontDoState(p); + __GeDoState(p); __ImposeDoState(p); __PowerDoState(p); __SasDoState(p); From e665618891a1212847d06cddaf906818e2d32d9a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 03:54:16 -0800 Subject: [PATCH 268/276] Fix kernel object loading (ouch) from save states. Also a fix to SAS voices not saving right. --- Core/HLE/sceKernel.cpp | 1 + Core/HW/SasAudio.cpp | 28 +++++++++++++++++++++------- Core/HW/SasAudio.h | 1 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index b9edf154cc..64909528d0 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -363,6 +363,7 @@ void KernelObjectPool::DoState(PointerWrap &p) { p.Do(type); pool[i] = CreateByIDType(type); + pool[i]->uid = i + handleOffset; // Already logged an error. if (pool[i] == NULL) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 3977537af5..6eb53d3f0d 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -190,9 +190,19 @@ SasInstance::SasInstance() } SasInstance::~SasInstance() { - delete [] mixBuffer; - delete [] sendBuffer; - delete [] resampleBuffer; + ClearGrainSize(); +} + +void SasInstance::ClearGrainSize() { + if (mixBuffer) + delete [] mixBuffer; + if (sendBuffer) + delete [] sendBuffer; + if (resampleBuffer) + delete [] resampleBuffer; + mixBuffer = NULL; + sendBuffer = NULL; + resampleBuffer = NULL; } void SasInstance::SetGrainSize(int newGrainSize) { @@ -315,20 +325,24 @@ void SasInstance::Mix(u32 outAddr) { void SasInstance::DoState(PointerWrap &p) { p.Do(grainSize); if (p.mode == p.MODE_READ) { - SetGrainSize(grainSize); + if (grainSize > 0) { + SetGrainSize(grainSize); + } else { + ClearGrainSize(); + } } p.Do(maxVoices); p.Do(sampleRate); p.Do(outputMode); - if (mixBuffer != NULL) { + if (mixBuffer != NULL && grainSize > 0) { p.DoArray(mixBuffer, grainSize * 2); } - if (sendBuffer != NULL) { + if (sendBuffer != NULL && grainSize > 0) { p.DoArray(sendBuffer, grainSize * 2); } - if (resampleBuffer != NULL) { + if (resampleBuffer != NULL && grainSize > 0) { p.DoArray(resampleBuffer, grainSize * 4 + 2); } diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index c2da15a969..1c204782fa 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -212,6 +212,7 @@ public: SasInstance(); ~SasInstance(); + void ClearGrainSize(); void SetGrainSize(int newGrainSize); int GetGrainSize() const { return grainSize; } From 644e6b615cc1dcbc79c08ab84aae55b0cfbcca4a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 12:38:00 -0800 Subject: [PATCH 269/276] Fix memory leak in msgpipe when loading state. --- Core/HLE/sceKernelMsgPipe.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 80c99cd623..6e727c7da0 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -56,6 +56,13 @@ struct MsgPipe : public KernelObject static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_MPPID; } int GetIDType() const { return SCE_KERNEL_TMID_Mpipe; } + MsgPipe() : buffer(NULL) {} + ~MsgPipe() + { + if (buffer != NULL) + delete [] buffer; + } + void AddWaitingThread(std::vector &list, SceUID id, u32 addr, u32 size, int waitMode, u32 transferredBytesAddr, bool usePrio) { MsgPipeWaitingThread thread = { id, addr, size, size, waitMode, transferredBytesAddr }; @@ -211,10 +218,6 @@ void sceKernelDeleteMsgPipe() RETURN(error); return; } - if (m->buffer != 0) - { - delete [] m->buffer; - } for (u32 i = 0; i < m->sendWaitingThreads.size(); i++) { __KernelResumeThreadFromWait(m->sendWaitingThreads[i].id); From bcecd881b189a86ad8886eeaa4259aac29d4e501 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 13:01:46 -0800 Subject: [PATCH 270/276] Savestate cleanup + be more careful with vectors. For some reason I debugged it going into std::string so I just made them all more explicit which fixed everything. --- Core/HLE/HLE.cpp | 2 +- Core/HLE/sceCtrl.cpp | 3 ++- Core/HLE/sceKernelEventFlag.cpp | 2 +- Core/HLE/sceKernelMbx.cpp | 2 +- Core/HLE/sceKernelModule.cpp | 1 + Core/HLE/sceKernelMsgPipe.cpp | 8 ++++++-- Core/HLE/sceKernelMutex.cpp | 6 ++++-- Core/HLE/sceKernelSemaphore.cpp | 3 ++- Core/HLE/sceKernelThread.cpp | 4 ++-- Core/HW/SasAudio.cpp | 1 + Core/Util/BlockAllocator.cpp | 3 +-- 11 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 7d5c426c49..ef81fa2a23 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -60,7 +60,7 @@ void HLEInit() void HLEDoState(PointerWrap &p) { - p.Do(unresolvedSyscalls); + p.Do(unresolvedSyscalls, Syscall()); p.DoMarker("HLE"); } diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 4fbc8bb455..234bb3dc5f 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -303,7 +303,8 @@ void __CtrlDoState(PointerWrap &p) p.Do(ctrlCycle); - p.Do(waitingThreads); + SceUID dv = 0; + p.Do(waitingThreads, dv); p.Do(ctrlTimer); CoreTiming::RestoreRegisterEvent(ctrlTimer, "CtrlSampleTimer", __CtrlTimerUpdate); diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 80471c4c4d..d57d63c9bd 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -66,7 +66,7 @@ public: virtual void DoState(PointerWrap &p) { p.Do(nef); - p.Do(waitingThreads); + p.Do(waitingThreads, EventFlagTh()); p.DoMarker("EventFlag"); } diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index 34aea59532..205a97460d 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -156,7 +156,7 @@ struct Mbx : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nmb); - p.Do(waitingThreads); + p.Do(waitingThreads, MbxWaitingThread()); p.DoMarker("Mbx"); } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 701b51297c..8f35526859 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -145,6 +145,7 @@ public: virtual void DoState(PointerWrap &p) { p.Do(moduleID_); p.Do(retValAddr); + p.DoMarker("AfterModuleEntryCall"); } static Action *Create() { return new AfterModuleEntryCall; diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 6e727c7da0..92ef03c74a 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -155,12 +155,16 @@ struct MsgPipe : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nmp); - p.Do(sendWaitingThreads); - p.Do(receiveWaitingThreads); + p.Do(sendWaitingThreads, MsgPipeWaitingThread()); + p.Do(receiveWaitingThreads, MsgPipeWaitingThread()); bool hasBuffer = buffer != NULL; p.Do(hasBuffer); if (hasBuffer) + { + if (buffer == NULL) + buffer = new u8[nmp.bufSize]; p.DoArray(buffer, nmp.bufSize); + } p.DoMarker("MsgPipe"); } diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index a6243fff08..a591e4ce6d 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -66,7 +66,8 @@ struct Mutex : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nm); - p.Do(waitingThreads); + SceUID dv = 0; + p.Do(waitingThreads, dv); p.DoMarker("Mutex"); } @@ -115,7 +116,8 @@ struct LwMutex : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nm); - p.Do(waitingThreads); + SceUID dv = 0; + p.Do(waitingThreads, dv); p.DoMarker("LwMutex"); } diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 6e213ff31d..f9e5cd4e0b 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -60,7 +60,8 @@ struct Semaphore : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(ns); - p.Do(waitingThreads); + SceUID dv = 0; + p.Do(waitingThreads, dv); p.DoMarker("Semaphore"); } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 7732c558ce..e791219d2b 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -431,7 +431,6 @@ public: for (size_t i = 0; i < THREAD_CALLBACK_NUM_TYPES; ++i) { - std::set::iterator it, end; p.Do(registeredCallbacks[i]); p.Do(readyCallbacks[i]); } @@ -615,7 +614,8 @@ void __KernelThreadingDoState(PointerWrap &p) p.Do(intReturnHackAddr); p.Do(currentThread); - p.Do(threadqueue); + SceUID dv = 0; + p.Do(threadqueue, dv); p.DoArray(threadIdleID, ARRAY_SIZE(threadIdleID)); p.Do(dispatchEnabled); p.Do(curModule); diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 6eb53d3f0d..3845922fbe 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -336,6 +336,7 @@ void SasInstance::DoState(PointerWrap &p) { p.Do(sampleRate); p.Do(outputMode); + // SetGrainSize() / ClearGrainSize() should've made our buffers match. if (mixBuffer != NULL && grainSize > 0) { p.DoArray(mixBuffer, grainSize * 2); } diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index 66cc8484e7..d778012ab9 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -300,8 +300,7 @@ u32 BlockAllocator::GetTotalFreeBytes() void BlockAllocator::DoState(PointerWrap &p) { - Block default_value(0, 0, false); - p.Do(blocks, default_value); + p.Do(blocks, Block(0, 0, false)); p.Do(rangeStart_); p.Do(rangeSize_); p.Do(grain_); From fd2f609367c44e4fab47cf8bfba0b1621f6442d8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 13:36:37 -0800 Subject: [PATCH 271/276] Save the savedata and other dialog state. Although, hopefully it wouldn't be running anyway. --- Core/Dialog/PSPDialog.cpp | 8 ++++++++ Core/Dialog/PSPDialog.h | 2 ++ Core/Dialog/PSPMsgDialog.cpp | 12 ++++++++++++ Core/Dialog/PSPMsgDialog.h | 3 ++- Core/Dialog/PSPOskDialog.cpp | 13 +++++++++++++ Core/Dialog/PSPOskDialog.h | 1 + Core/Dialog/PSPSaveDialog.cpp | 16 ++++++++++++++++ Core/Dialog/PSPSaveDialog.h | 3 ++- Core/Dialog/SavedataParam.cpp | 23 +++++++++++++++++------ Core/Dialog/SavedataParam.h | 4 +++- Core/HLE/sceKernel.cpp | 4 ++-- Core/HLE/sceUtility.cpp | 9 +++++++++ Core/HLE/sceUtility.h | 1 + 13 files changed, 88 insertions(+), 11 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index daf9c967ce..9750fb917d 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -64,6 +64,14 @@ int PSPDialog::Update() return 0; } +void PSPDialog::DoState(PointerWrap &p) +{ + p.Do(status); + p.Do(lastButtons); + p.Do(buttons); + p.DoMarker("PSPDialog"); +} + bool PSPDialog::IsButtonPressed(int checkButton) { return (!(lastButtons & checkButton)) && (buttons & checkButton); diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index c9c06120c8..f4884cda13 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -19,6 +19,7 @@ #include "../Config.h" +#include "../../Common/ChunkFile.h" #define SCE_UTILITY_DIALOG_RESULT_SUCCESS 0 #define SCE_UTILITY_DIALOG_RESULT_CANCEL 1 @@ -47,6 +48,7 @@ public: virtual int Update(); virtual int Shutdown(); + virtual void DoState(PointerWrap &p); enum DialogStatus { diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 5d0fa4a06b..a5ef5ceb6e 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -206,3 +206,15 @@ int PSPMsgDialog::Shutdown() return PSPDialog::Shutdown(); } +void PSPMsgDialog::DoState(PointerWrap &p) +{ + p.Do(display); + p.Do(messageDialog); + p.Do(messageDialogAddr); + p.Do(yesnoChoice); + p.Do(okButtonImg); + p.Do(cancelButtonImg); + p.Do(okButtonFlag); + p.Do(cancelButtonFlag); + p.DoMarker("PSPMsgDialog"); +} diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index 80b1f24e9f..779a77f4e6 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -43,7 +43,8 @@ public: virtual int Init(unsigned int paramAddr); virtual int Update(); - int Shutdown(); + virtual int Shutdown(); + virtual void DoState(PointerWrap &p); private : void DisplayBack(); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 791a6d565d..abe367b96e 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -233,3 +233,16 @@ int PSPOskDialog::Update() return 0; } + +void PSPOskDialog::DoState(PointerWrap &p) +{ + p.Do(oskParams); + p.Do(oskData); + p.Do(oskDesc); + p.Do(oskIntext); + p.Do(oskOuttext); + p.Do(oskParamsAddr); + p.Do(selectedChar); + p.Do(inputChars); + p.DoMarker("PSPOskDialog"); +} diff --git a/Core/Dialog/PSPOskDialog.h b/Core/Dialog/PSPOskDialog.h index 387abc32b9..1683edf040 100644 --- a/Core/Dialog/PSPOskDialog.h +++ b/Core/Dialog/PSPOskDialog.h @@ -146,6 +146,7 @@ public: virtual int Init(u32 oskPtr); virtual int Update(); + virtual void DoState(PointerWrap &p); private: void HackyGetStringWide(std::string& _string, const u32 em_address); void RenderKeyboard(); diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 44d110f5ab..4c02582986 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -706,3 +706,19 @@ int PSPSaveDialog::Shutdown() return 0; } +void PSPSaveDialog::DoState(PointerWrap &p) +{ + p.Do(display); + param.DoState(p); + p.Do(request); + // Just reset it. + param.SetPspParam(&request); + p.Do(requestAddr); + p.Do(currentSelectedSave); + p.Do(yesnoChoice); + p.Do(okButtonImg); + p.Do(cancelButtonImg); + p.Do(okButtonFlag); + p.Do(cancelButtonFlag); + p.DoMarker("PSPSaveDialog"); +} diff --git a/Core/Dialog/PSPSaveDialog.h b/Core/Dialog/PSPSaveDialog.h index c8149b7702..1e9eaea054 100644 --- a/Core/Dialog/PSPSaveDialog.h +++ b/Core/Dialog/PSPSaveDialog.h @@ -66,7 +66,8 @@ public: virtual int Init(int paramAddr); virtual int Update(); - int Shutdown(); + virtual int Shutdown(); + virtual void DoState(PointerWrap &p); private : diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 6fd27dd0e9..4abafe0c73 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -80,9 +80,9 @@ namespace SavedataParam::SavedataParam() : pspParam(0) , selectedSave(0) - , saveNameListData(0) , saveDataList(0) , saveNameListDataCount(0) + , saveDataListCount(0) { } @@ -431,23 +431,24 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) listEmptyFile = false; } + char (*saveNameListData)[20]; if (param->saveNameList != 0) { saveNameListData = (char(*)[20])Memory::GetPointer(param->saveNameList); // Get number of fileName in array - int count = 0; + saveDataListCount = 0; do { - count++; - } while(saveNameListData[count][0] != 0); + saveDataListCount++; + } while(saveNameListData[saveDataListCount][0] != 0); Clear(); - saveDataList = new SaveFileInfo[count]; + saveDataList = new SaveFileInfo[saveDataListCount]; // get and stock file info for each file int realCount = 0; - for (int i = 0; i < count; i++) + for (int i = 0; i < saveDataListCount; i++) { DEBUG_LOG(HLE,"Name : %s",saveNameListData[i]); @@ -600,3 +601,13 @@ void SavedataParam::SetSelectedSave(int idx) { selectedSave = idx; } + +void SavedataParam::DoState(PointerWrap &p) +{ + // pspParam is handled in PSPSaveDialog. + p.Do(selectedSave); + p.Do(saveDataListCount); + p.Do(saveNameListDataCount); + p.DoArray(saveDataList, saveDataListCount); + p.DoMarker("SavedataParam"); +} diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 78b6d8fec0..4a1384a8ac 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -166,14 +166,16 @@ public: int GetSelectedSave(); void SetSelectedSave(int idx); + void DoState(PointerWrap &p); + private: void Clear(); void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName); SceUtilitySavedataParam* pspParam; int selectedSave; - char (*saveNameListData)[20]; SaveFileInfo* saveDataList; + int saveDataListCount; int saveNameListDataCount; }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 64909528d0..b590393c49 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -155,19 +155,19 @@ void __KernelDoState(PointerWrap &p) __KernelMutexDoState(p); __KernelSemaDoState(p); - // TODO: non-kernel modules __AudioDoState(p); __CtrlDoState(p); __DisplayDoState(p); __FontDoState(p); __GeDoState(p); __ImposeDoState(p); + __IoDoState(p); __PowerDoState(p); __SasDoState(p); __SslDoState(p); __UmdDoState(p); + __UtilityDoState(p); __UsbDoState(p); - __IoDoState(p); __PPGeDoState(p); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index bebd56436d..c5dbc84934 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -39,6 +39,15 @@ void __UtilityInit() SavedataParam::Init(); } +void __UtilityDoState(PointerWrap &p) +{ + saveDialog.DoState(p); + msgDialog.DoState(p); + oskDialog.DoState(p); + netDialog.DoState(p); + p.DoMarker("sceUtility"); +} + void __UtilityShutdown() { saveDialog.Shutdown(); diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index ba85cd06c9..1518332972 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -18,6 +18,7 @@ #pragma once void __UtilityInit(); +void __UtilityDoState(PointerWrap &p); void __UtilityShutdown(); void Register_sceUtility(); From 94969c4eadb0aaf0794115be2f71c7e7ddff1f35 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 13:50:59 -0800 Subject: [PATCH 272/276] Add some basic Windows UI for save states. --- Windows/WndMainWindow.cpp | 19 ++++++++++++++----- Windows/WndMainWindow.h | 1 + Windows/ppsspp.rc | Bin 28864 -> 29384 bytes 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index debfc928bd..1e8a469a6d 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -18,8 +18,9 @@ #include "main.h" #include "../Core/Core.h" -#include "../Core/System.h" #include "../Core/MemMap.h" +#include "../Core/SaveState.h" +#include "../Core/System.h" #include "EmuThread.h" #include "resource.h" @@ -312,18 +313,18 @@ namespace MainWindow break; case ID_FILE_LOADSTATE: - if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.gcs)\0*.gcs\0All files\0*.*\0\0","gcs",fn)) + if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppssppst)\0*.ppssppst\0All files\0*.*\0\0","ppssppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); - SetCursor(LoadCursor(0,IDC_ARROW)); + SaveState::Load(fn, SaveStateActionFinished); } break; case ID_FILE_SAVESTATE: - if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.gcs)\0*.gcs\0All files\0*.*\0\0","gcs",fn)) + if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppssppst)\0*.ppssppst\0All files\0*.*\0\0","ppssppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); - SetCursor(LoadCursor(0,IDC_ARROW)); + SaveState::Save(fn, SaveStateActionFinished); } break; @@ -766,6 +767,14 @@ namespace MainWindow } } + void SaveStateActionFinished(bool result) + { + // TODO: Improve messaging? + if (!result) + MessageBox(0, "Savestate failure. Please try again later.", "Sorry", MB_OK); + SetCursor(LoadCursor(0, IDC_ARROW)); + } + void SetNextState(CoreState state) { nextState = state; diff --git a/Windows/WndMainWindow.h b/Windows/WndMainWindow.h index 7aaaaab423..b58823ca25 100644 --- a/Windows/WndMainWindow.h +++ b/Windows/WndMainWindow.h @@ -17,6 +17,7 @@ namespace MainWindow void SetPlaying(const char*text); void BrowseAndBoot(); void SetNextState(CoreState state); + void SaveStateActionFinished(bool result); void _ViewFullScreen(HWND hWnd); void _ViewNormal(HWND hWnd); } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 3c691428661e75dc9a4105a434f708ed81e8a7dd..e9561bdac4468508cfa78c949648e089abb2f193 100644 GIT binary patch delta 327 zcmX@`knzM*#tqkunK>CaCttJ_m-S)DXGmm7VNhTQW+(x&N*GcZVt}L@g9(Gul@>KO{;` zR&e5BHDrij(3$)&%6sy!I4P*8z+|g;{sUS`tKEgA2>#oFtfjv(5XGxC8)-Vk$)d From 269a776363fef304c398e62e9561a0e5614ee870 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Dec 2012 14:13:34 -0800 Subject: [PATCH 273/276] Add a simple devctl to verify the state. Could do more, but this should be useful. --- Core/HLE/sceIo.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index afe2c8615c..a7f8e00564 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -22,6 +22,7 @@ #include "../System.h" #include "../Config.h" +#include "../SaveState.h" #include "HLE.h" #include "../MIPS/MIPS.h" #include "../HW/MemoryStick.h" @@ -658,7 +659,12 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr, } case 3: // EMULATOR_DEVCTL__IS_EMULATOR if (Memory::IsValidAddress(outPtr)) - Memory::Write_U32(1, outPtr); // TODO: Make a headless mode for running tests! + Memory::Write_U32(1, outPtr); + return 0; + case 4: // EMULATOR_DEVCTL__VERIFY_STATE + // Note that this is async, and makes sure the save state matches up. + SaveState::Verify(); + // TODO: Maybe save/load to a file just to be sure? return 0; } From 95c4e0b9c497fee97821b58c1a080d76efd2d3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 28 Dec 2012 23:33:00 +0100 Subject: [PATCH 274/276] Quick build fix for gcc --- Core/HLE/HLE.cpp | 4 +++- Core/HLE/sceDisplay.cpp | 3 ++- Core/HLE/sceKernelEventFlag.cpp | 5 +++-- Core/HLE/sceKernelInterrupt.cpp | 3 ++- Core/HLE/sceKernelMbx.cpp | 3 ++- Core/HLE/sceKernelMsgPipe.cpp | 5 +++-- Core/SaveState.cpp | 2 +- Core/Util/BlockAllocator.cpp | 3 ++- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index ef81fa2a23..2ebb7b5149 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -17,6 +17,7 @@ #include "HLE.h" #include +#include #include "../MemMap.h" #include "HLETables.h" @@ -60,7 +61,8 @@ void HLEInit() void HLEDoState(PointerWrap &p) { - p.Do(unresolvedSyscalls, Syscall()); + Syscall sc = {0}; + p.Do(unresolvedSyscalls, sc); p.DoMarker("HLE"); } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 2eaa41f069..ddd793b43b 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -125,7 +125,8 @@ void __DisplayDoState(PointerWrap &p) { p.Do(isVblank); p.Do(hasSetMode); p.Do(lastFrameTime); - p.Do(vblankWaitingThreads, WaitVBlankInfo(0)); + WaitVBlankInfo wvi(0); + p.Do(vblankWaitingThreads, wvi); p.Do(enterVblankEvent); CoreTiming::RestoreRegisterEvent(enterVblankEvent, "EnterVBlank", &hleEnterVblank); diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index d57d63c9bd..8f62b722c0 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -57,7 +57,7 @@ public: nef.currentPattern, nef.numWaitThreads); } - + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_EVFID; } @@ -66,7 +66,8 @@ public: virtual void DoState(PointerWrap &p) { p.Do(nef); - p.Do(waitingThreads, EventFlagTh()); + EventFlagTh eft = {0}; + p.Do(waitingThreads, eft); p.DoMarker("EventFlag"); } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 7c8c9d2544..77e7e707a9 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -247,7 +247,8 @@ void __InterruptsDoState(PointerWrap &p) } intState.DoState(p); - p.Do(pendingInterrupts, PendingInterrupt(0, 0)); + PendingInterrupt pi(0, 0); + p.Do(pendingInterrupts, pi); p.Do(interruptsEnabled); p.Do(inInterrupt); p.DoMarker("sceKernelInterrupt"); diff --git a/Core/HLE/sceKernelMbx.cpp b/Core/HLE/sceKernelMbx.cpp index 205a97460d..a36183ecca 100644 --- a/Core/HLE/sceKernelMbx.cpp +++ b/Core/HLE/sceKernelMbx.cpp @@ -156,7 +156,8 @@ struct Mbx : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nmb); - p.Do(waitingThreads, MbxWaitingThread()); + MbxWaitingThread mwt(0,0); + p.Do(waitingThreads, mwt); p.DoMarker("Mbx"); } diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index 92ef03c74a..2f820a3a3a 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -155,8 +155,9 @@ struct MsgPipe : public KernelObject virtual void DoState(PointerWrap &p) { p.Do(nmp); - p.Do(sendWaitingThreads, MsgPipeWaitingThread()); - p.Do(receiveWaitingThreads, MsgPipeWaitingThread()); + MsgPipeWaitingThread mpwt1 = {0}, mpwt2 = {0}; + p.Do(sendWaitingThreads, mpwt1); + p.Do(receiveWaitingThreads, mpwt2); bool hasBuffer = buffer != NULL; p.Do(hasBuffer); if (hasBuffer) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 35f91ce900..485aeb726c 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -44,7 +44,7 @@ namespace SaveState struct Operation { - Operation(OperationType t, std::string &f, Callback cb) + Operation(OperationType t, const std::string &f, Callback cb) : type(t), filename(f), callback(cb) { } diff --git a/Core/Util/BlockAllocator.cpp b/Core/Util/BlockAllocator.cpp index d778012ab9..c8e7cbbe3e 100644 --- a/Core/Util/BlockAllocator.cpp +++ b/Core/Util/BlockAllocator.cpp @@ -300,7 +300,8 @@ u32 BlockAllocator::GetTotalFreeBytes() void BlockAllocator::DoState(PointerWrap &p) { - p.Do(blocks, Block(0, 0, false)); + Block b(0, 0, false); + p.Do(blocks, b); p.Do(rangeStart_); p.Do(rangeSize_); p.Do(grain_); From 90e3042b174098ec30a8758499be4d7c5a398775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 28 Dec 2012 23:43:09 +0100 Subject: [PATCH 275/276] Change save state extension to ".ppst" --- Windows/WndMainWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 1e8a469a6d..5237026b8b 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -37,7 +37,7 @@ #include "XPTheme.h" #endif -BOOL g_bFullScreen = FALSE; +BOOL g_bFullScreen = FALSE; RECT g_normalRC = {0}; namespace MainWindow @@ -313,7 +313,7 @@ namespace MainWindow break; case ID_FILE_LOADSTATE: - if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppssppst)\0*.ppssppst\0All files\0*.*\0\0","ppssppst",fn)) + if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); SaveState::Load(fn, SaveStateActionFinished); @@ -321,7 +321,7 @@ namespace MainWindow break; case ID_FILE_SAVESTATE: - if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppssppst)\0*.ppssppst\0All files\0*.*\0\0","ppssppst",fn)) + if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); SaveState::Save(fn, SaveStateActionFinished); From f9133c1a56985b108244f94dcd420d6647a3db42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 29 Dec 2012 00:09:17 +0100 Subject: [PATCH 276/276] Reset JIT before saving/loading state --- Core/MIPS/ARM/Jit.h | 4 +++- Core/MIPS/x86/Jit.h | 3 ++- Core/MIPS/x86/JitCache.cpp | 1 - Core/SaveState.cpp | 9 +++++++-- Core/SaveState.h | 6 +++--- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/MIPS/ARM/Jit.h b/Core/MIPS/ARM/Jit.h index d3c9cade66..567d77d7c9 100644 --- a/Core/MIPS/ARM/Jit.h +++ b/Core/MIPS/ARM/Jit.h @@ -94,8 +94,10 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } AsmRoutineManager &Asm() { return asm_; } -private: + void ClearCache(); + +private: void FlushAll(); void WriteExit(u32 destination, int exit_num); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 23abe06467..cd5a511efc 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -93,8 +93,9 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } AsmRoutineManager &Asm() { return asm_; } -private: + void ClearCache(); +private: void FlushAll(); void WriteExit(u32 destination, int exit_num); diff --git a/Core/MIPS/x86/JitCache.cpp b/Core/MIPS/x86/JitCache.cpp index 7cae2b5639..c710923972 100644 --- a/Core/MIPS/x86/JitCache.cpp +++ b/Core/MIPS/x86/JitCache.cpp @@ -104,7 +104,6 @@ JitBlockCache::~JitBlockCache() Shutdown(); } - // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache // is full and when saving and loading states. void JitBlockCache::Clear() diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 485aeb726c..aa74d0cebe 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -26,6 +26,7 @@ #include "HW/MemoryStick.h" #include "MemMap.h" #include "MIPS/MIPS.h" +#include "MIPS/JitCommon/JitCommon.h" #include "System.h" namespace SaveState @@ -95,12 +96,12 @@ namespace SaveState CoreTiming::ScheduleEvent_Threadsafe(0, timer); } - void Load(std::string &filename, Callback callback) + void Load(const std::string &filename, Callback callback) { Enqueue(Operation(SAVESTATE_LOAD, filename, callback)); } - void Save(std::string &filename, Callback callback) + void Save(const std::string &filename, Callback callback) { Enqueue(Operation(SAVESTATE_SAVE, filename, callback)); } @@ -132,11 +133,15 @@ namespace SaveState switch (op.type) { case SAVESTATE_LOAD: + if (MIPSComp::jit) + MIPSComp::jit->ClearCache(); INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str()); result = CChunkFileReader::Load(op.filename, REVISION, state); break; case SAVESTATE_SAVE: + if (MIPSComp::jit) + MIPSComp::jit->ClearCache(); INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str()); result = CChunkFileReader::Save(op.filename, REVISION, state); break; diff --git a/Core/SaveState.h b/Core/SaveState.h index 411ad2f88c..82a7021040 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -29,11 +29,11 @@ namespace SaveState // Load the specified file into the current state (async.) // Warning: callback will be called on a different thread. - void Load(std::string &filename, Callback callback = NULL); + void Load(const std::string &filename, Callback callback = NULL); // Save the current state to the specified file (async.) // Warning: callback will be called on a different thread. - void Save(std::string &filename, Callback callback = NULL); + void Save(const std::string &filename, Callback callback = NULL); // For testing / automated tests. Runs a save state verification pass (async.) // Warning: callback will be called on a different thread. void Verify(Callback callback = NULL); -}; \ No newline at end of file +};