From ecffab317a50f3769fc31747ddb03faf5f80f585 Mon Sep 17 00:00:00 2001 From: oioitff Date: Thu, 27 Jun 2013 23:46:26 +0800 Subject: [PATCH 1/9] Improve PsmfPlayer. Implement video loop for PsmfPlayer. --- Core/HLE/scePsmf.cpp | 60 ++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 1fc2c5f7f1..d8623df5a4 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -163,7 +163,8 @@ public: u32 filehandle; u32 fileoffset; - u32 filesize; + int readSize; + int streamSize; u8 tempbuf[0x10000]; int videoCodec; @@ -283,7 +284,8 @@ PsmfPlayer::PsmfPlayer(u32 data) { mediaengine = new MediaEngine; filehandle = 0; fileoffset = 0; - filesize = 0; + readSize = 0; + streamSize = 0; } void Psmf::DoState(PointerWrap &p) { @@ -331,7 +333,8 @@ void PsmfPlayer::DoState(PointerWrap &p) { p.DoClass(mediaengine); p.Do(filehandle); p.Do(fileoffset); - p.Do(filesize); + p.Do(readSize); + p.Do(streamSize); p.Do(status); p.Do(psmfPlayerAvcAu); @@ -413,6 +416,8 @@ void __PsmfDoState(PointerWrap &p) void __PsmfPlayerDoState(PointerWrap &p) { p.Do(psmfPlayerMap); + p.Do(videoPixelMode); + p.Do(videoLoopStatus); p.DoMarker("scePsmfPlayer"); } @@ -776,18 +781,42 @@ int scePsmfPlayerBreak(u32 psmfPlayer) return 0; } +int _PsmfPlayerFillRingbuffer(PsmfPlayer *psmfplayer) { + if (!psmfplayer->filehandle || !psmfplayer->tempbuf) + return -1; + u8* buf = psmfplayer->tempbuf; + u32 tempbufSize = sizeof(psmfplayer->tempbuf); + int size; + do { + size = std::min(psmfplayer->mediaengine->getRemainSize(), (int)tempbufSize); + size = std::min(psmfplayer->streamSize - psmfplayer->readSize, size); + if (size <= 0) + break; + size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, size); + psmfplayer->mediaengine->addStreamData(buf, size); + } while (size > 0); + if (psmfplayer->readSize >= psmfplayer->streamSize && videoLoopStatus == PSMF_PLAYER_CONFIG_LOOP) { + // start looping + psmfplayer->readSize = 0; + pspFileSystem.SeekFile(psmfplayer->filehandle, psmfplayer->fileoffset, FILEMOVE_BEGIN); + } + return 0; +} + int _PsmfPlayerSetPsmfOffset(PsmfPlayer *psmfplayer, const char * filename, int offset, bool docallback) { psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); - psmfplayer->fileoffset = offset; if (psmfplayer->filehandle && psmfplayer->tempbuf) { - pspFileSystem.SeekFile(psmfplayer->filehandle, offset, FILEMOVE_BEGIN); + if (offset > 0) + pspFileSystem.SeekFile(psmfplayer->filehandle, offset, FILEMOVE_BEGIN); u8* buf = psmfplayer->tempbuf; u32 tempbufSize = sizeof(psmfplayer->tempbuf); - int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, tempbufSize); - if (size) { - psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)tempbufSize)); - psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); - } + int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, 2048); + int mpegoffset = bswap32(*(u32*)(buf + PSMF_STREAM_OFFSET_OFFSET)); + psmfplayer->readSize = size - mpegoffset; + psmfplayer->streamSize = bswap32(*(u32*)(buf + PSMF_STREAM_SIZE_OFFSET)); + psmfplayer->fileoffset = offset + mpegoffset; + psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)tempbufSize)); + _PsmfPlayerFillRingbuffer(psmfplayer); psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); } return 0; @@ -932,7 +961,7 @@ int scePsmfPlayerUpdate(u32 psmfPlayer) DEBUG_LOG(HLE, "scePsmfPlayerUpdate(%08x)", psmfPlayer); if (psmfplayer->psmfPlayerAvcAu.pts > 0) { - if (psmfplayer->psmfPlayerAvcAu.pts >= psmfplayer->psmfPlayerLastTimestamp) { + if (psmfplayer->mediaengine->IsVideoEnd()) { INFO_LOG(HLE, "video end reached"); psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING_FINISHED; } @@ -970,14 +999,7 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) Memory::Write_U32(psmfplayer->psmfPlayerAvcAu.pts, videoDataAddr + 8); } - u32 tempbufSize = sizeof(psmfplayer->tempbuf); - int addSize = std::min(psmfplayer->mediaengine->getRemainSize(), (int)tempbufSize); - if (psmfplayer->filehandle && psmfplayer->tempbuf && addSize > 0) { - u8* buf = psmfplayer->tempbuf; - int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, addSize); - if (size) - psmfplayer->mediaengine->addStreamData(buf, size); - } + _PsmfPlayerFillRingbuffer(psmfplayer); int ret = psmfplayer->mediaengine->IsVideoEnd() ? ERROR_PSMFPLAYER_NO_MORE_DATA : 0; s64 deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp(); From a86ddab8d02dc04a5635639ba826e311d96fae82 Mon Sep 17 00:00:00 2001 From: oioitff Date: Fri, 28 Jun 2013 05:44:57 +0800 Subject: [PATCH 2/9] Tiny bug fix. --- Core/HLE/scePsmf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index d8623df5a4..e95ccdb9da 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -793,6 +793,7 @@ int _PsmfPlayerFillRingbuffer(PsmfPlayer *psmfplayer) { if (size <= 0) break; size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, size); + psmfplayer->readSize += size; psmfplayer->mediaengine->addStreamData(buf, size); } while (size > 0); if (psmfplayer->readSize >= psmfplayer->streamSize && videoLoopStatus == PSMF_PLAYER_CONFIG_LOOP) { From 6b8752407712884175c53d8a4eba7431f5759c1d Mon Sep 17 00:00:00 2001 From: oioitff Date: Fri, 28 Jun 2013 22:06:20 +0800 Subject: [PATCH 3/9] sceMpegGetAvcAu should return PSP_ERROR_MPEG_NO_DATA at first call before mpegAvcDecode. --- Core/HLE/sceMpeg.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 808e4ff089..77cfa16501 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -255,7 +255,7 @@ void AnalyzeMpeg(u32 buffer_addr, MpegContext *ctx) { ctx->mpegLastDate = convertTimestampToDate(ctx->mpegLastTimestamp); ctx->avc.avcDetailFrameWidth = (Memory::Read_U8(buffer_addr + 142) * 0x10); ctx->avc.avcDetailFrameHeight = (Memory::Read_U8(buffer_addr + 143) * 0x10); - ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS; + ctx->avc.avcDecodeResult = 0; ctx->avc.avcFrameStatus = 0; ctx->videoFrameCount = 0; @@ -965,6 +965,11 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) SceMpegAu sceAu; sceAu.read(auAddr); + if (ctx->avc.avcDecodeResult == 0) { + // return PSP_ERROR_MPEG_NO_DATA at first call before mpegAvcDecode + ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS; + return hleDelayResult(PSP_ERROR_MPEG_NO_DATA, "mpeg get avc", mpegDecodeErrorDelayMs); + } if (mpegRingbuffer.packetsRead == 0 || mpegRingbuffer.packetsFree == mpegRingbuffer.packets) { DEBUG_LOG(HLE, "PSP_ERROR_MPEG_NO_DATA=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", mpeg, streamId, auAddr, attrAddr); sceAu.pts = -1; From 1ecde4316307aca9270e188f7bbf0b30ae4c70de Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 29 Jun 2013 04:28:50 +0800 Subject: [PATCH 4/9] Match the font size of save dialog with real PSP --- Core/Dialog/PSPSaveDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index e763f957e6..29c3c98597 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -402,9 +402,9 @@ void PSPSaveDialog::DisplaySaveDataInfo1() std::string saveDetailTxt = saveDetail; PPGeDrawText(titleTxt.c_str(), 180, 136, PPGE_ALIGN_BOTTOM, 0.6f, CalcFadedColor(0xFFC0C0C0)); - PPGeDrawText(timeTxt.c_str(), 180, 137, PPGE_ALIGN_LEFT, 0.45f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(saveTitleTxt.c_str(), 175, 159, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(saveDetailTxt.c_str(), 175, 181, PPGE_ALIGN_LEFT, 0.45f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(timeTxt.c_str(), 180, 137, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(saveTitleTxt.c_str(), 175, 159, PPGE_ALIGN_LEFT, 0.55f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(saveDetailTxt.c_str(), 175, 181, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); } } From fa138b9354da3605e42e8e56a258339446fc6526 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 29 Jun 2013 04:31:17 +0800 Subject: [PATCH 5/9] Quick fix sizing --- Core/Dialog/PSPDialog.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 9560ed77f4..b44653a4a6 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -21,7 +21,7 @@ #include "i18n/i18n.h" #define FADE_TIME 0.5 -const float FONT_SCALE = 0.65f; +const float FONT_SCALE = 0.55f; PSPDialog::PSPDialog() : status(SCE_UTILITY_STATUS_SHUTDOWN) , lastButtons(0) @@ -141,12 +141,12 @@ void PSPDialog::DisplayButtons(int flags) if (flags & DS_BUTTON_OK) { PPGeDrawImage(okButtonImg, x2, 258, 11.5f, 11.5f, 0, CalcFadedColor(0x80000000)); PPGeDrawImage(okButtonImg, x2, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawText(d->T("Enter"), x2 + 15.5f, 252, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(d->T("Enter"), x2 + 14.5f, 250, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(d->T("Enter"), x2 + 15.5f, 254, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); + PPGeDrawText(d->T("Enter"), x2 + 14.5f, 252, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); } if (flags & DS_BUTTON_CANCEL) { - PPGeDrawText(d->T("Back"), x1 + 15.5f, 252, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); - PPGeDrawText(d->T("Back"), x1 + 14.5f, 250, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(d->T("Back"), x1 + 15.5f, 254, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0x80000000)); + PPGeDrawText(d->T("Back"), x1 + 14.5f, 252, PPGE_ALIGN_LEFT, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(cancelButtonImg, x1, 258, 11.5f, 11.5f, 0, CalcFadedColor(0x80000000)); PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, 0, CalcFadedColor(0xFFFFFFFF)); } From 0c22bcf2e411257514097bdbb881f729edbf92c2 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 29 Jun 2013 04:58:44 +0800 Subject: [PATCH 6/9] Fix wrong YES/NO color of save dialog --- Core/Dialog/PSPSaveDialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 29c3c98597..f006aa175b 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -456,7 +456,7 @@ void PSPSaveDialog::DisplaySaveDataInfo2() } snprintf(txt, 1024, "%s\n%s %s\n%lld KB", saveTitle, date, hour_time, sizeK); std::string saveinfoTxt = txt; - PPGeDrawText(saveinfoTxt.c_str(), 8, 200, PPGE_ALIGN_LEFT, 0.45f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawText(saveinfoTxt.c_str(), 8, 200, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF)); } } @@ -476,14 +476,14 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) if (yesnoChoice == 1) { choiceText = d->T("Yes"); x = 302.0f; - yesColor = 0xFF0FFFFF; + yesColor = 0xFFFFFFFF; noColor = 0xFFFFFFFF; } else { choiceText = d->T("No"); x = 366.0f; yesColor = 0xFFFFFFFF; - noColor = 0xFF0FFFFF; + noColor = 0xFFFFFFFF; } PPGeMeasureText(&w, &h, 0, choiceText, FONT_SCALE); w = w / 2.0f + 5.5f; @@ -491,7 +491,7 @@ void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo) float y2 = y + h2 + 4.0f; h2 += h + 4.0f; y = 132.0f - h; - PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF)); + PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x20CFCFCF)); PPGeDrawText(d->T("Yes"), 302.0f, y2, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(yesColor)); PPGeDrawText(d->T("No"), 366.0f, y2, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(noColor)); if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { From c8509091aff18f56cdce57319c37a06be6868d4d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Jun 2013 21:33:47 -0700 Subject: [PATCH 7/9] Allow the disasm height to be resized a bit more. --- Windows/Debugger/Debugger_Disasm.cpp | 29 ++++++++++++++-------------- Windows/Debugger/Debugger_Disasm.h | 3 ++- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index c453fb9e9b..25ca8acc0d 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -92,21 +92,15 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di CtrlRegisterList *rl = CtrlRegisterList::getFrom(GetDlgItem(m_hDlg,IDC_REGLIST)); rl->setCPU(cpu); - GetWindowRect(m_hDlg,&minRect); - // Reduce the minimum size slightly, so they can size it however they like. - minRect.right -= 100; - minRect.bottom -= 100; + GetWindowRect(m_hDlg, &defaultRect); //symbolMap.FillSymbolListBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); symbolMap.FillSymbolComboBox(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST),ST_FUNCTION); - GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST),®Rect); - GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW),&disRect); - GetWindowRect(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST),&breakpointRect); - - int minHeight = max((disRect.bottom-disRect.top)+(breakpointRect.bottom-breakpointRect.top)+37, - (regRect.bottom-regRect.top)+(breakpointRect.bottom-breakpointRect.top)+150); - if (h < minHeight) h = minHeight; + GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST), ®Rect); + GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW), &disRect); + GetWindowRect(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST), &breakpointRect); + GetWindowRect(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST), &defaultBreakpointRect); HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); @@ -714,9 +708,10 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) case WM_GETMINMAXINFO: { MINMAXINFO *m = (MINMAXINFO *)lParam; - m->ptMinTrackSize.x=minRect.right-minRect.left; - //m->ptMaxTrackSize.x=m->ptMinTrackSize.x; - m->ptMinTrackSize.y=minRect.bottom-minRect.top; + // Reduce the minimum size slightly, so they can size it however they like. + m->ptMinTrackSize.x = defaultRect.right - defaultRect.left - 100; + //m->ptMaxTrackSize.x = m->ptMinTrackSize.x; + m->ptMinTrackSize.y = defaultRect.bottom - defaultRect.top - 200; } return TRUE; case WM_CLOSE: @@ -733,7 +728,11 @@ void CDisasm::UpdateSize(WORD width, WORD height) HWND regList = GetDlgItem(m_hDlg, IDC_REGLIST); HWND breakpointList = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST); - int breakpointHeight = breakpointRect.bottom-breakpointRect.top; + int defaultHeight = defaultRect.bottom - defaultRect.top; + int breakpointHeight = defaultBreakpointRect.bottom - defaultBreakpointRect.top; + if (height < defaultHeight) + breakpointHeight -= defaultHeight - height; + int breakpointTop = height-breakpointHeight-8; int regWidth = regRect.right - regRect.left; int regTop = 138; diff --git a/Windows/Debugger/Debugger_Disasm.h b/Windows/Debugger/Debugger_Disasm.h index 644e2a7ea2..1ddbe6bbf5 100644 --- a/Windows/Debugger/Debugger_Disasm.h +++ b/Windows/Debugger/Debugger_Disasm.h @@ -15,7 +15,8 @@ class CDisasm : public Dialog { private: - RECT minRect; + RECT defaultRect; + RECT defaultBreakpointRect; RECT regRect; RECT disRect; RECT breakpointRect; From 3dcc16608e4f33ecb06f1c62178f407e1335ccca Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Jun 2013 21:44:38 -0700 Subject: [PATCH 8/9] Adjust the default disasm height to reduce padding. --- Windows/ppsspp.rc | Bin 40342 -> 40342 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index e0f08a274614d6c5089e2a71ae6934a259195ade..ea95ee62bce66e456a7377afaa912f3bb62093ec 100644 GIT binary patch delta 52 zcmbQXn`zo^rVSPfjE0jZ+8A%nQE=d3G}ydWLzj`+l)-fJLv8EH5?V*VY)4D?&1%{O FMF7Q=5NQAa delta 54 zcmV-60LlNBy8@QG0DfxCIA2c From 92ae7cb8e60ba914d7765cbc421f371c4576019f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 28 Jun 2013 22:27:04 -0700 Subject: [PATCH 9/9] Do less memcpy when copying the framebuf to mem. --- GPU/GLES/Framebuffer.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 5e01956d47..282a4e691a 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -857,26 +857,22 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb) { // (maybe it's more efficient to have the GPU flip it in the framebuffer and then flip it back?) int bufHeight = vfb->height; size_t bufSize = vfb->fb_stride * bufHeight; - GLubyte *buf1 = (GLubyte *) malloc(bufSize * pixelSize); - GLubyte *buf2 = (GLubyte *) malloc(bufSize * pixelSize); + GLubyte *flipBuf = (GLubyte *) malloc(bufSize * pixelSize); - u32 fb_address = (0x44000000) | vfb->fb_address; + u32 fb_address = (0x04000000) | vfb->fb_address; - DEBUG_LOG(HLE, "Reading pixels to mem, bufSize = %u, buf = %08x, fb_address = %08x", bufSize, buf1, fb_address); + DEBUG_LOG(HLE, "Reading pixels to mem, bufSize = %u, fb_address = %08x", bufSize, fb_address); glPixelStorei(GL_PACK_ALIGNMENT, align); - glReadPixels(0, 0, vfb->fb_stride, vfb->height, pixelFormat, pixelType, buf1); + glReadPixels(0, 0, vfb->fb_stride, vfb->height, pixelFormat, pixelType, flipBuf); // We have to flip glReadPixels data upside down - int i, j; - for(i = 0; i < bufHeight; i++) { - for(j = 0; j < vfb->fb_stride * pixelSize; j++) { - buf2[(bufHeight - 1 - i) * vfb->fb_stride * pixelSize + j] = buf1[i * vfb->fb_stride * pixelSize + j]; - } + int u8_stride = vfb->fb_stride * pixelSize; + for (int y = 0; y < bufHeight; y++) { + int inverted_y = bufHeight - 1 - y; + Memory::Memcpy(fb_address + inverted_y * u8_stride, &flipBuf[u8_stride * y], u8_stride); } - Memory::Memcpy(fb_address, buf2, bufSize * pixelSize); - free(buf1); - free(buf2); + free(flipBuf); fbo_unbind(); if(gl_extensions.FBO_ARB) { glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);