From c33036aa0128836163f8856c2277cfda7035632b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 7 Nov 2013 01:33:32 -0500 Subject: [PATCH 01/81] Fix the filter for some files in the Core VS project related to the JitIL. They were in the root of the project. They should actually be in their own filter named JitILCommon. --- Source/Core/Core/Core.vcxproj.filters | 66 +++++++++++++++------------ 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index ae766cd165..97364678a4 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -133,6 +133,9 @@ {8352be4d-d37d-4f55-adec-b940a9712802} + + {827afa93-1a80-4835-93ae-b5516d95867f} + @@ -636,39 +639,12 @@ PowerPC\JitCommon - - PowerPC\JitIL - PowerPC\JitIL PowerPC\JitIL - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - PowerPC\JitIL @@ -706,6 +682,33 @@ PowerPC\Jit64 + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + @@ -1190,9 +1193,6 @@ PowerPC\JitCommon - - PowerPC\JitIL - PowerPC\JitIL @@ -1209,6 +1209,12 @@ PowerPC\Jit64 + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + From ea2d8bf328e72da63edc1cfaaebfb6495ea1ccce Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 7 Nov 2013 15:54:16 +0100 Subject: [PATCH 02/81] VideoCommon: fix custom textures This fix a regression by revision 6cece6b48667 delete pointer must not do anything if pointer==NULL. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 41af7ac946..c29a59e2b4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -470,8 +470,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, expandedHeight = height; // If we thought we could reuse the texture before, make sure to pool it now! - PoolTexture(entry); - entry = NULL; + if(entry) + { + PoolTexture(entry); + entry = NULL; + } } using_custom_texture = true; } From 33d56f50a44863d482665cf2f38c4264424f6184 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Thu, 7 Nov 2013 09:24:56 -0800 Subject: [PATCH 03/81] Re-plumb window handle to the dsound backend. Reverts parts of commit 71c01d83ab614b9e0c421d03ca694713dbabff48. Fixes issue 6800 --- Source/Core/AudioCommon/Src/AudioCommon.cpp | 4 ++-- Source/Core/AudioCommon/Src/AudioCommon.h | 2 +- Source/Core/AudioCommon/Src/DSoundStream.h | 4 ++-- Source/Core/Core/Src/Core.cpp | 4 ++-- Source/Core/Core/Src/DSPEmulator.h | 3 ++- Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp | 5 +++-- Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h | 2 +- Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp | 5 +++-- Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h | 2 +- 9 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index acb9f95067..c8c37ea891 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -23,7 +23,7 @@ SoundStream *soundStream = nullptr; namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer) + SoundStream *InitSoundStream(CMixer *mixer, void *hWnd) { // TODO: possible memleak with mixer @@ -33,7 +33,7 @@ namespace AudioCommon else if (backend == BACKEND_NULLSOUND && NullSound::isValid()) soundStream = new NullSound(mixer); else if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) - soundStream = new DSound(mixer); + soundStream = new DSound(mixer, hWnd); else if (backend == BACKEND_XAUDIO2) { if (XAudio2::isValid()) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.h b/Source/Core/AudioCommon/Src/AudioCommon.h index 8ff5ff38e1..9c49293a48 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.h +++ b/Source/Core/AudioCommon/Src/AudioCommon.h @@ -40,7 +40,7 @@ union UDSPControl namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer); + SoundStream *InitSoundStream(CMixer *mixer, void *hWnd); void ShutdownSoundStream(); std::vector GetSoundBackends(); bool UseJIT(); diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h index 8778c7e863..a872e79181 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.h +++ b/Source/Core/AudioCommon/Src/DSoundStream.h @@ -48,7 +48,7 @@ class DSound : public SoundStream bool WriteDataToBuffer(DWORD dwOffset, char* soundData, DWORD dwSoundBytes); public: - DSound(CMixer *mixer, void *_hWnd = NULL) + DSound(CMixer *mixer, void *_hWnd) : SoundStream(mixer) , bufferSize(0) , currentPos(0) @@ -71,7 +71,7 @@ public: #else public: - DSound(CMixer *mixer) + DSound(CMixer *mixer, void *_hWnd) : SoundStream(mixer) {} #endif diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 88c0376cb2..ea54163c30 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -388,8 +388,8 @@ void EmuThread() OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000); - if (!DSP::GetDSPEmulator()->Initialize(_CoreParameter.bWii, - _CoreParameter.bDSPThread)) + if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle, + _CoreParameter.bWii, _CoreParameter.bDSPThread)) { HW::Shutdown(); g_video_backend->Shutdown(); diff --git a/Source/Core/Core/Src/DSPEmulator.h b/Source/Core/Core/Src/DSPEmulator.h index 207818cbca..45b2b30c8c 100644 --- a/Source/Core/Core/Src/DSPEmulator.h +++ b/Source/Core/Core/Src/DSPEmulator.h @@ -15,7 +15,7 @@ public: virtual bool IsLLE() = 0; - virtual bool Initialize(bool bWii, bool bDSPThread) = 0; + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread) = 0; virtual void Shutdown() = 0; virtual void DoState(PointerWrap &p) = 0; @@ -35,6 +35,7 @@ public: protected: SoundStream *soundStream; + void *m_hWnd; }; DSPEmulator *CreateDSPEmulator(bool HLE); diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp index 3897fd6e86..501bc2a0dd 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp @@ -42,8 +42,9 @@ struct DSPState } }; -bool DSPHLE::Initialize(bool bWii, bool bDSPThread) +bool DSPHLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { + m_hWnd = hWnd; m_bWii = bWii; m_pUCode = NULL; m_lastUCode = NULL; @@ -265,7 +266,7 @@ void DSPHLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000)); + soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h index 44248fd88f..6627b9dc2a 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h @@ -16,7 +16,7 @@ class DSPHLE : public DSPEmulator { public: DSPHLE(); - virtual bool Initialize(bool bWii, bool bDSPThread) override; + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread) override; virtual void Shutdown() override; virtual bool IsLLE() override { return false ; } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 9b9364947b..af747815d1 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -130,8 +130,9 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle) } } -bool DSPLLE::Initialize(bool bWii, bool bDSPThread) +bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { + m_hWnd = hWnd; m_bWii = bWii; m_bDSPThread = bDSPThread; m_InitMixer = false; @@ -184,7 +185,7 @@ void DSPLLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000)); + soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h index 5ae0fd6a74..71addf77b0 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h @@ -14,7 +14,7 @@ class DSPLLE : public DSPEmulator { public: DSPLLE(); - virtual bool Initialize(bool bWii, bool bDSPThread); + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread); virtual void Shutdown(); virtual bool IsLLE() { return true; } From 8923968b47ab27f571ff7464dc34143001c5a567 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 7 Nov 2013 21:16:36 +0100 Subject: [PATCH 04/81] Revert "VideoCommon: create native texture pool" This reverts commit 6cece6b486670dd149c827053a84754c98397ccc. In fact, there was a _huge_ speedup on lots of games (mostly on nvidia+ogl), but there are some crashes on D3D. I have to fix this crash and then I'll commit something like this again :-) Conflicts: Source/Core/VideoCommon/Src/TextureCacheBase.cpp --- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 90 +++---------------- .../Core/VideoCommon/Src/TextureCacheBase.h | 6 +- 2 files changed, 11 insertions(+), 85 deletions(-) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index c29a59e2b4..05c2e88aae 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -30,8 +30,6 @@ unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; -TextureCache::TexPool TextureCache::texPool; - TextureCache::BackupConfig TextureCache::backup_config; bool invalidate_texture_cache_requested; @@ -70,13 +68,6 @@ void TextureCache::Invalidate() delete iter->second; textures.clear(); - - TexPool::iterator - iter2 = texPool.begin(), - tcend2 = texPool.end(); - for (; iter2 != tcend2; ++iter2) - delete iter2->second; - texPool.clear(); } TextureCache::~TextureCache() @@ -144,7 +135,7 @@ void TextureCache::Cleanup() // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted && ! iter->second->IsEfbCopy() ) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -152,21 +143,6 @@ void TextureCache::Cleanup() ++iter; } } - - TexPool::iterator iter2 = texPool.begin(); - TexPool::iterator tcend2 = texPool.end(); - while (iter2 != tcend2) - { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter2->second->frameCount) - { - delete iter2->second; - texPool.erase(iter2++); - } - else - { - ++iter2; - } - } } void TextureCache::InvalidateRange(u32 start_address, u32 size) @@ -179,7 +155,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); if (0 == rangePosition) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -239,7 +215,7 @@ void TextureCache::ClearRenderTargets() { if (iter->second->type == TCET_EC_VRAM) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -450,8 +426,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, } else { - // pool the texture and make a new one - PoolTexture(entry); + // delete the texture and make a new one + delete entry; entry = NULL; } } @@ -472,7 +448,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // If we thought we could reuse the texture before, make sure to pool it now! if(entry) { - PoolTexture(entry); + delete entry; entry = NULL; } } @@ -500,15 +476,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR) - // try to search for a pooled texture - if (NULL == entry) - { - // Try to find a matching texture in the pool. We pool unused texture as they often just change the type. - // This happens in eg efb2ram which overwrites half of a texture. So most of this textures are only pooled - // for some frames. - textures[texID] = entry = GetPooledTexture ( width, height, full_format, texLevels, false ); - } - // create the entry/texture if (NULL == entry) { @@ -857,23 +824,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) { // remove it and recreate it as a render target - PoolTexture(entry); + delete entry; entry = NULL; } } if (NULL == entry) { - // search for a compatible pooled texture - entry = GetPooledTexture(scaled_tex_w, scaled_tex_h, 0, 0, true); - - if (NULL == entry) - { - // create the texture - entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); - } - textures[dstAddr] = entry; - + // create the texture + textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); + // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); @@ -885,33 +845,3 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } - -TextureCache::TCacheEntryBase* TextureCache::GetPooledTexture ( u32 width, u32 height, u32 full_format, u32 maxlevel, bool isEfbCopy ) -{ - TCacheEntryBase* entry = NULL; - std::pair bounds; - bounds = texPool.equal_range(std::make_pair(width, height)); - while(!entry && bounds.first != bounds.second) { - entry = bounds.first->second; - if ( - (isEfbCopy && entry->IsEfbCopy()) || - (!isEfbCopy && entry->type == TCET_NORMAL && full_format == entry->format && entry->num_mipmaps == maxlevel) || - (!isEfbCopy && entry->type == TCET_EC_DYNAMIC) - ) - { - texPool.erase(bounds.first); - } - else - { - entry = NULL; - bounds.first++; - } - } - return entry; -} - -void TextureCache::PoolTexture(TextureCache::TCacheEntryBase* entry) -{ - entry->frameCount = frameCount; - texPool.insert(std::make_pair(std::make_pair(entry->virtual_width, entry->virtual_height), entry)); -} diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index c035ee8d23..1afcb8cd2d 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -121,12 +121,8 @@ private: static void DumpTexture(TCacheEntryBase* entry, unsigned int level); typedef std::map TexCache; + static TexCache textures; - - static TCacheEntryBase* GetPooledTexture(u32 width, u32 height, u32 full_format, u32 maxlevel, bool isEfbCopy); - static void PoolTexture(TCacheEntryBase *entry); - typedef std::multimap, TCacheEntryBase*> TexPool; - static TexPool texPool; // Backup configuration values static struct BackupConfig From a83c239765f8add99a360a29bfba2fdb408075c8 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 10 Nov 2013 00:06:32 +0100 Subject: [PATCH 05/81] D3D: Reintroduce depencency on D3DX11 because it's the most straightforward way to bring back some broken features. The Dolphin development team is incapable of providing sufficient replacement for its previous usage in Dolphin and the advantages of dropping the dependency do not justify the removal of screenshots and texture dumping. From now on, d3dx11.h, d3dx11async.h, d3dx11core.h and d3dx11tex.h are required to be stored somewhere in the header include path. I don't know if this is the case for anyone else than me, but I can't really say that I care after having people randomly merge unfinished branches into master. --- Source/Core/VideoBackends/D3D/Src/D3DBase.cpp | 60 +++++++++++++++++++ Source/Core/VideoBackends/D3D/Src/D3DBase.h | 25 +++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp b/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp index 5434354f37..e9e678d841 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp @@ -17,6 +17,13 @@ D3DREFLECT PD3DReflect = NULL; pD3DCompile PD3DCompile = NULL; int d3dcompiler_dll_ref = 0; +HINSTANCE hD3DXDll = NULL; +D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL; +D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL; +D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL; +D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL; +int d3dx_dll_ref = 0; + CREATEDXGIFACTORY PCreateDXGIFactory = NULL; HINSTANCE hDXGIDll = NULL; int dxgi_dll_ref = 0; @@ -91,6 +98,44 @@ HRESULT LoadD3D() return S_OK; } +HRESULT LoadD3DX() +{ + if (d3dx_dll_ref++ > 0) return S_OK; + if (hD3DXDll) return S_OK; + + // try to load D3DX11 first to check whether we have proper runtime support + // try to use the dll the backend was compiled against first - don't bother about debug runtimes + hD3DXDll = LoadLibraryA(D3DX11_DLL_A); + if (!hD3DXDll) + { + // if that fails, use the dll which should be available in every SDK which officially supports DX11. + hD3DXDll = LoadLibraryA("d3dx11_42.dll"); + if (!hD3DXDll) + { + MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR); + return E_FAIL; + } + else + { + NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first."); + } + } + + PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory"); + if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR); + + PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture"); + if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR); + + PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA"); + if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR); + + PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW"); + if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR); + + return S_OK; +} + HRESULT LoadD3DCompiler() { if (d3dcompiler_dll_ref++ > 0) return S_OK; @@ -132,6 +177,18 @@ void UnloadDXGI() PCreateDXGIFactory = NULL; } +void UnloadD3DX() +{ + if (!d3dx_dll_ref) return; + if (--d3dx_dll_ref != 0) return; + + if (hD3DXDll) FreeLibrary(hD3DXDll); + hD3DXDll = NULL; + PD3DX11FilterTexture = NULL; + PD3DX11SaveTextureToFileA = NULL; + PD3DX11SaveTextureToFileW = NULL; +} + void UnloadD3D() { if (!d3d_dll_ref) return; @@ -215,11 +272,13 @@ HRESULT Create(HWND wnd) hr = LoadDXGI(); if (SUCCEEDED(hr)) hr = LoadD3D(); + if (SUCCEEDED(hr)) hr = LoadD3DX(); if (SUCCEEDED(hr)) hr = LoadD3DCompiler(); if (FAILED(hr)) { UnloadDXGI(); UnloadD3D(); + UnloadD3DX(); UnloadD3DCompiler(); return hr; } @@ -361,6 +420,7 @@ void Close() // unload DLLs UnloadD3D(); + UnloadD3DX(); UnloadDXGI(); } diff --git a/Source/Core/VideoBackends/D3D/Src/D3DBase.h b/Source/Core/VideoBackends/D3D/Src/D3DBase.h index 7f26cbd3cc..6e06de6e90 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DBase.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include #include #include "Common.h" #include @@ -25,9 +25,11 @@ namespace D3D HRESULT LoadDXGI(); HRESULT LoadD3D(); +HRESULT LoadD3DX(); HRESULT LoadD3DCompiler(); void UnloadDXGI(); void UnloadD3D(); +void UnloadD3DX(); void UnloadD3DCompiler(); D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter); @@ -72,6 +74,27 @@ void SetDebugObjectName(T resource, const char* name) } // namespace D3D +// Used to not require the SDK and runtime versions to match: +// Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the +// compiler's SDK a requirement, but this backend works with DX11 runtimes +// back to August 2009 even if the backend was built with June 2010. +// Add any d3dx11 functions which you want to use here and load them in Create() +typedef HRESULT(WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*); +typedef HRESULT(WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT); +typedef HRESULT(WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR); +typedef HRESULT(WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR); + +extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory; +extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture; +extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA; +extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW; + +#ifdef UNICODE +#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW +#else +#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA +#endif + typedef HRESULT (WINAPI *CREATEDXGIFACTORY)(REFIID, void**); extern CREATEDXGIFACTORY PCreateDXGIFactory; typedef HRESULT (WINAPI *D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); From 3de2ee5d46c118929bf90540706cf82fc0671920 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 10 Nov 2013 00:09:09 +0100 Subject: [PATCH 06/81] D3D: Use D3DX for texture dumping. --- Source/Core/VideoBackends/D3D/Src/TextureCache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index 7ee92459c6..d3c536c4a6 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -42,8 +42,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) warn_once = false; return false; } - //return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); - return true; + return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, From 0b02880b7699b8049be0ae64ff1461a792a9bf9b Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 10 Nov 2013 00:10:20 +0100 Subject: [PATCH 07/81] Revert "Be less dumb." Revert "Actually, filename really does need to be a parameter because of some random debug thing." Revert "fix non-HAVE_WX case" Revert "Handle screenshot saving in RenderBase. Removes dependency on D3DX11 for screenshots (texture dumping is still broken)." This reverts commits 00fe5057f13bca3416b9d25a1fe9df27c514b29c, 74b5fb3ab4b066681336d1be44c7eecfcf6a4dc6, cd46138d299088631bbcbf37543584946c4b174a and 5f72542e0637799092ad1006d16ebad1961020e0 because taking screenshots in D3D still crashed for me so there was no point in the code changes (which I found ugly anyway). --- Source/Core/VideoBackends/D3D/Src/Render.cpp | 36 +++-- Source/Core/VideoBackends/D3D/Src/Render.h | 3 +- Source/Core/VideoBackends/OGL/Src/Render.cpp | 130 ++++++++++++++++-- Source/Core/VideoBackends/OGL/Src/Render.h | 4 +- .../VideoBackends/OGL/Src/VertexManager.cpp | 2 +- Source/Core/VideoCommon/Src/RenderBase.cpp | 77 +---------- Source/Core/VideoCommon/Src/RenderBase.h | 7 +- 7 files changed, 148 insertions(+), 111 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 9790f2b52e..380ab7fa83 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -680,7 +680,7 @@ void Renderer::SetBlendMode(bool forceUpdate) } } -void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename) +bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle& rc) { if (!s_screenshot_texture) CreateScreenshotTexture(rc); @@ -689,26 +689,34 @@ void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename) D3D11_BOX box = CD3D11_BOX(rc.left, rc.top, 0, rc.right, rc.bottom, 1); D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex(), 0, &box); - u8* __restrict dest = (u8*) malloc(rc.GetWidth() * rc.GetHeight() * 3); - + // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - u8* src = (u8*) map.pData; - for (int y = 0; y < rc.GetHeight(); ++y) + for (unsigned int y = 0; y < rc.GetHeight(); ++y) { - u8* __restrict row = src; - for (int x = 0; x < rc.GetWidth(); ++x) + u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; + for (unsigned int x = 0; x < rc.GetWidth(); ++x) { - *dest++ = *row++; - *dest++ = *row++; - *dest++ = *row++; - row++; + *ptr = 0xFF; + ptr += 4; } - src += map.RowPitch; } D3D::context->Unmap(s_screenshot_texture, 0); - SaveScreenshot(dest, rc.GetWidth(), rc.GetHeight(), filename); + // ready to be saved + //HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); + HRESULT hr = 0; + if (SUCCEEDED(hr)) + { + OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), + rc.GetHeight(), filename.c_str())); + } + else + { + OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str())); + } + + return SUCCEEDED(hr); } void formatBufferDump(const u8* in, u8* out, int w, int h, int p) @@ -846,7 +854,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // done with drawing the game stuff, good moment to save a screenshot if (s_bScreenshot) { - TakeScreenshot(GetTargetRectangle(), s_sScreenshotName); + SaveScreenshot(s_sScreenshotName, GetTargetRectangle()); s_bScreenshot = false; } diff --git a/Source/Core/VideoBackends/D3D/Src/Render.h b/Source/Core/VideoBackends/D3D/Src/Render.h index e899484111..12e5b595d3 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.h +++ b/Source/Core/VideoBackends/D3D/Src/Render.h @@ -48,10 +48,9 @@ public: void UpdateViewport(); - static void TakeScreenshot(const TargetRectangle &rc, std::string filename); + bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); static bool CheckForResize(); - }; } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 4583c6772c..d03d3cedd3 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -11,6 +11,9 @@ #include #include "GLUtil.h" +#if defined(HAVE_WX) && HAVE_WX +#include "WxUtils.h" +#endif #include "FileUtil.h" @@ -22,6 +25,7 @@ #include "DriverDetails.h" #include "VideoConfig.h" #include "Statistics.h" +#include "ImageWrite.h" #include "PixelEngine.h" #include "Render.h" #include "BPStructs.h" @@ -58,6 +62,10 @@ #include "AVIDump.h" #endif +#if defined(HAVE_WX) && HAVE_WX +#include +#endif + // glew1.8 doesn't define KHR_debug #ifndef GL_DEBUG_OUTPUT #define GL_DEBUG_OUTPUT 0x92E0 @@ -70,6 +78,17 @@ void VideoConfig::UpdateProjectionHack() } +#if defined(HAVE_WX) && HAVE_WX +// Screenshot thread struct +typedef struct +{ + int W, H; + std::string filename; + wxImage *img; +} ScrStrct; +#endif + + int OSDInternalW, OSDInternalH; namespace OGL @@ -108,6 +127,10 @@ static u32 s_blendMode; static bool s_vsync; +#if defined(HAVE_WX) && HAVE_WX +static std::thread scrshotThread; +#endif + // EFB cache related static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks. static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up @@ -616,6 +639,11 @@ Renderer::Renderer() Renderer::~Renderer() { + +#if defined(HAVE_WX) && HAVE_WX + if (scrshotThread.joinable()) + scrshotThread.join(); +#endif } void Renderer::Shutdown() @@ -1391,9 +1419,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // Save screenshot if (s_bScreenshot) { - TakeScreenshot(flipped_trc, s_sScreenshotName); - s_bScreenshot = false; + std::lock_guard lk(s_criticalScreenshot); + SaveScreenshot(s_sScreenshotName, flipped_trc); // Reset settings + s_sScreenshotName.clear(); + s_bScreenshot = false; } // Frame dumps are handled a little differently in Windows @@ -1771,22 +1801,71 @@ void Renderer::SetInterlacingMode() void Renderer::FlipImageData(u8 *data, int w, int h) { - // XXX make this faster - u8* __restrict top = data; - u8* bot = data + w * h * 3; + // Flip image upside down. Damn OpenGL. for (int y = 0; y < h / 2; y++) { - size_t stride = w * 3; - bot -= stride; - u8* __restrict brow = bot; - for(size_t x = 0; x < stride; x++) + for(int x = 0; x < w; x++) { - std::swap(*top++, *brow++); + std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]); + std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]); + std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]); } } } -void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filename) +} + +// TODO: remove +extern bool g_aspect_wide; + +#if defined(HAVE_WX) && HAVE_WX +void TakeScreenshot(ScrStrct* threadStruct) +{ + // These will contain the final image size + float FloatW = (float)threadStruct->W; + float FloatH = (float)threadStruct->H; + + // Handle aspect ratio for the final ScrStrct to look exactly like what's on screen. + if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) + { + bool use16_9 = g_aspect_wide; + + // Check for force-settings and override. + if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) + use16_9 = true; + else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) + use16_9 = false; + + float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); + + // If ratio > 1 the picture is too wide and we have to limit the width. + if (Ratio > 1) + FloatW /= Ratio; + // ratio == 1 or the image is too high, we have to limit the height. + else + FloatH *= Ratio; + + // This is a bit expensive on high resolutions + threadStruct->img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); + } + + // Save the screenshot and finally kill the wxImage object + // This is really expensive when saving to PNG, but not at all when using BMP + threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename), + wxBITMAP_TYPE_PNG); + threadStruct->img->Destroy(); + + // Show success messages + OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, + threadStruct->filename.c_str()), 2000); + delete threadStruct; +} +#endif + +namespace OGL +{ + +bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &back_rc) { u32 W = back_rc.GetWidth(); u32 H = back_rc.GetHeight(); @@ -1800,13 +1879,38 @@ void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filena { free(data); OSD::AddMessage("Error capturing or saving screenshot.", 2000); - return; + return false; } // Turn image upside down FlipImageData(data, W, H); - SaveScreenshot(data, W, H, filename); +#if defined(HAVE_WX) && HAVE_WX + // Create wxImage + wxImage *a = new wxImage(W, H, data); + + if (scrshotThread.joinable()) + scrshotThread.join(); + + ScrStrct *threadStruct = new ScrStrct; + threadStruct->filename = filename; + threadStruct->img = a; + threadStruct->H = H; threadStruct->W = W; + + scrshotThread = std::thread(TakeScreenshot, threadStruct); +#ifdef _WIN32 + SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); +#endif + bool result = true; + + OSD::AddMessage("Saving Screenshot... ", 2000); + +#else + bool result = SaveTGA(filename.c_str(), W, H, data); + free(data); +#endif + + return result; } } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.h b/Source/Core/VideoBackends/OGL/Src/Render.h index f38c9b4c58..9b4838ee25 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.h +++ b/Source/Core/VideoBackends/OGL/Src/Render.h @@ -63,7 +63,7 @@ public: void RenderText(const char* pstr, int left, int top, u32 color) override; void DrawDebugInfo(); - static void FlipImageData(u8 *data, int w, int h); + void FlipImageData(u8 *data, int w, int h); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; @@ -80,7 +80,7 @@ public: void UpdateViewport() override; - static void TakeScreenshot(const TargetRectangle &rc, std::string filename); + bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); private: void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data); diff --git a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp index 4fb355d897..44d8ddeaa4 100644 --- a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp @@ -341,7 +341,7 @@ void VertexManager::vFlush() tr.right = Renderer::GetTargetWidth(); tr.top = 0; tr.bottom = Renderer::GetTargetHeight(); - Renderer::TakeScreenshot(tr, str); + g_renderer->SaveScreenshot(str, tr); } #endif g_Config.iSaveTargetId++; diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index bb3dad8a73..e509ccb980 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -30,12 +30,6 @@ #include "XFMemory.h" #include "FifoPlayer/FifoRecorder.h" #include "AVIDump.h" -#include "OnScreenDisplay.h" -#if defined(HAVE_WX) && HAVE_WX -#include "WxUtils.h" -#include -#endif -#include "ImageWrite.h" #include #include @@ -73,8 +67,6 @@ unsigned int Renderer::efb_scale_numeratorY = 1; unsigned int Renderer::efb_scale_denominatorX = 1; unsigned int Renderer::efb_scale_denominatorY = 1; -// TODO: remove -extern bool g_aspect_wide; Renderer::Renderer() : frame_data() @@ -250,72 +242,6 @@ void Renderer::SetScreenshot(const char *filename) s_bScreenshot = true; } -#if defined(HAVE_WX) && HAVE_WX -void Renderer::SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename) -{ - wxImage *img = new wxImage(width, height, data); - - // These will contain the final image size - float FloatW = (float)width; - float FloatH = (float)height; - - // Handle aspect ratio for the final ScrStrct to look exactly like what's on screen. - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) - { - bool use16_9 = g_aspect_wide; - - // Check for force-settings and override. - if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) - use16_9 = true; - else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) - use16_9 = false; - - float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - - // If ratio > 1 the picture is too wide and we have to limit the width. - if (Ratio > 1) - FloatW /= Ratio; - // ratio == 1 or the image is too high, we have to limit the height. - else - FloatH *= Ratio; - - // This is a bit expensive on high resolutions - img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); - } - - // Save the screenshot and finally kill the wxImage object - // This is really expensive when saving to PNG, but not at all when using BMP - img->SaveFile(StrToWxStr(filename), wxBITMAP_TYPE_PNG); - img->Destroy(); - - // Show success messages - OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, - filename.c_str()), 2000); -} -#endif - -void Renderer::SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename) -{ - std::lock_guard lk(s_criticalScreenshot); -#if defined(HAVE_WX) && HAVE_WX - // Create wxImage - - std::thread thread(SaveScreenshotOnThread, ptr, width, height, filename); -#ifdef _WIN32 - SetThreadPriority(thread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); -#endif - thread.detach(); - - OSD::AddMessage("Saving Screenshot... ", 2000); - -#else - SaveTGA(filename.c_str(), width, height, ptr); - free(ptr); -#endif - - s_bScreenshot = false; -} - // Create On-Screen-Messages void Renderer::DrawDebugText() { @@ -421,6 +347,9 @@ void Renderer::DrawDebugText() g_renderer->RenderText(final_yellow.c_str(), 20, 20, 0xFFFFFF00); } +// TODO: remove +extern bool g_aspect_wide; + void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height) { float FloatGLWidth = (float)backbuffer_width; diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 7a153fb5cc..22d31cde23 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -110,6 +110,8 @@ public: virtual void UpdateViewport() = 0; + virtual bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc) = 0; + static unsigned int GetPrevPixelFormat() { return prev_efb_format; } static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; } @@ -121,11 +123,6 @@ protected: static void CheckFifoRecording(); static void RecordVideoMemory(); - #if defined(HAVE_WX) && HAVE_WX - static void SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename); - #endif - static void SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename); - static volatile bool s_bScreenshot; static std::mutex s_criticalScreenshot; static std::string s_sScreenshotName; From 22f727cc69a897cfb79ddf77b7f11539477b3390 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 10 Nov 2013 00:14:01 +0100 Subject: [PATCH 08/81] D3D: Use D3DX11 for taking screenshots. --- Source/Core/VideoBackends/D3D/Src/Render.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 380ab7fa83..1a4421f3c5 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -704,8 +704,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D::context->Unmap(s_screenshot_texture, 0); // ready to be saved - //HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); - HRESULT hr = 0; + HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); if (SUCCEEDED(hr)) { OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), From e013a74cdbdf9cebb150bc59c196a5ff3f6af710 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 10 Nov 2013 05:02:32 +0000 Subject: [PATCH 09/81] [ARM] More NEON emitters. --- Source/Core/Common/Src/ArmEmitter.cpp | 73 ++++++++++++++++++++------- Source/Core/Common/Src/ArmEmitter.h | 10 ++-- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index cb9544dce3..a324659f26 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -938,13 +938,13 @@ u32 EncodeVm(ARMReg Vm) // Double/single, Neon extern const VFPEnc VFPOps[16][2] = { - {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA + {{0xE0, 0xA0}, { -1, -1}}, // 0: VMLA {{0xE1, 0xA4}, { -1, -1}}, // 1: VNMLA - {{0xE0, 0xA4}, {0x22, 0xD1}}, // 2: VMLS + {{0xE0, 0xA4}, { -1, -1}}, // 2: VMLS {{0xE1, 0xA0}, { -1, -1}}, // 3: VNMLS - {{0xE3, 0xA0}, {0x20, 0xD0}}, // 4: VADD - {{0xE3, 0xA4}, {0x22, 0xD0}}, // 5: VSUB - {{0xE2, 0xA0}, {0x30, 0xD1}}, // 6: VMUL + {{0xE3, 0xA0}, { -1, -1}}, // 4: VADD + {{0xE3, 0xA4}, { -1, -1}}, // 5: VSUB + {{0xE2, 0xA0}, { -1, -1}}, // 6: VMUL {{0xE2, 0xA4}, { -1, -1}}, // 7: VNMUL {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 8: VABS(Vn(0x0) used for encoding) {{0xE8, 0xA0}, { -1, -1}}, // 9: VDIV @@ -1710,6 +1710,56 @@ void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0xA0 << 4) | EncodeVm(Vm)); } +void NEONXEmitter::VMUL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_POLYNOMIAL) ? (1 << 24) : 0) | (encodedSize(Size) << 20) | \ + EncodeVn(Vn) | EncodeVd(Vd) | (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xC0 << 4) | ((Size & I_POLYNOMIAL) ? 1 << 9 : 0) | EncodeVm(Vm)); +} +void NEONXEmitter::VNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) | \ + EncodeVd(Vd) | ((Size & F_32) ? 1 << 10 : 0) | (0xE << 6) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (3 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { @@ -1797,18 +1847,5 @@ void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) | ((Vm & 0x10) << 1) | (Vm & 0xF)); } -void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) -{ - bool register_quad = Vd >= Q0; - Vd = SubBase(Vd); - Vn = SubBase(Vn); - Vm = SubBase(Vm); - - Write32((0xF2 << 24) | (0x1 << 21) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) - | ((Vd & 0xF) << 12) | (1 << 8) | ((Vn & 0x10) << 3) - | (register_quad << 6) | ((Vm & 0x10) << 1) | (1 << 4) | (Vm & 0xF)); -} - - } diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h index cdfddd8d7e..a00c0d1197 100644 --- a/Source/Core/Common/Src/ArmEmitter.h +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -580,7 +580,8 @@ enum NEONElementType I_64 = (1 << 3), I_SIGNED = (1 << 4), I_UNSIGNED = (1 << 5), - F_32 = (1 << 6) + F_32 = (1 << 6), + I_POLYNOMIAL = (1 << 7), // Only used in VMUL/VMULL }; enum NEONAlignment @@ -665,6 +666,11 @@ public: void VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMUL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm); void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm); @@ -672,8 +678,6 @@ public: void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); void VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); From 3a28afd8d5d55dc4a90199029d50a7e13dc7c7b2 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Sun, 10 Nov 2013 04:57:11 -0500 Subject: [PATCH 10/81] Changed thread barrier and event to use a lamba wait predicate instead of a functor. --- Source/Core/Common/Src/Thread.h | 42 +++++---------------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index bfd7ea0308..b2e9572ce5 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -38,7 +38,7 @@ class Event public: Event() : is_set(false) - {}; + {} void Set() { @@ -53,34 +53,20 @@ public: void Wait() { std::unique_lock lk(m_mutex); - m_condvar.wait(lk, IsSet(this)); + m_condvar.wait(lk, [&]{ return is_set; }); is_set = false; } void Reset() { std::unique_lock lk(m_mutex); - // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration + // no other action required, since wait loops on + // the predicate and any lingering signal will get + // cleared on the first iteration is_set = false; } private: - class IsSet - { - public: - IsSet(const Event* ev) - : m_event(ev) - {} - - bool operator()() - { - return m_event->is_set; - } - - private: - const Event* const m_event; - }; - volatile bool is_set; std::condition_variable m_condvar; std::mutex m_mutex; @@ -110,28 +96,12 @@ public: } else { - m_condvar.wait(lk, IsDoneWating(this)); + m_condvar.wait(lk, [&]{ return (0 == m_waiting); }); return false; } } private: - class IsDoneWating - { - public: - IsDoneWating(const Barrier* bar) - : m_bar(bar) - {} - - bool operator()() - { - return (0 == m_bar->m_waiting); - } - - private: - const Barrier* const m_bar; - }; - std::condition_variable m_condvar; std::mutex m_mutex; const size_t m_count; From d1de3368797e137a9b953356775271918c116e57 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 11 Nov 2013 01:46:57 +0000 Subject: [PATCH 11/81] [ARM] More NEON emitters. --- Source/Core/Common/Src/ArmEmitter.cpp | 351 ++++++++++++++++++++++++-- Source/Core/Common/Src/ArmEmitter.h | 34 ++- 2 files changed, 359 insertions(+), 26 deletions(-) diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index a324659f26..6fa952ea40 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -1760,22 +1760,340 @@ void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); } - -void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VPADAL(NEONElementType Size, ARMReg Vd, ARMReg Vm) { - _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)"); - _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); - // Gets encoded as a double register + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x60 << 4) | ((Size & I_UNSIGNED) ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VPADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB1 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VPADDL(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x20 << 4) | (Size & I_UNSIGNED ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VPMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VPMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA1 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQABS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x90 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x78 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQRDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x41 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x21 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VRECPE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (0x3 << 16) | EncodeVd(Vd) | \ + (0x40 << 4) | (Size & F_32 ? 1 << 8 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x10 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x50 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + bool register_quad = Vd >= Q0; Vd = SubBase(Vd); - Vn = SubBase(Vn); Vm = SubBase(Vm); - Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (encodedSize(Size) << 20) | ((Vn & 0xF) << 16) \ - | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \ - | ((Vm & 0x10) << 1) | (Vm & 0xF)); + Write32((0xF3 << 24) | (0xB << 20) | ((Vd & 0x10) << 18) | (0xB << 16) + | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) + | ((Vm & 0x10) << 1) | (Vm & 0xF)); } +void NEONXEmitter::VRSQRTS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, Size & F_32, __FUNCTION__ " only supports float"); + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 21) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x80 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x20 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x30 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSWP(ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (1 << 17) | EncodeVd(Vd) | \ + (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VTRN(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (1 << 7) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VTST(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VUZP(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VZIP(NEONElementType Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x18 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Only support loading to 1 reg @@ -1786,7 +2104,6 @@ void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } - void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x8; // Single spaced registers @@ -1797,7 +2114,6 @@ void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } - void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Single spaced registers @@ -1809,7 +2125,6 @@ void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | (align << 4) | Rm); } - void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm) { bool register_quad = Vd >= Q0; @@ -1835,17 +2150,5 @@ void NEONXEmitter::VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm) { VREVX(2, Size, Vd, Vm); } - -void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) -{ - bool register_quad = Vd >= Q0; - Vd = SubBase(Vd); - Vm = SubBase(Vm); - - Write32((0xF3 << 24) | (0xB << 20) | ((Vd & 0x10) << 18) | (0xB << 16) - | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) - | ((Vm & 0x10) << 1) | (Vm & 0xF)); -} - } diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h index a00c0d1197..a2b6884607 100644 --- a/Source/Core/Common/Src/ArmEmitter.h +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -671,13 +671,43 @@ public: void VNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm); void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADAL(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VPADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADDL(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VPMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQABS(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VQADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VQRDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRECPE(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VRHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VRSQRTS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSWP(ARMReg Vd, ARMReg Vm); + void VTRN(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VTST(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VUZP(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VZIP(NEONElementType Size, ARMReg Vd, ARMReg Vm); void VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm); void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm); void VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); void VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); From 22fef0da9bdda47dba0b83ba2ea89de1b28a75ab Mon Sep 17 00:00:00 2001 From: Chanwoong Kim Date: Tue, 12 Nov 2013 01:05:30 +0900 Subject: [PATCH 12/81] Fixed a bug that incorrectly recognized as 'GameCube'. when you open the Korean Wii Disc, which is re-encrypted with a common-key(g_MasterKey). --- Source/Core/DiscIO/Src/VolumeCreator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Core/DiscIO/Src/VolumeCreator.cpp b/Source/Core/DiscIO/Src/VolumeCreator.cpp index 7cf26f826a..4863a17949 100644 --- a/Source/Core/DiscIO/Src/VolumeCreator.cpp +++ b/Source/Core/DiscIO/Src/VolumeCreator.cpp @@ -183,8 +183,14 @@ static IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _Part memset(IV, 0, 16); _rReader.Read(rPartition.Offset + 0x44c, 8, IV); + bool usingKoreanKey = false; + if (Korean && Reader.Read32(0x501ee) != 0) + { + usingKoreanKey = true; + } + aes_context AES_ctx; - aes_setkey_dec(&AES_ctx, (Korean ? g_MasterKeyK : g_MasterKey), 128); + aes_setkey_dec(&AES_ctx, (usingKoreanKey ? g_MasterKeyK : g_MasterKey), 128); u8 VolumeKey[16]; aes_crypt_cbc(&AES_ctx, AES_DECRYPT, 16, IV, SubKey, VolumeKey); From 68ba0f7f4e587e3359411cd57f7acb51b96e5d2c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 11 Nov 2013 17:17:49 +0000 Subject: [PATCH 13/81] Add a comment to the magic value reading location. --- Source/Core/DiscIO/Src/VolumeCreator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/DiscIO/Src/VolumeCreator.cpp b/Source/Core/DiscIO/Src/VolumeCreator.cpp index 4863a17949..4dd24f9b4b 100644 --- a/Source/Core/DiscIO/Src/VolumeCreator.cpp +++ b/Source/Core/DiscIO/Src/VolumeCreator.cpp @@ -184,6 +184,10 @@ static IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _Part _rReader.Read(rPartition.Offset + 0x44c, 8, IV); bool usingKoreanKey = false; + // Issue: 6813 + // Magic value is at 0x501f1 (1byte) + // If encrypted with the Korean key, the magic value would be 1 + // Otherwise it is zero if (Korean && Reader.Read32(0x501ee) != 0) { usingKoreanKey = true; From 56557c845aa4ee5a0f9a1b06ad3fc5d6e7e6e4b7 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Nov 2013 01:01:54 +0000 Subject: [PATCH 14/81] [ARM] Fix NEON emitter encodings. --- Source/Core/Common/Src/ArmEmitter.cpp | 181 ++++++++++-------- Source/Core/Common/Src/ArmEmitter.h | 172 ++++++++--------- Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp | 19 ++ 3 files changed, 201 insertions(+), 171 deletions(-) diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index 6fa952ea40..6178d2c58c 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -1237,7 +1237,7 @@ void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags) } } -void NEONXEmitter::VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1248,7 +1248,7 @@ void NEONXEmitter::VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x71 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1260,7 +1260,7 @@ void NEONXEmitter::VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x50 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1273,7 +1273,7 @@ void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1285,7 +1285,7 @@ void NEONXEmitter::VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VABS(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1327,7 +1327,7 @@ void NEONXEmitter::VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm) VACGT(Vd, Vn, Vm); } -void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1341,7 +1341,7 @@ void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (0x8 << 8) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd < Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1353,7 +1353,7 @@ void NEONXEmitter::VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1364,7 +1364,7 @@ void NEONXEmitter::VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \ | EncodeVd(Vd) | EncodeVm(Vm)); } -void NEONXEmitter::VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1420,7 +1420,7 @@ void NEONXEmitter::VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF3 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1433,7 +1433,7 @@ void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1443,7 +1443,7 @@ void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF2 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1455,7 +1455,7 @@ void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ | (0x31 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1464,7 +1464,7 @@ void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x8 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1476,7 +1476,7 @@ void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1485,11 +1485,11 @@ void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { VCGE(Size, Vd, Vm, Vn); } -void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1498,7 +1498,7 @@ void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (3 << 7) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLS(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1508,11 +1508,11 @@ void NEONXEmitter::VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (1 << 10) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { VCGT(Size, Vd, Vm, Vn); } -void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1521,7 +1521,7 @@ void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x20 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLZ(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1530,7 +1530,7 @@ void NEONXEmitter::VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (0x48 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCNT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1540,7 +1540,7 @@ void NEONXEmitter::VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index) +void NEONXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1562,7 +1562,7 @@ void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index) Write32((0xF3 << 24) | (0xD << 20) | (sizeEncoded << 16) | (indexEncoded << 16) \ | EncodeVd(Vd) | (0xC0 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt) +void NEONXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Rt) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Rt < D0, "Pass invalid register to " __FUNCTION__); @@ -1616,7 +1616,7 @@ void NEONXEmitter::VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1627,7 +1627,7 @@ void NEONXEmitter::VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1638,7 +1638,7 @@ void NEONXEmitter::VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (1 << 9) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1651,7 +1651,7 @@ void NEONXEmitter::VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x60 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1664,7 +1664,7 @@ void NEONXEmitter::VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x61 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1676,7 +1676,7 @@ void NEONXEmitter::VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) else Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1688,7 +1688,7 @@ void NEONXEmitter::VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) else Write32((0xF2 << 24) | (1 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1699,7 +1699,7 @@ void NEONXEmitter::VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1710,7 +1710,7 @@ void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0xA0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VMUL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1723,7 +1723,7 @@ void NEONXEmitter::VMUL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_POLYNOMIAL) ? (1 << 24) : 0) | (encodedSize(Size) << 20) | \ EncodeVn(Vn) | EncodeVd(Vd) | (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1732,7 +1732,7 @@ void NEONXEmitter::VMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xC0 << 4) | ((Size & I_POLYNOMIAL) ? 1 << 9 : 0) | EncodeVm(Vm)); } -void NEONXEmitter::VNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VNEG(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1760,7 +1760,7 @@ void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VPADAL(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VPADAL(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1771,7 +1771,7 @@ void NEONXEmitter::VPADAL(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ (0x60 << 4) | ((Size & I_UNSIGNED) ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VPADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1779,10 +1779,10 @@ void NEONXEmitter::VPADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) if (Size & F_32) Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | EncodeVm(Vm)); else - Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xB1 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VPADDL(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VPADDL(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1793,7 +1793,7 @@ void NEONXEmitter::VPADDL(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ (0x20 << 4) | (Size & I_UNSIGNED ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VPMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1804,7 +1804,7 @@ void NEONXEmitter::VPMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xA0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VPMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1815,7 +1815,7 @@ void NEONXEmitter::VPMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xA1 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQABS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VQABS(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1826,7 +1826,7 @@ void NEONXEmitter::VQABS(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VQADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1837,7 +1837,7 @@ void NEONXEmitter::VQADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x1 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VQMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1846,7 +1846,7 @@ void NEONXEmitter::VQMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x90 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1855,7 +1855,7 @@ void NEONXEmitter::VQMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xB0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1864,7 +1864,7 @@ void NEONXEmitter::VQDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xB0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQDMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1873,7 +1873,7 @@ void NEONXEmitter::VQDMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xD0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VQNEG(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1884,7 +1884,7 @@ void NEONXEmitter::VQNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ (0x78 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VQRDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1893,7 +1893,7 @@ void NEONXEmitter::VQRDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg V Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xB0 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VQRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1902,9 +1902,9 @@ void NEONXEmitter::VQRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) bool register_quad = Vd >= Q0; Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ - (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); + (0x51 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VQSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1915,7 +1915,7 @@ void NEONXEmitter::VQSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x41 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VQSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1926,35 +1926,46 @@ void NEONXEmitter::VQSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x21 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VRADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); - Write32((0xF3 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x40 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VRECPE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VRECPE(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); bool register_quad = Vd >= Q0; - Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (0x3 << 16) | EncodeVd(Vd) | \ + Write32((0xF3 << 24) | (0xB << 20) | (0xB << 16) | EncodeVd(Vd) | \ (0x40 << 4) | (Size & F_32 ? 1 << 8 : 0) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VRHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + bool register_quad = Vd >= Q0; + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ - (0x10 << 4) | EncodeVm(Vm)); + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1965,8 +1976,11 @@ void NEONXEmitter::VRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x50 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm) { + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + bool register_quad = Vd >= Q0; Vd = SubBase(Vd); Vm = SubBase(Vm); @@ -1975,27 +1989,26 @@ void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF)); } -void NEONXEmitter::VRSQRTS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); - _dbg_assert_msg_(DYNA_REC, Size & F_32, __FUNCTION__ " only supports float"); bool register_quad = Vd >= Q0; Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VRSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); - Write32((0xF3 << 24) | (1 << 21) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x60 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2006,7 +2019,7 @@ void NEONXEmitter::VSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x40 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2020,28 +2033,28 @@ void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x80 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); - Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF2 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x60 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VSUBL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); - Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x20 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VSUBW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); - Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x30 << 4) | EncodeVm(Vm)); } void NEONXEmitter::VSWP(ARMReg Vd, ARMReg Vm) @@ -2054,7 +2067,7 @@ void NEONXEmitter::VSWP(ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (1 << 17) | EncodeVd(Vd) | \ (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VTRN(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VTRN(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2064,7 +2077,7 @@ void NEONXEmitter::VTRN(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ (1 << 7) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VTST(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2074,7 +2087,7 @@ void NEONXEmitter::VTST(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VUZP(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VUZP(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2084,7 +2097,7 @@ void NEONXEmitter::VUZP(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VZIP(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VZIP(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -2094,7 +2107,7 @@ void NEONXEmitter::VZIP(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ (0x18 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) +void NEONXEmitter::VLD1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Only support loading to 1 reg // Gets encoded as a double register @@ -2104,7 +2117,7 @@ void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } -void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) +void NEONXEmitter::VLD2(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x8; // Single spaced registers // Gets encoded as a double register @@ -2114,7 +2127,7 @@ void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } -void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) +void NEONXEmitter::VST1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Single spaced registers // Gets encoded as a double register @@ -2125,7 +2138,7 @@ void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | (align << 4) | Rm); } -void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm) { bool register_quad = Vd >= Q0; Vd = SubBase(Vd); @@ -2136,17 +2149,17 @@ void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm) | (register_quad << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF)); } -void NEONXEmitter::VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV64(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(0, Size, Vd, Vm); } -void NEONXEmitter::VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV32(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(1, Size, Vd, Vm); } -void NEONXEmitter::VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV16(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(2, Size, Vd, Vm); } diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h index a2b6884607..99024f3b6f 100644 --- a/Source/Core/Common/Src/ArmEmitter.h +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -338,6 +338,15 @@ struct LiteralPool }; typedef const u8* JumpTarget; +// XXX: Stop polluting the global namespace +const u32 I_8 = (1 << 0); +const u32 I_16 = (1 << 1); +const u32 I_32 = (1 << 2); +const u32 I_64 = (1 << 3); +const u32 I_SIGNED = (1 << 4); +const u32 I_UNSIGNED = (1 << 5); +const u32 F_32 = (1 << 6); +const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL u32 EncodeVd(ARMReg Vd); u32 EncodeVn(ARMReg Vn); @@ -572,18 +581,6 @@ public: }; // class ARMXEmitter -enum NEONElementType -{ - I_8 = (1 << 0), - I_16 = (1 << 1), - I_32 = (1 << 2), - I_64 = (1 << 3), - I_SIGNED = (1 << 4), - I_UNSIGNED = (1 << 5), - F_32 = (1 << 6), - I_POLYNOMIAL = (1 << 7), // Only used in VMUL/VMULL -}; - enum NEONAlignment { ALIGN_NONE = 0, @@ -614,104 +611,105 @@ private: return 0; } - void VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm); -public: +public: NEONXEmitter(ARMXEmitter *emit) : _emit(emit) {} - void VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABS(u32 Size, ARMReg Vd, ARMReg Vm); void VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index); - void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLS(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLZ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCNT(u32 Size, ARMReg Vd, ARMReg Vm); + void VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index); + void VDUP(u32 Size, ARMReg Vd, ARMReg Rt); void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index); void VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMUL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VNEG(u32 Size, ARMReg Vd, ARMReg Vm); void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VPADAL(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VPADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VPADDL(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VPMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VPMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQABS(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VQADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQDMULL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQNEG(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VQRDMULH(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VQSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VRADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VRECPE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VRHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VRSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VRSQRTS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VRSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSHL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUBHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUBL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUBW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADAL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADDL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQABS(u32 Size, ARMReg Vd, ARMReg Vm); + void VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQNEG(u32 Size, ARMReg Vd, ARMReg Vm); + void VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRECPE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VSWP(ARMReg Vd, ARMReg Vm); - void VTRN(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VTST(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VUZP(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VZIP(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VTRN(u32 Size, ARMReg Vd, ARMReg Vm); + void VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VUZP(u32 Size, ARMReg Vd, ARMReg Vm); + void VZIP(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV64(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV32(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV16(u32 Size, ARMReg Vd, ARMReg Vm); - void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); - void VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VLD1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VLD2(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); - void VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); }; // Everything that needs to generate X86 code should inherit from this. diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp index 4083a383e9..0b13372079 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp @@ -358,6 +358,25 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo b->checkedEntry = start; b->runCount = 0; + BKPT(1); + NEONXEmitter emit(this); +#if 1 + emit.VNEG(I_8, D15, D15); + emit.VNEG(I_16, D15, D15); + emit.VNEG(I_32, D15, D15); + emit.VNEG(F_32, Q15, Q15); + +#elif 0 + emit.VTRN(I_8, D31, D31); + emit.VTRN(I_8, Q15, Q15); + emit.VTRN(I_16, D31, D31); + emit.VTRN(I_16, Q15, Q15); + emit.VTRN(I_32, D31, D31); + emit.VTRN(I_32, Q15, Q15); +#else + emit.VSWP(D31, D31); + emit.VSWP(Q15, Q15); +#endif // Downcount flag check, Only valid for linked blocks { SetCC(CC_MI); From a72b3ca20c82c6828676b60b9e20358ce93f9a24 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Nov 2013 04:22:42 +0000 Subject: [PATCH 15/81] [ARM] Don't leave my test code in the JIT core. --- Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp index 0b13372079..4083a383e9 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.cpp @@ -358,25 +358,6 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo b->checkedEntry = start; b->runCount = 0; - BKPT(1); - NEONXEmitter emit(this); -#if 1 - emit.VNEG(I_8, D15, D15); - emit.VNEG(I_16, D15, D15); - emit.VNEG(I_32, D15, D15); - emit.VNEG(F_32, Q15, Q15); - -#elif 0 - emit.VTRN(I_8, D31, D31); - emit.VTRN(I_8, Q15, Q15); - emit.VTRN(I_16, D31, D31); - emit.VTRN(I_16, Q15, Q15); - emit.VTRN(I_32, D31, D31); - emit.VTRN(I_32, Q15, Q15); -#else - emit.VSWP(D31, D31); - emit.VSWP(Q15, Q15); -#endif // Downcount flag check, Only valid for linked blocks { SetCC(CC_MI); From 0f94652952058e41f19d6dc2a6bf55f471305251 Mon Sep 17 00:00:00 2001 From: Rachel Bryk Date: Tue, 12 Nov 2013 04:16:51 -0500 Subject: [PATCH 16/81] Disable wiimote source selection while netplay is running. --- Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index 86127eba6b..5e145ec391 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -3,6 +3,7 @@ #include "HW/Wiimote.h" #include "HW/WiimoteReal/WiimoteReal.h" #include "Frame.h" +#include "NetPlayProto.h" WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) : wxDialog(parent, -1, _("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize) @@ -134,6 +135,16 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin WiimoteSpkVolumeText->Disable(); WiimoteSpkVolumeMinText->Disable(); WiimoteSpkVolumeMaxText->Disable(); + if (NetPlay::IsNetPlayRunning()) + { + bb_source->Disable(); + for (int i = 0; i < 4; ++i) + { + wiimote_label[i]->Disable(); + wiimote_source_ch[i]->Disable(); + } + } + } From 7c1ac441f633220365d0feef3871f891e7ed7a43 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Nov 2013 16:34:32 -0600 Subject: [PATCH 17/81] Redo 'Fixes GCC 4.9 compilation. It now supplies its own _mm_shuffle_epi8 intrinsic.' This time with support for Windows. --- Source/Core/Common/Src/CommonFuncs.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h index bf50a1756f..63bdc04dfb 100644 --- a/Source/Core/Common/Src/CommonFuncs.h +++ b/Source/Core/Common/Src/CommonFuncs.h @@ -31,7 +31,12 @@ struct ArraySizeImpl : public std::extent #define b32(x) (b16(x) | (b16(x) >>16) ) #define ROUND_UP_POW2(x) (b32(x - 1) + 1) -#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC +#ifndef __GNUC_PREREQ + #define __GNUC_PREREQ(a, b) 0 +#endif + +#if (defined __GNUC__ && !__GNUC_PREREQ(4,9)) \ + && !defined __SSSE3__ && !defined _M_GENERIC #include static __inline __m128i __attribute__((__always_inline__)) _mm_shuffle_epi8(__m128i a, __m128i mask) From 39ad5a2f7a6f8533d19fea41e4eeaf8ace2763d4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 12 Nov 2013 19:37:09 -0600 Subject: [PATCH 18/81] Disable Fastmem on JIT64IL. JIT64IL is completely incompatible with Fastmem and doesn't need it since it has its own way to speed up memory accesses. This fixes the JIT64IL core, which I totally didn't break but was blamed for. --- .../Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp | 10 ++++----- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h | 8 +------ .../Src/PowerPC/JitCommon/JitAsmCommon.cpp | 22 +++++++++---------- .../Core/Src/PowerPC/JitCommon/Jit_Util.cpp | 18 ++++++++------- .../Core/Src/PowerPC/JitCommon/Jit_Util.h | 10 ++++----- 5 files changed, 32 insertions(+), 36 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index 69dc1c2bd3..7a37a1cb43 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -470,7 +470,7 @@ static void regEmitMemLoad(RegInfo& RI, InstLoc I, unsigned Size) { X64Reg reg; auto info = regBuildMemAddress(RI, I, getOp1(I), 1, Size, ®); - RI.Jit->SafeLoadToReg(reg, info.first, Size, info.second, regsInUse(RI), false); + RI.Jit->SafeLoadToReg(reg, info.first, Size, info.second, regsInUse(RI), false, EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (regReadUse(RI, I)) RI.regs[reg] = I; } @@ -498,7 +498,7 @@ static void regEmitMemStore(RegInfo& RI, InstLoc I, unsigned Size) { } else { RI.Jit->MOV(32, R(EAX), regLocForInst(RI, getOp1(I))); } - RI.Jit->SafeWriteRegToReg(EAX, ECX, Size, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, Size, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (RI.IInfo[I - RI.FirstI] & 4) regClearInst(RI, getOp1(I)); } @@ -1187,7 +1187,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { Jit->MOV(32, R(EAX), loc1); } Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I))); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (RI.IInfo[I - RI.FirstI] & 4) fregClearInst(RI, getOp1(I)); if (RI.IInfo[I - RI.FirstI] & 8) @@ -1250,12 +1250,12 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { Jit->PSRLQ(XMM0, 32); Jit->MOVD_xmm(R(EAX), XMM0); Jit->MOV(32, R(ECX), address); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); Jit->MOVAPD(XMM0, value); Jit->MOVD_xmm(R(EAX), XMM0); Jit->MOV(32, R(ECX), address); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 4, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 4, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); Jit->SetJumpTarget(exit); if (RI.IInfo[I - RI.FirstI] & 4) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index 3f0e847d91..e56a56c815 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -58,14 +58,10 @@ private: JitBlockCache blocks; TrampolineCache trampolines; - // The default code buffer. We keep it around to not have to alloc/dealloc a - // large chunk of memory for each recompiled block. - PPCAnalyst::CodeBuffer code_buffer; - public: JitILAsmRoutineManager asm_routines; - JitIL() : code_buffer(32000) {} + JitIL() {} ~JitIL() {} // Initialization, etc @@ -140,6 +136,4 @@ public: void DynaRunTable63(UGeckoInstruction _inst) override; }; -void Jit(u32 em_address); - #endif // _JITIL_H diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp index 311ced730a..bc8272f48c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp @@ -196,7 +196,7 @@ void CommonAsmRoutines::GenQuantizedStores() PACKSSDW(XMM0, R(XMM0)); PACKUSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -215,7 +215,7 @@ void CommonAsmRoutines::GenQuantizedStores() PACKSSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -241,7 +241,7 @@ void CommonAsmRoutines::GenQuantizedStores() MOV(16, R(AX), M((char*)psTemp + 4)); BSWAP(32, EAX); - SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -261,7 +261,7 @@ void CommonAsmRoutines::GenQuantizedStores() MOVD_xmm(R(EAX), XMM0); BSWAP(32, EAX); ROL(32, R(EAX), Imm8(16)); - SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -286,7 +286,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() // Easy! const u8* storeSingleFloat = AlignCode4(); - SafeWriteFloatToReg(XMM0, ECX, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteFloatToReg(XMM0, ECX, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); /* if (cpu_info.bSSSE3) { @@ -294,11 +294,11 @@ void CommonAsmRoutines::GenQuantizedSingleStores() // TODO: SafeWriteFloat MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); } else { MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); }*/ const u8* storeSingleU8 = AlignCode4(); // Used by MKWii @@ -309,7 +309,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_255)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleS8 = AlignCode4(); @@ -319,7 +319,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, M((void *)&m_m128)); MINSS(XMM0, M((void *)&m_127)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleU16 = AlignCode4(); // Used by MKWii @@ -330,7 +330,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_65535)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleS16 = AlignCode4(); @@ -340,7 +340,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, M((void *)&m_m32768)); MINSS(XMM0, M((void *)&m_32767)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); singleStoreQuantized = reinterpret_cast(const_cast(AlignCode16())); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index ae62bae6ce..00e24e7a20 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -117,18 +117,20 @@ u8 *EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, Gen::OpArg opAddress, int ac return result; } -void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend) +void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend, int flags) { if (!jit->js.memcheck) { registersInUse &= ~(1 << RAX | 1 << reg_value); } #if defined(_M_X64) + if (!Core::g_CoreStartupParameter.bMMU && + Core::g_CoreStartupParameter.bFastmem && + !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) #ifdef ENABLE_MEM_CHECK - if (!Core::g_CoreStartupParameter.bMMU && !Core::g_CoreStartupParameter.bEnableDebugging && Core::g_CoreStartupParameter.bFastmem) -#else - if (!Core::g_CoreStartupParameter.bMMU && Core::g_CoreStartupParameter.bFastmem) + && !Core::g_CoreStartupParameter.bEnableDebugging #endif + ) { u8 *mov = UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend); @@ -282,14 +284,14 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce #if defined(_M_X64) if (!Core::g_CoreStartupParameter.bMMU && Core::g_CoreStartupParameter.bFastmem && - !(flags & (SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_FASTMEM)) + !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) #ifdef ENABLE_MEM_CHECK && !Core::g_CoreStartupParameter.bEnableDebugging #endif ) { MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write - u8 *mov = UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, offset, !(flags & SAFE_WRITE_NO_SWAP)); + u8 *mov = UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, offset, !(flags & SAFE_LOADSTORE_NO_SWAP)); if (accessSize == 8) { NOP(1); @@ -321,8 +323,8 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write TEST(32, R(reg_addr), Imm32(mem_mask)); FixupBranch fast = J_CC(CC_Z, true); - bool noProlog = flags & SAFE_WRITE_NO_PROLOG; - bool swap = !(flags & SAFE_WRITE_NO_SWAP); + bool noProlog = flags & SAFE_LOADSTORE_NO_PROLOG; + bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); ABI_PushRegistersAndAdjustStack(registersInUse, noProlog); switch (accessSize) { diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h index 86802df822..a321ddd117 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h @@ -28,13 +28,13 @@ public: // these return the address of the MOV, for backpatching u8 *UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset = 0, bool swap = true); u8 *UnsafeLoadToReg(Gen::X64Reg reg_value, Gen::OpArg opAddress, int accessSize, s32 offset, bool signExtend); - void SafeLoadToReg(Gen::X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend); - enum SafeWriteFlags + enum SafeLoadStoreFlags { - SAFE_WRITE_NO_SWAP = 1, - SAFE_WRITE_NO_PROLOG = 2, - SAFE_WRITE_NO_FASTMEM = 4 + SAFE_LOADSTORE_NO_SWAP = 1, + SAFE_LOADSTORE_NO_PROLOG = 2, + SAFE_LOADSTORE_NO_FASTMEM = 4 }; + void SafeLoadToReg(Gen::X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend, int flags = 0); void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset, u32 registersInUse, int flags = 0); // Trashes both inputs and EAX. From 268bdf19cee3836af68a4248e373c2f0897afc5a Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sat, 26 Oct 2013 11:55:41 +0200 Subject: [PATCH 19/81] Fix format string warnings --- Source/Core/Common/Src/SDCardUtil.cpp | 3 ++- Source/Core/Common/Src/SysConf.cpp | 4 +++- Source/Core/Common/Src/x64Emitter.cpp | 4 +++- Source/Core/Core/Src/CoreParameter.cpp | 4 +++- Source/Core/Core/Src/CoreTiming.cpp | 3 ++- Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp | 5 +++-- Source/Core/Core/Src/HW/GCMemcard.cpp | 5 ++++- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp | 14 ++++++++------ .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 10 +++++++--- .../Core/Src/PowerPC/Interpreter/Interpreter.cpp | 4 ++-- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 3 ++- .../Core/Src/PowerPC/JitCommon/JitBackpatch.cpp | 3 ++- Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp | 3 ++- Source/Core/Core/Src/PowerPC/JitInterface.cpp | 5 +++-- Source/Core/Core/Src/PowerPC/PPCTables.cpp | 5 +++-- Source/Core/DiscIO/Src/CompressedBlob.cpp | 6 ++++-- Source/Core/DiscIO/Src/DiscScrubber.cpp | 8 +++++--- Source/Core/DiscIO/Src/FileSystemGCWii.cpp | 3 ++- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 3 ++- Source/Core/DolphinWX/Src/ISOFile.cpp | 2 +- Source/Core/DolphinWX/Src/ISOProperties.cpp | 3 ++- .../DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp | 8 +++++--- Source/Core/VideoBackends/D3D/Src/Render.cpp | 5 +++-- Source/Core/VideoBackends/OGL/Src/Render.cpp | 3 ++- 24 files changed, 75 insertions(+), 41 deletions(-) diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp index cf37ffff3e..5475cf131d 100644 --- a/Source/Core/Common/Src/SDCardUtil.cpp +++ b/Source/Core/Common/Src/SDCardUtil.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #ifndef _WIN32 #include // for unlink() @@ -196,7 +197,7 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) disk_size *= 1024 * 1024; if (disk_size < 0x800000 || disk_size > 0x800000000ULL) { - ERROR_LOG(COMMON, "Trying to create SD Card image of size %lliMB is out of range (8MB-32GB)", disk_size/(1024*1024)); + ERROR_LOG(COMMON, "Trying to create SD Card image of size %" PRIu64 "MB is out of range (8MB-32GB)", disk_size/(1024*1024)); return false; } diff --git a/Source/Core/Common/Src/SysConf.cpp b/Source/Core/Common/Src/SysConf.cpp index e1c3eb8abb..519765b10d 100644 --- a/Source/Core/Common/Src/SysConf.cpp +++ b/Source/Core/Common/Src/SysConf.cpp @@ -5,6 +5,8 @@ #include "FileUtil.h" #include "SysConf.h" +#include + SysConf::SysConf() : m_IsValid(false) { @@ -42,7 +44,7 @@ bool SysConf::LoadFromFile(const char *filename) u64 size = File::GetSize(filename); if (size != SYSCONF_SIZE) { - if (AskYesNoT("Your SYSCONF file is the wrong size.\nIt should be 0x%04x (but is 0x%04llx)\nDo you want to generate a new one?", + if (AskYesNoT("Your SYSCONF file is the wrong size.\nIt should be 0x%04x (but is 0x%04" PRIx64 ")\nDo you want to generate a new one?", SYSCONF_SIZE, size)) { GenerateSysConf(); diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 8b3002b26a..261213fdfa 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -7,6 +7,8 @@ #include "x64ABI.h" #include "CPUDetect.h" +#include + namespace Gen { @@ -176,7 +178,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, _assert_msg_(DYNA_REC, (distance < 0x80000000LL && distance >= -0x80000000LL) || !warn_64bit_offset, - "WriteRest: op out of range (0x%llx uses 0x%llx)", + "WriteRest: op out of range (0x%" PRIx64 " uses 0x%" PRIx64 ")", ripAddr, offset); s32 offs = (s32)distance; emit->Write32((u32)offs); diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 4cba012ea4..e7843fe997 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -18,6 +18,8 @@ #include "Core.h" // for bWii #include "FifoPlayer/FifoDataFile.h" +#include + SCoreStartupParameter::SCoreStartupParameter() : hInstance(0), bEnableDebugging(false), bAutomaticStart(false), bBootToPause(false), @@ -278,7 +280,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2) // Use the TitleIDhex for name and/or unique ID if launching from nand folder // or if it is not ascii characters (specifically sysmenu could potentially apply to other things) char titleidstr[17]; - snprintf(titleidstr, 17, "%016llx", ContentLoader.GetTitleID()); + snprintf(titleidstr, 17, "%016" PRIx64, ContentLoader.GetTitleID()); if (!m_strName.length()) { diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index c17e46fc80..6dac07e567 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Thread.h" #include "PowerPC/PowerPC.h" @@ -429,7 +430,7 @@ void LogPendingEvents() Event *ptr = first; while (ptr) { - INFO_LOG(POWERPC, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type); + INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", globalTimer, ptr->time, ptr->type); ptr = ptr->next; } } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp index 4013ec77c9..c879f5604b 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp @@ -6,6 +6,7 @@ #include "FileUtil.h" #include "DSP/DSPCore.h" #include "DSPLLEGlobals.h" +#include #if PROFILE @@ -37,12 +38,12 @@ void ProfilerDump(u64 count) File::IOFile pFile("DSP_Prof.txt", "wt"); if (pFile) { - fprintf(pFile.GetHandle(), "Number of DSP steps: %llu\n\n", count); + fprintf(pFile.GetHandle(), "Number of DSP steps: %" PRIu64 "\n\n", count); for (int i=0; i 0) { - fprintf(pFile.GetHandle(), "0x%04X: %llu\n", i, g_profileMap[i]); + fprintf(pFile.GetHandle(), "0x%04X: %" PRIu64 "\n", i, g_profileMap[i]); } } } diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index 22786b3027..adaa7a1858 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -4,6 +4,9 @@ #include "GCMemcard.h" #include "ColorUtil.h" + +#include + static void ByteSwap(u8 *valueA, u8 *valueB) { u8 tmp = *valueA; @@ -173,7 +176,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) } else { - PanicAlertT("Failed to read block %d of the save data\nMemcard may be truncated\nFilePosition:%llx", i, mcdFile.Tell()); + PanicAlertT("Failed to read block %d of the save data\nMemcard may be truncated\nFilePosition:%" PRIx64, i, mcdFile.Tell()); m_valid = false; break; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp index 9b6cf8ac8e..e0106bf273 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp @@ -19,6 +19,8 @@ #include "../../DiscIO/Src/FileMonitor.h" +#include + using namespace DVDInterface; @@ -108,7 +110,7 @@ bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) // Get TMD offset for requested partition... u64 const TMDOffset = ((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2 ) + 0x2c0; - INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016llx", TMDOffset); + INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016" PRIx64, TMDOffset); static u32 const TMDsz = 0x208; //CommandBuffer.PayloadBuffer[0].m_Size; u8 pTMD[TMDsz]; @@ -204,13 +206,13 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { - INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%llx) - (DVDAddr: 0x%llx, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%" PRIx64 ") - (DVDAddr: 0x%" PRIx64 ", Size: 0x%x)", pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress, Size); FileMon::CheckFile(std::string(pFilename), (int)m_pFileSystem->GetFileSize(pFilename)); } else { - INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unknown - (DVDAddr: 0x%llx, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unknown - (DVDAddr: 0x%" PRIx64 ", Size: 0x%x)", DVDAddress, Size); } } @@ -308,7 +310,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 u64 DVDAddress = (u64)DVDAddress32 << 2; - INFO_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: DVDAddr: 0x%08llx, Size: 0x%x", DVDAddress, Size); + INFO_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: DVDAddr: 0x%08" PRIx64 ", Size: 0x%x", DVDAddress, Size); if (Size > _BufferOutSize) { @@ -342,12 +344,12 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { - INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%llx) - (DVDAddr: 0x%llx)", + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%" PRIx64 ") - (DVDAddr: 0x%" PRIx64 ")", pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress); } else { - INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unknown - (DVDAddr: 0x%llx)", + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unknown - (DVDAddr: 0x%" PRIx64 ")", DVDAddress); } } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 151010e8fa..58ff0917ed 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -35,6 +35,10 @@ #include "WII_IPC_HLE_Device_es.h" +// need to include this before polarssl/aes.h, +// otherwise we may not get __STDC_FORMAT_MACROS +#include + #include "../PowerPC/PowerPC.h" #include "../VolumeHandler.h" #include "FileUtil.h" @@ -205,7 +209,7 @@ u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) if (!Loader.IsValid()) { - WARN_LOG(WII_IPC_ES, "ES: loader not valid for %llx", TitleID); + WARN_LOG(WII_IPC_ES, "ES: loader not valid for %" PRIx64, TitleID); return 0xffffffff; } @@ -940,7 +944,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) if (!bSuccess) { PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload a title that is not available in your NAND dump\n" - "TitleID %016llx.\n Dolphin will likely hang now.", TitleID); + "TitleID %016" PRIx64".\n Dolphin will likely hang now.", TitleID); } else { @@ -983,7 +987,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) //TODO: provide correct return code when bSuccess= false Memory::Write_U32(0, _CommandAddress + 0x4); - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH %016llx %08x %016llx %08x %016llx %04x", TitleID,view,ticketid,devicetype,titleid,access); + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x", TitleID,view,ticketid,devicetype,titleid,access); // IOCTL_ES_LAUNCH 0001000248414341 00000001 0001c0fef3df2cfa 00000000 0001000248414341 ffff // This is necessary because Reset(true) above deleted this object. Ew. diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp index 0082d9946b..dd71abcaeb 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp @@ -10,11 +10,11 @@ #include "../../Host.h" #include "../../IPC_HLE/WII_IPC_HLE.h" - #ifdef USE_GDBSTUB #include "../GDBStub.h" #endif +#include namespace { u32 last_pc; @@ -79,7 +79,7 @@ void Trace( UGeckoInstruction &instCode ) std::string fregs = ""; for (int i=0; i<32; i++) { - sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); + sprintf(freg, "f%02d: %08" PRIx64 " %08" PRIx64 " ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); fregs.append(freg); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index d7ccddb83c..8ecc3a2902 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Common.h" #include "../../HLE/HLE.h" @@ -217,7 +218,7 @@ namespace JitILProfiler const u64 totalElapsed = block.totalElapsed; const u64 numberOfCalls = block.numberOfCalls; const double elapsedPerCall = totalElapsed / (double)numberOfCalls; - fprintf(file.GetHandle(), "%016llx,%lld,%lld,%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); + fprintf(file.GetHandle(), "%016" PRIx64 ",%" PRId64 ",%" PRId64 ",%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); } } }; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index cd10306f2f..dd481da9bc 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Common.h" #include "disasm.h" @@ -32,7 +33,7 @@ static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) #endif PanicAlert("%s\n\n" "Error encountered accessing emulated address %08x.\n" - "Culprit instruction: \n%s\nat %#llx", + "Culprit instruction: \n%s\nat %#" PRIx64, text.c_str(), emAddress, disbuf, code_addr); return; } diff --git a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp index ffc5f94b62..a8e37c92dd 100644 --- a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp @@ -118,6 +118,7 @@ Fix profiled loads/stores to work safely. On 32-bit, one solution is to #include #include +#include #include #include #include "IR.h" @@ -1279,7 +1280,7 @@ void IRBuilder::WriteToFile(u64 codeHash) { } FILE* const file = writer->file.GetHandle(); - fprintf(file, "\ncode hash:%016llx\n", codeHash); + fprintf(file, "\ncode hash:%016" PRIx64 "\n", codeHash); const InstLoc lastCurReadPtr = curReadPtr; StartForwardPass(); diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.cpp b/Source/Core/Core/Src/PowerPC/JitInterface.cpp index ce8cc2e3ef..91d43a7792 100644 --- a/Source/Core/Core/Src/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/Src/PowerPC/JitInterface.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #ifdef _WIN32 #include @@ -171,12 +172,12 @@ namespace JitInterface double percent = 100.0 * (double)stat.cost / (double)cost_sum; #ifdef _WIN32 double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", + fprintf(f.GetHandle(), "%08x\t%s\t%" PRIu64 "\t%" PRIu64 "\t%.2lf\t%llf\t%lf\t%i\n", block->originalAddress, name.c_str(), stat.cost, block->ticCounter, percent, timePercent, (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); #else - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", + fprintf(f.GetHandle(), "%08x\t%s\t%" PRIu64 "\t???\t%.2lf\t???\t???\t%i\n", block->originalAddress, name.c_str(), stat.cost, percent, block->codeSize); #endif } diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index 0041904a75..d901f639e5 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "Common.h" #include "PPCTables.h" @@ -213,7 +214,7 @@ void LogCompiledInstructions() { if (m_allInstructions[i]->compileCount > 0) { - fprintf(f.GetHandle(), "%s\t%i\t%lld\t%08x\n", m_allInstructions[i]->opname, + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", m_allInstructions[i]->opname, m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount, m_allInstructions[i]->lastUse); } } @@ -223,7 +224,7 @@ void LogCompiledInstructions() { if (m_allInstructions[i]->compileCount == 0) { - fprintf(f.GetHandle(), "%s\t%i\t%lld\n", m_allInstructions[i]->opname, + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", m_allInstructions[i]->opname, m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount); } } diff --git a/Source/Core/DiscIO/Src/CompressedBlob.cpp b/Source/Core/DiscIO/Src/CompressedBlob.cpp index 3fdc779a44..c801ea3698 100644 --- a/Source/Core/DiscIO/Src/CompressedBlob.cpp +++ b/Source/Core/DiscIO/Src/CompressedBlob.cpp @@ -9,6 +9,8 @@ #include #endif +#include + #include "CompressedBlob.h" #include "DiscScrubber.h" #include "FileUtil.h" @@ -99,7 +101,7 @@ void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr) // First, check hash. u32 block_hash = HashAdler32(source, comp_block_size); if (block_hash != hashes[block_num]) - PanicAlert("Hash of block %lli is %08x instead of %08x.\n" + PanicAlert("Hash of block %" PRIu64 " is %08x instead of %08x.\n" "Your ISO, %s, is corrupt.", block_num, block_hash, hashes[block_num], file_name.c_str()); @@ -127,7 +129,7 @@ void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr) { // this seem to fire wrongly from time to time // to be sure, don't use compressed isos :P - PanicAlert("Failure reading block %lli - out of data and not at end.", block_num); + PanicAlert("Failure reading block %" PRIu64 " - out of data and not at end.", block_num); } inflateEnd(&z); if (uncomp_size != header.block_size) diff --git a/Source/Core/DiscIO/Src/DiscScrubber.cpp b/Source/Core/DiscIO/Src/DiscScrubber.cpp index 4f289cef9f..928383579e 100644 --- a/Source/Core/DiscIO/Src/DiscScrubber.cpp +++ b/Source/Core/DiscIO/Src/DiscScrubber.cpp @@ -7,6 +7,8 @@ #include "FileUtil.h" #include "DiscScrubber.h" +#include + namespace DiscIO { @@ -121,13 +123,13 @@ void GetNextBlock(File::IOFile& in, u8* buffer) if (m_isScrubbing && m_FreeTable[i]) { - DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset); + DEBUG_LOG(DISCIO, "Freeing 0x%016" PRIx64, CurrentOffset); std::fill(buffer, buffer + m_BlockSize, 0xFF); in.Seek(m_BlockSize, SEEK_CUR); } else { - DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset); + DEBUG_LOG(DISCIO, "Used 0x%016" PRIx64, CurrentOffset); in.ReadBytes(buffer, m_BlockSize); } @@ -150,7 +152,7 @@ void MarkAsUsed(u64 _Offset, u64 _Size) u64 CurrentOffset = _Offset; u64 EndOffset = CurrentOffset + _Size; - DEBUG_LOG(DISCIO, "Marking 0x%016llx - 0x%016llx as used", _Offset, EndOffset); + DEBUG_LOG(DISCIO, "Marking 0x%016" PRIx64 " - 0x%016" PRIx64 " as used", _Offset, EndOffset); while ((CurrentOffset < EndOffset) && (CurrentOffset < m_FileSize)) { diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index 90731b2573..cc09138f3e 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "FileSystemGCWii.h" #include "StringUtil.h" @@ -70,7 +71,7 @@ u64 CFileSystemGCWii::ReadFile(const char* _rFullPath, u8* _pBuffer, size_t _Max if (pFileInfo->m_FileSize > _MaxBufferSize) return 0; - DEBUG_LOG(DISCIO, "Filename: %s. Offset: %llx. Size: %llx",_rFullPath, + DEBUG_LOG(DISCIO, "Filename: %s. Offset: %" PRIx64 ". Size: %" PRIx64, _rFullPath, pFileInfo->m_Offset, pFileInfo->m_FileSize); m_rVolume->Read(pFileInfo->m_Offset, pFileInfo->m_FileSize, _pBuffer); diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index c1d8ef3787..54c59dd806 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "FileSearch.h" @@ -383,7 +384,7 @@ wxString NiceSizeFormat(u64 _size) auto const value = (_size + unit_size / 2) / unit_size; auto const frac = (_size % unit_size * 10 + unit_size / 2) / unit_size % 10; - return StrToWxStr(StringFromFormat("%llu.%llu %s", value, frac, unit_symbols[unit])); + return StrToWxStr(StringFromFormat("%" PRIu64 ".%" PRIu64 " %s", value, frac, unit_symbols[unit])); } void CGameListCtrl::InsertItemInReportView(long _Index) diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index a867d9b6ca..5aa02f5df1 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -188,7 +188,7 @@ std::string GameListItem::CreateCacheFilename() // Filename.extension_HashOfFolderPath_Size.cache // Append hash to prevent ISO name-clashing in different folders. - Filename.append(StringFromFormat("%s_%x_%llx.cache", + Filename.append(StringFromFormat("%s_%x_%zx.cache", extension.c_str(), HashFletcher((const u8 *)LegalPathname.c_str(), LegalPathname.size()), File::GetSize(m_FileName))); diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index a191b79677..89f07815b1 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -7,6 +7,7 @@ #endif #include +#include #include "Common.h" #include "CommonPaths.h" @@ -118,7 +119,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW u8 _tTitleID[8]; if(OpenISO->GetTitleID(_tTitleID)) { - snprintf(tmp, 17, "%016llx", Common::swap64(_tTitleID)); + snprintf(tmp, 17, "%016" PRIx64, Common::swap64(_tTitleID)); _iniFilename = tmp; } } diff --git a/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp b/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp index 10cebc904e..2ccc236395 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp +++ b/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp @@ -7,12 +7,14 @@ // Licensed under the terms of the GNU GPL, version 2 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +#include +#include + #include "WiiSaveCrypted.h" #include "FileUtil.h" #include "MathUtil.h" #include "NandPaths.h" #include "FileUtil.h" -#include static Common::replace_v replacements; @@ -152,7 +154,7 @@ void CWiiSaveCrypted::ReadHDR() md5((u8*)&_header, HEADER_SZ, md5_calc); if (memcmp(md5_file, md5_calc, 0x10)) { - PanicAlertT("MD5 mismatch\n %016llx%016llx != %016llx%016llx", Common::swap64(md5_file),Common::swap64(md5_file+8), Common::swap64(md5_calc), Common::swap64(md5_calc+8)); + PanicAlertT("MD5 mismatch\n %016" PRIx64 "%016" PRIx64 " != %016" PRIx64 "%016" PRIx64, Common::swap64(md5_file),Common::swap64(md5_file+8), Common::swap64(md5_calc), Common::swap64(md5_calc+8)); b_valid= false; } @@ -244,7 +246,7 @@ void CWiiSaveCrypted::ReadBKHDR() if (_sizeOfFiles + FULL_CERT_SZ != _totalSize) WARN_LOG(CONSOLE, "Size(%x) + cert(%x) does not equal totalsize(%x)", _sizeOfFiles, FULL_CERT_SZ, _totalSize); if (m_TitleID != Common::swap64(bkhdr.SaveGameTitle)) - WARN_LOG(CONSOLE, "Encrypted title (%llx) does not match unencrypted title (%llx)", m_TitleID, Common::swap64(bkhdr.SaveGameTitle)); + WARN_LOG(CONSOLE, "Encrypted title (%" PRIx64 ") does not match unencrypted title (%" PRIx64 ")", m_TitleID, Common::swap64(bkhdr.SaveGameTitle)); } void CWiiSaveCrypted::WriteBKHDR() diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 1a4421f3c5..091eb100be 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -2,7 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include +#include +#include #include "Timer.h" @@ -928,7 +929,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r if (SConfig::GetInstance().m_ShowLag) { char lag[10]; - StringCchPrintfA(lag, 10, "Lag: %llu\n", Movie::g_currentLagCount); + StringCchPrintfA(lag, 10, "Lag: %" PRIu64 "\n", Movie::g_currentLagCount); D3D::font.DrawTextScaled(0, 18, 20, 0.0f, 0xFF00FFFF, lag); } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index d03d3cedd3..63f8a3db49 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "GLUtil.h" #if defined(HAVE_WX) && HAVE_WX @@ -709,7 +710,7 @@ void Renderer::DrawDebugInfo() p+=sprintf(p, "FPS: %d\n", s_fps); if (SConfig::GetInstance().m_ShowLag) - p+=sprintf(p, "Lag: %llu\n", Movie::g_currentLagCount); + p+=sprintf(p, "Lag: %" PRIu64 "\n", Movie::g_currentLagCount); if (g_ActiveConfig.bShowInputDisplay) p+=sprintf(p, "%s", Movie::GetInputDisplay().c_str()); From 6f5650f82e81f9e9d1fea307cdff0d2f324bf79a Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 4 Nov 2013 09:33:33 +0100 Subject: [PATCH 20/81] Fix Bluetooth warnings --- Source/Core/Core/Src/IPC_HLE/hci.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/hci.h b/Source/Core/Core/Src/IPC_HLE/hci.h index 8923f68fb4..41f145a8ed 100644 --- a/Source/Core/Core/Src/IPC_HLE/hci.h +++ b/Source/Core/Core/Src/IPC_HLE/hci.h @@ -84,14 +84,6 @@ // All structs in this file are packed #pragma pack(push, 1) -/* - * Bluetooth Address Family Protocol Numbers - */ -#define BTPROTO_HCI 1 -#define BTPROTO_L2CAP 2 -#define BTPROTO_RFCOMM 3 -#define BTPROTO_SCO 4 - /* All sizes are in bytes */ #define BLUETOOTH_BDADDR_SIZE 6 @@ -102,9 +94,8 @@ typedef struct { uint8_t b[BLUETOOTH_BDADDR_SIZE]; } bdaddr_t; -#endif - #define BDADDR_ANY { { 0, 0, 0, 0, 0, 0 } } +#endif /************************************************************************** ************************************************************************** From 2fecb033be90217f47f5c4d19b44c2cf0595779b Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 7 Nov 2013 03:38:04 +0100 Subject: [PATCH 21/81] Jit64: micro-optimize ps_sel Adapted from a patch by konpie: https://forums.dolphin-emu.org/Thread-code-bug-report-based-on-3-0-735 --- Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp index 96a3335249..781b75a538 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp @@ -14,10 +14,9 @@ // cmppd, andpd, andnpd, or // lfsx, ps_merge01 etc -const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL}; -const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL}; -const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0}; -const double GC_ALIGNED16(psZeroZero[2]) = {0.0, 0.0}; +static const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL}; +static const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL}; +static const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0}; void Jit64::ps_mr(UGeckoInstruction inst) { @@ -52,14 +51,15 @@ void Jit64::ps_sel(UGeckoInstruction inst) fpr.Lock(a, b, c, d); MOVAPD(XMM0, fpr.R(a)); + XORPD(XMM1, R(XMM1)); // XMM0 = XMM0 < 0 ? all 1s : all 0s - CMPPD(XMM0, M((void*)psZeroZero), LT); + CMPPD(XMM0, R(XMM1), LT); MOVAPD(XMM1, R(XMM0)); ANDPD(XMM0, fpr.R(b)); ANDNPD(XMM1, fpr.R(c)); + ORPD(XMM0, R(XMM1)); fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), R(XMM0)); - ORPD(fpr.RX(d), R(XMM1)); fpr.UnlockAll(); } From 6054129df8df194828cdf4409c7bf2180af7b265 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 13 Nov 2013 04:46:34 +0100 Subject: [PATCH 22/81] x64: detect FMA support --- Source/Core/Common/Src/CPUDetect.h | 1 + Source/Core/Common/Src/x64CPUDetect.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index be6ce34985..e93a902d63 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -41,6 +41,7 @@ struct CPUInfo bool bLZCNT; bool bSSE4A; bool bAVX; + bool bFMA; bool bAES; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 07b35cb968..2b434ad2b6 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -169,7 +169,11 @@ void CPUInfo::Detect() if (((cpu_id[2] >> 28) & 1) && ((cpu_id[2] >> 27) & 1)) { if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) + { bAVX = true; + if ((cpu_id[2] >> 12) & 1) + bFMA = true; + } } } if (max_ex_fn >= 0x80000004) { @@ -225,6 +229,7 @@ std::string CPUInfo::Summarize() if (bSSE4_2) sum += ", SSE4.2"; if (HTT) sum += ", HTT"; if (bAVX) sum += ", AVX"; + if (bFMA) sum += ", FMA"; if (bAES) sum += ", AES"; if (bLongMode) sum += ", 64-bit support"; return sum; From 22b47d5b9c078d978c0d71b0493509b5e30d0857 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 13 Nov 2013 05:58:28 +0100 Subject: [PATCH 23/81] Jit64: Fix and re-enable psq_l for W=1 Patch by konpie: https://forums.dolphin-emu.org/Thread-code-bug-report-based-on-3-0-735 --- .../Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp index e881b5e7e8..a2cb0784d1 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -122,12 +122,6 @@ void Jit64::psq_l(UGeckoInstruction inst) const UGQR gqr(rSPR(SPR_GQR0 + inst.I)); - if (inst.W) { - // PanicAlert("Single ps load: %i %i", gqr.ST_TYPE, gqr.ST_SCALE); - Default(inst); - return; - } - bool update = inst.OPCD == 57; int offset = inst.SIMM_12; @@ -143,6 +137,8 @@ void Jit64::psq_l(UGeckoInstruction inst) MOV(32, gpr.R(inst.RA), R(ECX)); MOVZX(32, 16, EAX, M(((char *)&GQR(inst.I)) + 2)); MOVZX(32, 8, EDX, R(AL)); + if (inst.W) + OR(32, R(EDX), Imm8(8)); #ifdef _M_IX86 int addr_scale = SCALE_4; #else From ae86850a787eada3a585583878649c93b78cfcd6 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 4 Nov 2013 21:37:07 +0100 Subject: [PATCH 24/81] x64: support VEX opcode encoding and add some AVX instructions --- Source/Core/Common/Src/x64Emitter.cpp | 53 +++++++++++++++++++++++++++ Source/Core/Common/Src/x64Emitter.h | 13 +++++++ 2 files changed, 66 insertions(+) diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 261213fdfa..05540ba4a8 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -156,6 +156,40 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const #endif } +void OpArg::WriteVex(XEmitter* emit, int size, int packed, Gen::X64Reg regOp1, Gen::X64Reg regOp2) const +{ + int R = !(regOp1 & 8); + int X = !(indexReg & 8); + int B = !(offsetOrBaseReg & 8); + + // not so sure about this one... + int W = 0; + + // aka map_select in AMD manuals + // only support VEX opcode map 1 for now (analog to secondary opcode map) + int mmmmm = 1; + + int vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf); + int L = size == 256; + int pp = (packed << 1) | (size == 64); + + // do we need any VEX fields that only appear in the three-byte form? + if (X == 1 && B == 1 && W == 0 && mmmmm == 1) + { + u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 1) | pp; + emit->Write8(0xC5); + emit->Write8(RvvvvLpp); + } + else + { + u8 RXBmmmmm = (R << 7) | (X << 6) | (B << 5) | mmmmm; + u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 1) | pp; + emit->Write8(0xC4); + emit->Write8(RXBmmmmm); + emit->Write8(WvvvvLpp); + } +} + void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, bool warn_64bit_offset) const { @@ -1143,6 +1177,18 @@ void XEmitter::WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg a arg.WriteRest(this, extrabytes); } +void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes) +{ + WriteAVXOp(size, sseOp, packed, regOp, X64Reg::INVALID_REG, arg, extrabytes); +} + +void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes) +{ + arg.WriteVex(this, size, packed, regOp1, regOp2); + Write8(sseOp); + arg.WriteRest(this, extrabytes, regOp1); +} + void XEmitter::MOVD_xmm(X64Reg dest, const OpArg &arg) {WriteSSEOp(64, 0x6E, true, dest, arg, 0);} void XEmitter::MOVD_xmm(const OpArg &arg, X64Reg src) {WriteSSEOp(64, 0x7E, true, src, arg, 0);} @@ -1446,6 +1492,13 @@ void XEmitter::PMOVMSKB(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0xD7, true, d void XEmitter::PSHUFLW(X64Reg regOp, OpArg arg, u8 shuffle) {WriteSSEOp(64, 0x70, false, regOp, arg, 1); Write8(shuffle);} +// VEX +void XEmitter::VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseADD, false, regOp1, regOp2, arg);} +void XEmitter::VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseSUB, false, regOp1, regOp2, arg);} +void XEmitter::VMULSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseMUL, false, regOp1, regOp2, arg);} +void XEmitter::VDIVSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseDIV, false, regOp1, regOp2, arg);} +void XEmitter::VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseSQRT, false, regOp1, regOp2, arg);} + // Prefixes void XEmitter::LOCK() { Write8(0xF0); } diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 6ce16abcce..87e76ef21a 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -33,6 +33,9 @@ enum X64Reg XMM0=0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, + YMM0=0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15, + INVALID_REG = 0xFFFFFFFF }; @@ -111,6 +114,7 @@ struct OpArg offset = _offset; } void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const; + void WriteVex(XEmitter* emit, int size, int packed, Gen::X64Reg regOp1, X64Reg regOp2) const; void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=(X64Reg)0xFF, bool warn_64bit_offset = true) const; void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits); // This one is public - must be written to @@ -239,6 +243,8 @@ private: void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext); void WriteMXCSR(OpArg arg, int ext); void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0); + void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0); + void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0); void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2); protected: @@ -616,6 +622,13 @@ public: void PSRAW(X64Reg reg, int shift); void PSRAD(X64Reg reg, int shift); + // AVX + void VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VMULSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VDIVSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void RTDSC(); // Utility functions From ddaf29e039d1736be1ca48c1c0b6af1c8d4ec47d Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 4 Nov 2013 21:42:30 +0100 Subject: [PATCH 25/81] Jit64: use AVX instructions in some places --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 2 +- .../Src/PowerPC/Jit64/Jit_FloatingPoint.cpp | 94 +++++++++++++------ 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 8676b1cb5a..71a556cb5f 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -119,7 +119,7 @@ public: void tri_op(int d, int a, int b, bool reversible, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); typedef u32 (*Operation)(u32 a, u32 b); void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false); - void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); + void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op_2)(Gen::X64Reg, Gen::OpArg), void (XEmitter::*op_3)(Gen::X64Reg, Gen::X64Reg, Gen::OpArg)); // OPCODES void unknown_instruction(UGeckoInstruction _inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index ec8ddc63d3..066ba69dfd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -13,37 +13,62 @@ static const u64 GC_ALIGNED16(psAbsMask2[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFF static const double GC_ALIGNED16(psOneOne2[2]) = {1.0, 1.0}; static const double one_const = 1.0f; -void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)) +void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, + void (XEmitter::*op_2)(Gen::X64Reg, Gen::OpArg), + void (XEmitter::*op_3)(Gen::X64Reg, Gen::X64Reg, Gen::OpArg)) { + if (!cpu_info.bAVX) + { + op_3 = nullptr; + } + fpr.Lock(d, a, b); if (d == a) { - fpr.BindToRegister(d, true); - (this->*op)(fpr.RX(d), fpr.R(b)); + fpr.BindToRegister(d); + (this->*op_2)(fpr.RX(d), fpr.R(b)); } else if (d == b) { if (reversible) { - fpr.BindToRegister(d, true); - (this->*op)(fpr.RX(d), fpr.R(a)); + fpr.BindToRegister(d); + (this->*op_2)(fpr.RX(d), fpr.R(a)); } else { - MOVSD(XMM0, fpr.R(b)); - fpr.BindToRegister(d, !dupe); - MOVSD(fpr.RX(d), fpr.R(a)); - (this->*op)(fpr.RX(d), Gen::R(XMM0)); + if (op_3) + { + fpr.BindToRegister(d); + fpr.BindToRegister(a, true, false); + (this->*op_3)(fpr.RX(d), fpr.RX(a), fpr.R(b)); + } + else + { + MOVSD(XMM0, fpr.R(b)); + fpr.BindToRegister(d, !single); + MOVSD(fpr.RX(d), fpr.R(a)); + (this->*op_2)(fpr.RX(d), Gen::R(XMM0)); + } } } else { - // Sources different from d, can use rather quick solution - fpr.BindToRegister(d, !dupe); - MOVSD(fpr.RX(d), fpr.R(a)); - (this->*op)(fpr.RX(d), fpr.R(b)); + if (op_3) + { + fpr.BindToRegister(d, !single); + fpr.BindToRegister(a); + (this->*op_3)(fpr.RX(d), fpr.RX(a), fpr.R(b)); + } + else + { + fpr.BindToRegister(d, !single); + MOVSD(fpr.RX(d), fpr.R(a)); + (this->*op_2)(fpr.RX(d), fpr.R(b)); + } } - if (dupe) + + if (single) { ForceSinglePrecisionS(fpr.RX(d)); if (cpu_info.bSSE3) @@ -73,13 +98,13 @@ void Jit64::fp_arith_s(UGeckoInstruction inst) Default(inst); return; } - bool dupe = inst.OPCD == 59; + bool single = inst.OPCD == 59; switch (inst.SUBOP5) { - case 18: fp_tri_op(inst.FD, inst.FA, inst.FB, false, dupe, &XEmitter::DIVSD); break; //div - case 20: fp_tri_op(inst.FD, inst.FA, inst.FB, false, dupe, &XEmitter::SUBSD); break; //sub - case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, dupe, &XEmitter::ADDSD); break; //add - case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, dupe, &XEmitter::MULSD); break; //mul + case 18: fp_tri_op(inst.FD, inst.FA, inst.FB, false, single, &XEmitter::DIVSD, &XEmitter::VDIVSD); break; //div + case 20: fp_tri_op(inst.FD, inst.FA, inst.FB, false, single, &XEmitter::SUBSD, &XEmitter::VSUBSD); break; //sub + case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, single, &XEmitter::ADDSD, &XEmitter::VADDSD); break; //add + case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, single, &XEmitter::MULSD, &XEmitter::VMULSD); break; //mul default: _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); } @@ -87,17 +112,24 @@ void Jit64::fp_arith_s(UGeckoInstruction inst) void Jit64::frsqrtex(UGeckoInstruction inst) { - INSTRUCTION_START - JITDISABLE(bJITFloatingPointOff) - int d = inst.FD; - int b = inst.FB; - fpr.Lock(b, d); - fpr.BindToRegister(d, true, true); - MOVSD(XMM0, M((void *)&one_const)); - SQRTSD(XMM1, fpr.R(b)); - DIVSD(XMM0, R(XMM1)); - MOVSD(fpr.R(d), XMM0); - fpr.UnlockAll(); + INSTRUCTION_START + JITDISABLE(bJITFloatingPointOff) + int d = inst.FD; + int b = inst.FB; + fpr.Lock(b, d); + fpr.BindToRegister(d, d == b, true); + MOVSD(XMM0, M((void *)&one_const)); + SQRTSD(XMM1, fpr.R(b)); + if (cpu_info.bAVX) + { + VDIVSD(fpr.RX(d), XMM0, R(XMM1)); + } + else + { + DIVSD(XMM0, R(XMM1)); + MOVSD(fpr.R(d), XMM0); + } + fpr.UnlockAll(); } void Jit64::fmaddXX(UGeckoInstruction inst) @@ -198,7 +230,7 @@ void Jit64::fmrx(UGeckoInstruction inst) int d = inst.FD; int b = inst.FB; fpr.Lock(b, d); - fpr.BindToRegister(d, true, true); + fpr.BindToRegister(d, d == b, true); MOVSD(XMM0, fpr.R(b)); MOVSD(fpr.R(d), XMM0); fpr.UnlockAll(); From 710a0ff435c8593914c6eb074b6bc4d1985ae8c5 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 7 Nov 2013 01:57:52 +0100 Subject: [PATCH 26/81] Jit64: don't unnecessarily load registers --- Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index 066ba69dfd..c4699ecc62 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -46,7 +46,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, else { MOVSD(XMM0, fpr.R(b)); - fpr.BindToRegister(d, !single); + fpr.BindToRegister(d, false); MOVSD(fpr.RX(d), fpr.R(a)); (this->*op_2)(fpr.RX(d), Gen::R(XMM0)); } @@ -56,13 +56,13 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, { if (op_3) { - fpr.BindToRegister(d, !single); + fpr.BindToRegister(d, false); fpr.BindToRegister(a); (this->*op_3)(fpr.RX(d), fpr.RX(a), fpr.R(b)); } else { - fpr.BindToRegister(d, !single); + fpr.BindToRegister(d, false); MOVSD(fpr.RX(d), fpr.R(a)); (this->*op_2)(fpr.RX(d), fpr.R(b)); } From 466a7afde336d381e250d51e4c268c769e072a02 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 24 Oct 2013 13:52:22 +0200 Subject: [PATCH 27/81] Interpreter: support non-IEEE mode emulation v2: fix fxsave on visual studio, thx @ rodolfo for this patch --- Source/Core/Common/Src/CPUDetect.h | 3 ++ Source/Core/Common/Src/FPURoundMode.h | 2 +- .../Core/Common/Src/GenericFPURoundMode.cpp | 2 +- Source/Core/Common/Src/x64CPUDetect.cpp | 22 +++++++++++++ Source/Core/Common/Src/x64FPURoundMode.cpp | 32 ++++++++++++++----- .../Interpreter_SystemRegisters.cpp | 11 ++----- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index e93a902d63..eab62d3d19 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -43,6 +43,9 @@ struct CPUInfo bool bAVX; bool bFMA; bool bAES; + // FXSAVE/FXRSTOR + bool bFXSR; + bool bDAZ; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h index fad4d5d6aa..c552ad7ff0 100644 --- a/Source/Core/Common/Src/FPURoundMode.h +++ b/Source/Core/Common/Src/FPURoundMode.h @@ -36,7 +36,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode); - void SetSIMDMode(u32 mode); + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode); /* * There are two different flavors of float to int conversion: diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp index cc878291a1..c8e70a4990 100644 --- a/Source/Core/Common/Src/GenericFPURoundMode.cpp +++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp @@ -26,7 +26,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode) { } - void SetSIMDMode(u32 mode) + void SetSIMDMode(u32 mode, u32 nonIEEEMode) { } void SaveSIMDState() diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 2b434ad2b6..182cca5224 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -162,6 +162,28 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; if ((cpu_id[2] >> 25) & 1) bAES = true; + if ((cpu_id[3] >> 24) & 1) + { + // We can use FXSAVE. + bFXSR = true; + + GC_ALIGNED16(u8 fx_state[512]); + memset(fx_state, 0, sizeof(fx_state)); +#ifdef _WIN32 +#ifdef _M_IX86 + _fxsave(fx_state); +#elif defined (_M_X64) + _fxsave64(fx_state); +#endif +#else + __asm__("fxsave %0" : "=m" (fx_state)); +#endif + + // lowest byte of MXCSR_MASK + if ((fx_state[0x1C] >> 6) & 1) + bDAZ = true; + } + // AVX support requires 3 separate checks: // - Is the AVX bit set in CPUID? // - Is the XSAVE bit set in CPUID? diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp index 2c950ade96..a8b0d16809 100644 --- a/Source/Core/Common/Src/x64FPURoundMode.cpp +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -4,6 +4,7 @@ #include "Common.h" #include "FPURoundMode.h" +#include "CPUDetect.h" #ifndef _WIN32 static const unsigned short FPU_ROUND_NEAR = 0 << 10; @@ -14,8 +15,11 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10; #include #endif -const u32 MASKS = 0x1F80; // mask away the interrupts. +// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register) +const u32 EXCEPTION_MASK = 0x1F80; +// Denormals-Are-Zero (non-IEEE mode: denormal inputs are set to +/- 0) const u32 DAZ = 0x40; +// Flush-To-Zero (non-IEEE mode: denormal outputs are set to +/- 0) const u32 FTZ = 0x8000; namespace FPURoundMode @@ -79,16 +83,28 @@ namespace FPURoundMode //but still - set any useful sse options here #endif } - void SetSIMDMode(u32 mode) + + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode) { - static const u32 ssetable[4] = + // lookup table for FPSCR.RN-to-MXCSR.RC translation + static const u32 roundingModeLUT[4] = { - (0 << 13) | MASKS, - (3 << 13) | MASKS, - (2 << 13) | MASKS, - (1 << 13) | MASKS, + (0 << 13) | EXCEPTION_MASK, // nearest + (3 << 13) | EXCEPTION_MASK, // -inf + (2 << 13) | EXCEPTION_MASK, // +inf + (1 << 13) | EXCEPTION_MASK, // zero }; - u32 csr = ssetable[mode]; + u32 csr = roundingModeLUT[roundingMode]; + + static const u32 denormalLUT[2] = + { + FTZ, // flush-to-zero only + FTZ | DAZ, // flush-to-zero and denormals-are-zero (may not be supported) + }; + if (nonIEEEMode) + { + csr |= denormalLUT[cpu_info.bDAZ]; + } _mm_setcsr(csr); } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 688d166608..475f7591ce 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -48,15 +48,8 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) // Pokemon Colosseum does this. Gah. } - // Also corresponding SSE rounding mode setting - if (FPSCR.NI) - { - // Either one of these two breaks Beyond Good & Evil. - // if (cpu_info.bSSSE3) - // csr |= DAZ; - // csr |= FTZ; - } - FPURoundMode::SetSIMDMode(FPSCR.RN); + // Set SSE rounding mode and denormal handling + FPURoundMode::SetSIMDMode(FPSCR.RN, FPSCR.NI); } void Interpreter::mtfsb0x(UGeckoInstruction _inst) From cd069fdce1bd7a30f99f3bed9dfe0af60cd562d8 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 24 Oct 2013 22:05:53 +0200 Subject: [PATCH 28/81] Interpreter: software-based flush-to-zero bDAZ is now called bFlushToZero to better reflect what it's actually used for. I decided not to support any hardware-based flush-to-zero on systems that don't support this for both inputs _and_ outputs. It makes the code cleaner and the intersection of CPUs that support SSE2 but not DAZ should be very small. --- Source/Core/Common/Src/CPUDetect.h | 5 +++- Source/Core/Common/Src/MathUtil.h | 4 +-- Source/Core/Common/Src/x64CPUDetect.cpp | 8 ++++- Source/Core/Common/Src/x64FPURoundMode.cpp | 2 +- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 29 ++++++++----------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index eab62d3d19..967be0949b 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -45,7 +45,10 @@ struct CPUInfo bool bAES; // FXSAVE/FXRSTOR bool bFXSR; - bool bDAZ; + // This flag indicates that the hardware supports some mode + // in which denormal inputs _and_ outputs are automatically set to (signed) zero. + // TODO: ARM + bool bFlushToZero; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index 31772c3c60..f085c6ed2b 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -64,10 +64,10 @@ inline float FlushToZero(float f) return x.f; } -inline double FlushToZeroAsFloat(double d) +inline double FlushToZero(double d) { IntDouble x; x.d = d; - if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) + if ((x.i & DOUBLE_EXP) == 0) x.i &= DOUBLE_SIGN; // turn into signed zero return x.d; } diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 182cca5224..d6f36eb142 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -162,6 +162,7 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; if ((cpu_id[2] >> 25) & 1) bAES = true; + // To check DAZ support, we first need to check FXSAVE support. if ((cpu_id[3] >> 24) & 1) { // We can use FXSAVE. @@ -181,7 +182,12 @@ void CPUInfo::Detect() // lowest byte of MXCSR_MASK if ((fx_state[0x1C] >> 6) & 1) - bDAZ = true; + { + // On x86, the FTZ field (supported since SSE1) only flushes denormal _outputs_ to zero, + // now that we checked DAZ support (flushing denormal _inputs_ to zero), + // we can set our generic flag. + bFlushToZero = true; + } } // AVX support requires 3 separate checks: diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp index a8b0d16809..f46c6000eb 100644 --- a/Source/Core/Common/Src/x64FPURoundMode.cpp +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -103,7 +103,7 @@ namespace FPURoundMode }; if (nonIEEEMode) { - csr |= denormalLUT[cpu_info.bDAZ]; + csr |= denormalLUT[cpu_info.bFlushToZero]; } _mm_setcsr(csr); } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h index d379bf7049..9190a18ed7 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -5,6 +5,7 @@ #ifndef _INTERPRETER_FPUTILS_H #define _INTERPRETER_FPUTILS_H +#include "CPUDetect.h" #include "Interpreter.h" #include "MathUtil.h" @@ -69,28 +70,22 @@ inline void UpdateFPSCR() inline double ForceSingle(double _x) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - if (FPSCR.NI) - _x = FlushToZeroAsFloat(_x); - - double x = static_cast(_x); - + // convert to float... + float x = _x; + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + x = FlushToZero(x); + } + // ...and back to double: return x; } inline double ForceDouble(double d) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - - //if (FPSCR.NI) - //{ - // IntDouble x; x.d = d; - //if ((x.i & DOUBLE_EXP) == 0) - // x.i &= DOUBLE_SIGN; // turn into signed zero - // return x.d; - //} + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + d = FlushToZero(d); + } return d; } From d78c8c21a21a58f6bcd0fd8c01648c5c0bf2cc8b Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 24 Oct 2013 22:50:20 +0200 Subject: [PATCH 29/81] jit64: enable fp instructions faddx fsubx fdivx fdivsx all of them are now accurate enough as we handle non-ieee floats correctly --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 2 +- .../Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp | 16 ++++++++-------- .../Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index 71a556cb5f..139414a103 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -182,7 +182,7 @@ public: void ps_sum(UGeckoInstruction inst); void ps_muls(UGeckoInstruction inst); - void fp_arith_s(UGeckoInstruction inst); + void fp_arith(UGeckoInstruction inst); void frsqrtex(UGeckoInstruction inst); void fcmpx(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 0ff2bf5d7f..dc81015573 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -320,12 +320,12 @@ static GekkoOPTemplate table31_2[] = static GekkoOPTemplate table59[] = { - {18, &Jit64::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, - {20, &Jit64::fp_arith_s}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::fp_arith_s}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, + {20, &Jit64::fp_arith}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, // {22, &Jit64::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko {24, &Jit64::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, {30, &Jit64::fmaddXX}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, @@ -354,12 +354,12 @@ static GekkoOPTemplate table63[] = static GekkoOPTemplate table63_2[] = { - {18, &Jit64::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, - {20, &Jit64::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::Default}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, + {20, &Jit64::fp_arith}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, {22, &Jit64::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, {23, &Jit64::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, {26, &Jit64::frsqrtex}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index c4699ecc62..b0d0ab4853 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -85,7 +85,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, fpr.UnlockAll(); } -void Jit64::fp_arith_s(UGeckoInstruction inst) +void Jit64::fp_arith(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) @@ -106,7 +106,7 @@ void Jit64::fp_arith_s(UGeckoInstruction inst) case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, single, &XEmitter::ADDSD, &XEmitter::VADDSD); break; //add case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, single, &XEmitter::MULSD, &XEmitter::VMULSD); break; //mul default: - _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); + _assert_msg_(DYNA_REC, 0, "fp_arith WTF!!!"); } } From 288bef280784e02cc80f0aee9360e45548c06e9a Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sun, 3 Nov 2013 23:56:30 +0100 Subject: [PATCH 30/81] x64: add small warning if CPU has SSE2 but not DAZ --- Source/Core/Common/Src/x64CPUDetect.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index d6f36eb142..2fa25e8074 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -250,7 +250,12 @@ std::string CPUInfo::Summarize() { std::string sum(cpu_string); if (bSSE) sum += ", SSE"; - if (bSSE2) sum += ", SSE2"; + if (bSSE2) + { + sum += ", SSE2"; + if (!bFlushToZero) + sum += " (but not DAZ!)"; + } if (bSSE3) sum += ", SSE3"; if (bSSSE3) sum += ", SSSE3"; if (bSSE4_1) sum += ", SSE4.1"; From 038ffea369bbe65a7436c81f6ff7fb12d14ee46d Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 13 Nov 2013 08:03:18 +0100 Subject: [PATCH 31/81] Jit64: don't flush clean FPRs --- Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp index f804877627..b2317c9394 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp @@ -351,11 +351,12 @@ void FPURegCache::StoreFromRegister(int i) { X64Reg xr = regs[i].location.GetSimpleReg(); _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - store - invalid reg"); + OpArg newLoc = GetDefaultLocation(i); + if (xregs[xr].dirty) + emit->MOVAPD(newLoc, xr); xregs[xr].free = true; xregs[xr].dirty = false; xregs[xr].ppcReg = -1; - OpArg newLoc = GetDefaultLocation(i); - emit->MOVAPD(newLoc, xr); regs[i].location = newLoc; regs[i].away = false; } From f96e9e1ae43a510c83087efcbfb5fd57cdfe0b38 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Wed, 13 Nov 2013 04:03:46 -0500 Subject: [PATCH 32/81] warnings and code formatting --- Source/Core/Common/Src/ChunkFile.h | 4 +++- Source/Core/Common/Src/StringUtil.cpp | 12 ++++++++---- Source/Core/Common/Src/SysConf.cpp | 2 +- Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp | 4 ++-- Source/Core/VideoBackends/D3D/Src/Render.cpp | 4 ++-- Source/Core/VideoBackends/D3D/Src/VertexManager.cpp | 4 ++-- Source/Core/VideoCommon/Src/PixelShaderGen.cpp | 12 +++++++++--- Source/Core/VideoCommon/Src/PixelShaderManager.cpp | 8 ++++---- Source/Core/VideoCommon/Src/ShaderGenCommon.h | 2 +- Source/Core/VideoCommon/Src/VertexShaderGen.cpp | 6 +++++- 10 files changed, 37 insertions(+), 21 deletions(-) diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 5192b4332e..d7aeba0558 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -193,10 +193,12 @@ public: void DoPointer(T*& x, T* const base) { // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range - s32 offset = x - base; + ptrdiff_t offset = x - base; Do(offset); if (mode == MODE_READ) + { x = base + offset; + } } // Let's pretend std::list doesn't exist! diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 5243b24260..7ad4ac6ca5 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -404,26 +404,30 @@ std::string UriEncode(const std::string & sSrc) std::string UTF16ToUTF8(const std::wstring& input) { - auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); + auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), nullptr, 0, nullptr, nullptr); std::string output; output.resize(size); - if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) + if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), &output[0], (int)output.size(), nullptr, nullptr)) + { output.clear(); + } return output; } std::wstring CPToUTF16(u32 code_page, const std::string& input) { - auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); + auto const size = MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), nullptr, 0); std::wstring output; output.resize(size); - if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size())) + if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), &output[0], (int)output.size())) + { output.clear(); + } return output; } diff --git a/Source/Core/Common/Src/SysConf.cpp b/Source/Core/Common/Src/SysConf.cpp index 519765b10d..acfb11b0ed 100644 --- a/Source/Core/Common/Src/SysConf.cpp +++ b/Source/Core/Common/Src/SysConf.cpp @@ -153,7 +153,7 @@ unsigned int create_item(SSysConfEntry &item, SysconfType type, const std::strin { item.offset = offset; item.type = type; - item.nameLength = name.length(); + item.nameLength = (u8)(name.length()); strncpy(item.name, name.c_str(), 32); item.dataLength = data_length; item.data = new u8[data_length]; diff --git a/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp b/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp index 1bcd314291..b2c77a876e 100644 --- a/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp +++ b/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp @@ -116,7 +116,7 @@ void PerfQuery::FlushOne() } // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight()); m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer); --m_query_count; @@ -147,7 +147,7 @@ void PerfQuery::WeakFlush() if (hr == S_OK) { // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight()); m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer); --m_query_count; diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 091eb100be..c7ad9e2bda 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -693,10 +693,10 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - for (unsigned int y = 0; y < rc.GetHeight(); ++y) + for (auto y = 0; y < rc.GetHeight(); ++y) { u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; - for (unsigned int x = 0; x < rc.GetWidth(); ++x) + for (auto x = 0; x < rc.GetWidth(); ++x) { *ptr = 0xFF; ptr += 4; diff --git a/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp b/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp index a48a3d289a..b951a7464f 100644 --- a/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp @@ -222,9 +222,9 @@ void VertexManager::vFlush() tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), + ((tex.texMode0[i&3].min_filter & 3) != 0), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + (tex.texImage1[i&3].image_type != 0)); if (tentry) { diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 442cfc1ef4..f107da783e 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -316,8 +316,10 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes - for (int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + { out.Write("VARYIN float3 uv%d_2;\n", i); + } out.Write("VARYIN float4 clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) { @@ -392,9 +394,13 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T out.Write("float4 colors_1 = colors_12;\n"); // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes - if(numTexgen) - for (int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + if (numTexgen) + { + for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + { out.Write("float3 uv%d = uv%d_2;\n", i, i); + } + } out.Write("float4 clipPos = clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) { diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp index b999ada6a3..98722e48ce 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp @@ -84,7 +84,7 @@ void PixelShaderManager::SetConstants(u32 components) // they are the coefficients from the center to the border of the screen // so to simplify I use the hi coefficient as K in the shader taking 256 as the scale constants.fog[2][0] = ScreenSpaceCenter; - constants.fog[2][1] = Renderer::EFBToScaledX((int)(2.0f * xfregs.viewport.wd)); + constants.fog[2][1] = (float)Renderer::EFBToScaledX((int)(2.0f * xfregs.viewport.wd)); constants.fog[2][2] = bpmem.fogRange.K[4].HI / 256.0f; } else @@ -263,8 +263,8 @@ void PixelShaderManager::SetZTextureTypeChanged() void PixelShaderManager::SetTexCoordChanged(u8 texmapid) { TCoordInfo& tc = bpmem.texcoords[texmapid]; - constants.texdims[texmapid][2] = tc.s.scale_minus_1 + 1; - constants.texdims[texmapid][3] = tc.t.scale_minus_1 + 1; + constants.texdims[texmapid][2] = (float)(tc.s.scale_minus_1 + 1); + constants.texdims[texmapid][3] = (float)(tc.t.scale_minus_1 + 1); dirty = true; } @@ -283,7 +283,7 @@ void PixelShaderManager::SetFogParamChanged() constants.fog[1][0] = bpmem.fog.a.GetA(); constants.fog[1][1] = (float)bpmem.fog.b_magnitude / 0xFFFFFF; constants.fog[1][2] = bpmem.fog.c_proj_fsel.GetC(); - constants.fog[1][3] = 1 << bpmem.fog.b_shift; + constants.fog[1][3] = (float)(1 << bpmem.fog.b_shift); } else { diff --git a/Source/Core/VideoCommon/Src/ShaderGenCommon.h b/Source/Core/VideoCommon/Src/ShaderGenCommon.h index 35ec50407a..b56e9f29ff 100644 --- a/Source/Core/VideoCommon/Src/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/Src/ShaderGenCommon.h @@ -236,7 +236,7 @@ public: u32 value = ((u32*)&new_uid.GetUidData())[i]; if ((i % 4) == 0) { - unsigned int last_value = (i+3 < new_uid.GetUidDataSize()-1) ? i+3 : new_uid.GetUidDataSize(); + auto last_value = (i+3 < new_uid.GetUidDataSize()-1) ? i+3 : new_uid.GetUidDataSize(); file << std::setfill(' ') << std::dec; file << "Values " << std::setw(2) << i << " - " << last_value << ": "; } diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index f36f857973..78b3c57dda 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -130,9 +130,13 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ } // Let's set up attributes - for (int i = 0; i < 8; ++i) + for (size_t i = 0; i < 8; ++i) + { if (i < xfregs.numTexGen.numTexGens) + { out.Write("VARYOUT float3 uv%d_2;\n", i); + } + } out.Write("VARYOUT float4 clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) out.Write("VARYOUT float4 Normal_2;\n"); From abc3bddb548e6fa7406d99703260f8099c808d1b Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Wed, 13 Nov 2013 17:58:49 +1300 Subject: [PATCH 33/81] Revert "D3D: Reintroduce depencency on D3DX11 because it's the most straightforward way to bring back some broken features." This reverts commit a83c239765f8add99a360a29bfba2fdb408075c8. --- Source/Core/VideoBackends/D3D/Src/D3DBase.cpp | 60 ------------------- Source/Core/VideoBackends/D3D/Src/D3DBase.h | 25 +------- 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp b/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp index e9e678d841..5434354f37 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DBase.cpp @@ -17,13 +17,6 @@ D3DREFLECT PD3DReflect = NULL; pD3DCompile PD3DCompile = NULL; int d3dcompiler_dll_ref = 0; -HINSTANCE hD3DXDll = NULL; -D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory = NULL; -D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture = NULL; -D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA = NULL; -D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW = NULL; -int d3dx_dll_ref = 0; - CREATEDXGIFACTORY PCreateDXGIFactory = NULL; HINSTANCE hDXGIDll = NULL; int dxgi_dll_ref = 0; @@ -98,44 +91,6 @@ HRESULT LoadD3D() return S_OK; } -HRESULT LoadD3DX() -{ - if (d3dx_dll_ref++ > 0) return S_OK; - if (hD3DXDll) return S_OK; - - // try to load D3DX11 first to check whether we have proper runtime support - // try to use the dll the backend was compiled against first - don't bother about debug runtimes - hD3DXDll = LoadLibraryA(D3DX11_DLL_A); - if (!hD3DXDll) - { - // if that fails, use the dll which should be available in every SDK which officially supports DX11. - hD3DXDll = LoadLibraryA("d3dx11_42.dll"); - if (!hD3DXDll) - { - MessageBoxA(NULL, "Failed to load d3dx11_42.dll, update your DX11 runtime, please", "Critical error", MB_OK | MB_ICONERROR); - return E_FAIL; - } - else - { - NOTICE_LOG(VIDEO, "Successfully loaded d3dx11_42.dll. If you're having trouble, try updating your DX runtime first."); - } - } - - PD3DX11CompileFromMemory = (D3DX11COMPILEFROMMEMORYTYPE)GetProcAddress(hD3DXDll, "D3DX11CompileFromMemory"); - if (PD3DX11CompileFromMemory == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11CompileFromMemory!", "Critical error", MB_OK | MB_ICONERROR); - - PD3DX11FilterTexture = (D3DX11FILTERTEXTURETYPE)GetProcAddress(hD3DXDll, "D3DX11FilterTexture"); - if (PD3DX11FilterTexture == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11FilterTexture!", "Critical error", MB_OK | MB_ICONERROR); - - PD3DX11SaveTextureToFileA = (D3DX11SAVETEXTURETOFILEATYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileA"); - if (PD3DX11SaveTextureToFileA == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileA!", "Critical error", MB_OK | MB_ICONERROR); - - PD3DX11SaveTextureToFileW = (D3DX11SAVETEXTURETOFILEWTYPE)GetProcAddress(hD3DXDll, "D3DX11SaveTextureToFileW"); - if (PD3DX11SaveTextureToFileW == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3DX11SaveTextureToFileW!", "Critical error", MB_OK | MB_ICONERROR); - - return S_OK; -} - HRESULT LoadD3DCompiler() { if (d3dcompiler_dll_ref++ > 0) return S_OK; @@ -177,18 +132,6 @@ void UnloadDXGI() PCreateDXGIFactory = NULL; } -void UnloadD3DX() -{ - if (!d3dx_dll_ref) return; - if (--d3dx_dll_ref != 0) return; - - if (hD3DXDll) FreeLibrary(hD3DXDll); - hD3DXDll = NULL; - PD3DX11FilterTexture = NULL; - PD3DX11SaveTextureToFileA = NULL; - PD3DX11SaveTextureToFileW = NULL; -} - void UnloadD3D() { if (!d3d_dll_ref) return; @@ -272,13 +215,11 @@ HRESULT Create(HWND wnd) hr = LoadDXGI(); if (SUCCEEDED(hr)) hr = LoadD3D(); - if (SUCCEEDED(hr)) hr = LoadD3DX(); if (SUCCEEDED(hr)) hr = LoadD3DCompiler(); if (FAILED(hr)) { UnloadDXGI(); UnloadD3D(); - UnloadD3DX(); UnloadD3DCompiler(); return hr; } @@ -420,7 +361,6 @@ void Close() // unload DLLs UnloadD3D(); - UnloadD3DX(); UnloadDXGI(); } diff --git a/Source/Core/VideoBackends/D3D/Src/D3DBase.h b/Source/Core/VideoBackends/D3D/Src/D3DBase.h index 6e06de6e90..7f26cbd3cc 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DBase.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include #include #include "Common.h" #include @@ -25,11 +25,9 @@ namespace D3D HRESULT LoadDXGI(); HRESULT LoadD3D(); -HRESULT LoadD3DX(); HRESULT LoadD3DCompiler(); void UnloadDXGI(); void UnloadD3D(); -void UnloadD3DX(); void UnloadD3DCompiler(); D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter); @@ -74,27 +72,6 @@ void SetDebugObjectName(T resource, const char* name) } // namespace D3D -// Used to not require the SDK and runtime versions to match: -// Linking with d3dx11.lib makes the most recent d3dx11_xx.dll of the -// compiler's SDK a requirement, but this backend works with DX11 runtimes -// back to August 2009 even if the backend was built with June 2010. -// Add any d3dx11 functions which you want to use here and load them in Create() -typedef HRESULT(WINAPI* D3DX11COMPILEFROMMEMORYTYPE)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO*, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump*, ID3D10Blob**, ID3D10Blob**, HRESULT*); -typedef HRESULT(WINAPI* D3DX11FILTERTEXTURETYPE)(ID3D11DeviceContext*, ID3D11Resource*, UINT, UINT); -typedef HRESULT(WINAPI* D3DX11SAVETEXTURETOFILEATYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCSTR); -typedef HRESULT(WINAPI* D3DX11SAVETEXTURETOFILEWTYPE)(ID3D11DeviceContext*, ID3D11Resource*, D3DX11_IMAGE_FILE_FORMAT, LPCWSTR); - -extern D3DX11COMPILEFROMMEMORYTYPE PD3DX11CompileFromMemory; -extern D3DX11FILTERTEXTURETYPE PD3DX11FilterTexture; -extern D3DX11SAVETEXTURETOFILEATYPE PD3DX11SaveTextureToFileA; -extern D3DX11SAVETEXTURETOFILEWTYPE PD3DX11SaveTextureToFileW; - -#ifdef UNICODE -#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileW -#else -#define PD3DX11SaveTextureToFile PD3DX11SaveTextureToFileA -#endif - typedef HRESULT (WINAPI *CREATEDXGIFACTORY)(REFIID, void**); extern CREATEDXGIFACTORY PCreateDXGIFactory; typedef HRESULT (WINAPI *D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); From 7b53574b68be91e29b57939c003809855fff6c5c Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 14 Nov 2013 00:48:02 +1300 Subject: [PATCH 34/81] Support texture and screenshot dumping using WIC, no XP support. --- .../Core/VideoBackends/D3D/Src/D3DTexture.cpp | 126 ++++++++++++++++++ .../Core/VideoBackends/D3D/Src/D3DTexture.h | 1 + Source/Core/VideoBackends/D3D/Src/Render.cpp | 15 +-- .../VideoBackends/D3D/Src/TextureCache.cpp | 28 +++- 4 files changed, 157 insertions(+), 13 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp index abf34b3cca..94d778d17b 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp @@ -5,12 +5,138 @@ #include "D3DBase.h" #include "D3DTexture.h" +#include +#include +#include +#pragma comment(lib, "WindowsCodecs.lib") + namespace DX11 { namespace D3D { +HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, LPCWSTR wzFilename, int width, int height, bool saveAlpha) +{ + IWICImagingFactory *piFactory = NULL; + IWICBitmapEncoder *piEncoder = NULL; + IWICBitmapFrameEncode *piBitmapFrame = NULL; + IPropertyBag2 *pPropertybag = NULL; + + IWICStream *piStream = NULL; + + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory, + NULL, + CLSCTX_INPROC_SERVER, + IID_IWICImagingFactory, + (LPVOID*)&piFactory); + + if (SUCCEEDED(hr)) + { + hr = piFactory->CreateStream(&piStream); + } + + if (SUCCEEDED(hr)) + { + hr = piStream->InitializeFromFilename(wzFilename, GENERIC_WRITE); + } + + if (SUCCEEDED(hr)) + { + hr = piFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &piEncoder); + } + + if (SUCCEEDED(hr)) + { + hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache); + } + + if (SUCCEEDED(hr)) + { + hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag); + } + + if (SUCCEEDED(hr)) + { + if (SUCCEEDED(hr)) + { + hr = piBitmapFrame->Initialize(pPropertybag); + } + } + + if (SUCCEEDED(hr)) + { + hr = piBitmapFrame->SetSize(width, height); + } + + WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA; + if (SUCCEEDED(hr)) + { + hr = piBitmapFrame->SetPixelFormat(&formatGUID); + } + + if (SUCCEEDED(hr)) + { + // We're expecting to write out 32bppBGRA. Fail if the encoder cannot do it. + hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat32bppBGRA) ? S_OK : E_FAIL; + } + + if (SUCCEEDED(hr)) + { + if (map.pData != NULL) + { + for (int y = 0; y < height; ++y) + { + u8* ptr = (u8*)map.pData + y * map.RowPitch; + for (unsigned int x = 0; x < map.RowPitch/4; ++x) + { + u8 r = ptr[0]; + u8 g = ptr[1]; + u8 b = ptr[2]; + ptr[0] = b; + ptr[1] = g; + ptr[2] = r; + if (!saveAlpha) + ptr[3] = 0xff; + + + ptr += 4; + } + } + hr = piBitmapFrame->WritePixels(height, map.RowPitch, height * map.RowPitch, (BYTE*)map.pData); + } + else + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + hr = piBitmapFrame->Commit(); + } + + if (SUCCEEDED(hr)) + { + hr = piEncoder->Commit(); + } + + if (piFactory) + piFactory->Release(); + + if (piBitmapFrame) + piBitmapFrame->Release(); + + if (piEncoder) + piEncoder->Release(); + + if (piStream) + piStream->Release(); + + return hr; +} + void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) { if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h index 5c2aa57f4a..d047d3f249 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h @@ -11,6 +11,7 @@ namespace DX11 namespace D3D { + HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, LPCWSTR wzFilename, int width, int height, bool saveAlpha = true); void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); } diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index c7ad9e2bda..33528359c5 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -690,22 +690,13 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D11_BOX box = CD3D11_BOX(rc.left, rc.top, 0, rc.right, rc.bottom, 1); D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex(), 0, &box); - // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - for (auto y = 0; y < rc.GetHeight(); ++y) - { - u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; - for (auto x = 0; x < rc.GetWidth(); ++x) - { - *ptr = 0xFF; - ptr += 4; - } - } - D3D::context->Unmap(s_screenshot_texture, 0); // ready to be saved - HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str()); + HRESULT hr = D3D::TextureToPng(map, UTF8ToUTF16(filename.c_str()).c_str(), rc.GetWidth(), rc.GetHeight(), false); + D3D::context->Unmap(s_screenshot_texture, 0); + if (SUCCEEDED(hr)) { OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index d3c536c4a6..9d1e28b9b0 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -42,7 +42,33 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) warn_once = false; return false; } - return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); + + ID3D11Texture2D* pNewTexture = NULL; + ID3D11Texture2D* pSurface = texture->GetTex(); + D3D11_TEXTURE2D_DESC desc; + pSurface->GetDesc(&desc); + + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Usage = D3D11_USAGE_STAGING; + + HRESULT hr = D3D::device->CreateTexture2D(&desc, NULL, &pNewTexture); + + if (SUCCEEDED(hr) && pNewTexture) + { + D3D::context->CopyResource(pNewTexture, pSurface); + + D3D11_MAPPED_SUBRESOURCE map; + HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); + if (SUCCEEDED(hr)) + { + hr = D3D::TextureToPng(map, UTF8ToUTF16(filename).c_str(), desc.Width, desc.Height); + D3D::context->Unmap(pNewTexture, 0); + } + SAFE_RELEASE(pNewTexture); + } + + return SUCCEEDED(hr); } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, From 652ef24a2efd73fca5e316e2e54b31c4f96e62c8 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 13 Nov 2013 11:43:54 -0600 Subject: [PATCH 35/81] Remove our two instances of auto_ptr and replace it with unique_ptr. auto_ptr has been deprecated. --- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 4 ++-- Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index 8ecc3a2902..6a8cb8d594 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -222,10 +222,10 @@ namespace JitILProfiler } } }; - std::auto_ptr finalizer; + std::unique_ptr finalizer; static void Init() { - finalizer = std::auto_ptr(new JitILProfilerFinalizer); + finalizer = std::unique_ptr(new JitILProfilerFinalizer); } static void Shutdown() { diff --git a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp index a8e37c92dd..3a4866f2f8 100644 --- a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp @@ -1224,7 +1224,7 @@ struct Writer virtual ~Writer() {} }; -static std::auto_ptr writer; +static std::unique_ptr writer; static const std::string opcodeNames[] = { "Nop", "LoadGReg", "LoadLink", "LoadCR", "LoadCarry", "LoadCTR", @@ -1276,7 +1276,7 @@ void IRBuilder::WriteToFile(u64 codeHash) { _assert_(sizeof(opcodeNames) / sizeof(opcodeNames[0]) == Int3 + 1); if (!writer.get()) { - writer = std::auto_ptr(new Writer); + writer = std::unique_ptr(new Writer); } FILE* const file = writer->file.GetHandle(); From 63a9dff3bb8c88cdc5b941db1f3813843c7a8564 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 13 Nov 2013 12:51:49 -0600 Subject: [PATCH 36/81] Windows requires memory to be included to use unique_ptr --- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index 6a8cb8d594..b15ffbacca 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include "Common.h" From ca5b3b4773d6cac757c6ac3eb2c0a50984b7353f Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 14 Nov 2013 18:10:39 +1300 Subject: [PATCH 37/81] atlbase not needed. Interim fix until I get png done. --- Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp index 94d778d17b..fed4c69ef3 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp @@ -5,7 +5,6 @@ #include "D3DBase.h" #include "D3DTexture.h" -#include #include #include #pragma comment(lib, "WindowsCodecs.lib") From 39a4d4329dd335cb46900e029bac7a7719a88a31 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Thu, 14 Nov 2013 02:19:15 -0500 Subject: [PATCH 38/81] more warning fixes --- .../Core/Core/Src/FifoPlayer/FifoDataFile.cpp | 4 +- .../Src/FifoPlayer/FifoPlaybackAnalyzer.cpp | 2 +- .../Core/Core/Src/FifoPlayer/FifoPlayer.cpp | 10 ++-- .../Core/Core/Src/FifoPlayer/FifoRecorder.cpp | 6 +-- Source/Core/Core/Src/HW/DVDInterface.cpp | 2 +- .../Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp | 2 +- Source/Core/Core/Src/HW/GCMemcard.cpp | 4 +- Source/Core/Core/Src/HW/GCPadEmu.cpp | 2 +- .../Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 4 +- .../Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 2 +- .../Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h | 4 +- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 10 ++-- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 8 ++- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 2 +- Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp | 6 ++- .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 2 +- Source/Core/Core/Src/NetPlayClient.cpp | 9 ++-- Source/Core/Core/Src/NetPlayServer.cpp | 6 ++- .../Src/PowerPC/JitCommon/JitBackpatch.cpp | 2 +- .../Core/Src/PowerPC/JitCommon/Jit_Util.cpp | 2 +- Source/Core/Core/Src/PowerPC/PPCTables.cpp | 2 +- Source/Core/Core/Src/State.cpp | 8 ++- .../Src/ControllerInterface/SDL/SDL.cpp | 52 ++++++++++--------- .../Core/VideoBackends/OGL/Src/RasterFont.cpp | 2 +- .../VideoCommon/Src/x64TextureDecoder.cpp | 2 +- 27 files changed, 89 insertions(+), 70 deletions(-) diff --git a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp index 118511af92..5e7e864ad0 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp @@ -86,7 +86,7 @@ bool FifoDataFile::Save(const char *filename) header.xfRegsSize = XF_REGS_SIZE; header.frameListOffset = frameListOffset; - header.frameCount = m_Frames.size(); + header.frameCount = (u32)m_Frames.size(); header.flags = m_Flags; @@ -111,7 +111,7 @@ bool FifoDataFile::Save(const char *filename) dstFrame.fifoStart = srcFrame.fifoStart; dstFrame.fifoEnd = srcFrame.fifoEnd; dstFrame.memoryUpdatesOffset = memoryUpdatesOffset; - dstFrame.numMemoryUpdates = srcFrame.memoryUpdates.size(); + dstFrame.numMemoryUpdates = (u32)srcFrame.memoryUpdates.size(); // Write frame info u64 frameOffset = frameListOffset + (i * sizeof(FileFrameInfo)); diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp index 1e606e52e4..e6adc14130 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp @@ -234,7 +234,7 @@ u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data) break; } - return data - dataStart; + return (u32)(data - dataStart); } void FifoPlaybackAnalyzer::StoreEfbCopyRegion() diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp index 0f65c6a966..8aaf962999 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp @@ -105,7 +105,9 @@ bool FifoPlayer::Play() u32 FifoPlayer::GetFrameObjectCount() { if (m_CurrentFrame < m_FrameInfo.size()) - return m_FrameInfo[m_CurrentFrame].objectStarts.size(); + { + return (u32)(m_FrameInfo[m_CurrentFrame].objectStarts.size()); + } return 0; } @@ -172,7 +174,7 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo m_FrameFifoSize = frame.fifoDataSize; // Determine start and end objects - u32 numObjects = info.objectStarts.size(); + u32 numObjects = (u32)(info.objectStarts.size()); u32 drawStart = std::min(numObjects, m_ObjectRangeStart); u32 drawEnd = std::min(numObjects - 1, m_ObjectRangeEnd); @@ -181,7 +183,9 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo // Skip memory updates during frame if true if (m_EarlyMemoryUpdates) - memoryUpdate = frame.memoryUpdates.size(); + { + memoryUpdate = (u32)(frame.memoryUpdates.size()); + } if (numObjects > 0) { diff --git a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp index fb98205d27..e58b34658a 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp @@ -83,9 +83,9 @@ void FifoRecorder::WriteGPCommand(u8 *data, u32 size) if (m_FrameEnded && m_FifoData.size() > 0) { size_t dataSize = m_FifoData.size(); - m_CurrentFrame.fifoDataSize = dataSize; + m_CurrentFrame.fifoDataSize = (u32)dataSize; m_CurrentFrame.fifoData = new u8[dataSize]; - memcpy(m_CurrentFrame.fifoData, &m_FifoData[0], dataSize); + memcpy(m_CurrentFrame.fifoData, m_FifoData.data(), dataSize); sMutex.lock(); @@ -129,7 +129,7 @@ void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) // Record memory update MemoryUpdate memUpdate; memUpdate.address = address; - memUpdate.fifoPosition = m_FifoData.size(); + memUpdate.fifoPosition = (u32)(m_FifoData.size()); memUpdate.size = size; memUpdate.type = type; memUpdate.data = new u8[size]; diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp index fc326fec90..d77fa4877f 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.cpp +++ b/Source/Core/Core/Src/HW/DVDInterface.cpp @@ -325,7 +325,7 @@ void ChangeDisc(const char* _newFileName) { Movie::g_bDiscChange = true; std::string fileName = _newFileName; - int sizeofpath = fileName.find_last_of("/\\") + 1; + auto sizeofpath = fileName.find_last_of("/\\") + 1; if (fileName.substr(sizeofpath).length() > 40) { PanicAlert("Saving iso filename to .dtm failed; max file name length is 40 characters."); diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp index 1cdeb1fbcf..2d1fb56c2a 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp @@ -191,7 +191,7 @@ void CEXIMemoryCard::CmdDone() void CEXIMemoryCard::CmdDoneLater(u64 cycles) { CoreTiming::RemoveEvent(et_cmd_done); - CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index); + CoreTiming::ScheduleEvent((int)cycles, et_cmd_done, (u64)card_index); } void CEXIMemoryCard::SetCS(int cs) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index adaa7a1858..2421e572ae 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -40,7 +40,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) PanicAlertT("File has the extension \"%s\"\nvalid extensions are (.raw/.gcp)", fileType.c_str()); return; } - u32 size = mcdFile.GetSize(); + auto size = mcdFile.GetSize(); if (size < MC_FST_BLOCKS*BLOCK_SIZE) { PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, size); @@ -52,7 +52,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) return; } - m_sizeMb = (size/BLOCK_SIZE) / MBIT_TO_BLOCKS; + m_sizeMb = (u16)((size/BLOCK_SIZE) / MBIT_TO_BLOCKS); switch (m_sizeMb) { case MemCard59Mb: diff --git a/Source/Core/Core/Src/HW/GCPadEmu.cpp b/Source/Core/Core/Src/HW/GCPadEmu.cpp index 28c33ae926..80fc48b9db 100644 --- a/Source/Core/Core/Src/HW/GCPadEmu.cpp +++ b/Source/Core/Core/Src/HW/GCPadEmu.cpp @@ -209,5 +209,5 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface) bool GCPad::GetMicButton() const { - return m_buttons->controls.back()->control_ref->State(); + return (0 != m_buttons->controls.back()->control_ref->State()); } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 235d5cb7f1..2014f0b1f4 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -32,7 +32,7 @@ namespace WiimoteEmu { -void Spy(Wiimote* wm_, const void* data_, int size_) +void Spy(Wiimote* wm_, const void* data_, size_t size_) { #if 0 // enable log @@ -1275,7 +1275,7 @@ void Wiimote::DoState(PointerWrap& p) else { std::queue tmp_queue(m_read_requests); - size = m_read_requests.size(); + size = (u32)(m_read_requests.size()); p.Do(size); while (!tmp_queue.empty()) { diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 28f60940c4..4c80b1adda 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -765,7 +765,7 @@ void Wiimote::Update() if (-1 == rptf_size) { std::copy(rpt.begin(), rpt.end(), data); - rptf_size = rpt.size(); + rptf_size = (s8)(rpt.size()); } } } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 9ed58f8b48..f2afda4aa3 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -96,7 +96,7 @@ inline double trim(double a) class Wiimote : public ControllerEmu { friend class WiimoteReal::Wiimote; -friend void Spy(Wiimote* wm_, const void* data_, int size_); +friend void Spy(Wiimote* wm_, const void* data_, size_t size_); public: enum @@ -245,7 +245,7 @@ private: } m_reg_speaker; }; -void Spy(Wiimote* wm_, const void* data_, int size_); +void Spy(Wiimote* wm_, const void* data_, size_t size_); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 2f1efd0228..13728a9d72 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -140,7 +140,7 @@ namespace WiimoteReal { -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len); +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len); int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index); void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read); @@ -247,7 +247,7 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot // SLEEP(2000); } -int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts) +int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, size_t size, int attempts) { OVERLAPPED hid_overlap_write = OVERLAPPED(); hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL); @@ -641,7 +641,7 @@ int Wiimote::IORead(u8* buf) } -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len) +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len) { WiimoteEmu::Spy(NULL, buf, len); @@ -663,7 +663,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac } case MSBT_STACK_MS: { - auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); + auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, (ULONG)(len - 1)); //FlushFileBuffers(dev_handle); if (!result) @@ -715,7 +715,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index e5fff5b3f1..dea6f7fce6 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -239,7 +239,9 @@ bool Wiimote::Write() IOWrite(rpt.data(), rpt.size()); if (is_speaker_data) + { m_last_audio_report.Update(); + } m_write_reports.Pop(); return true; @@ -293,8 +295,10 @@ void Wiimote::Update() // Send the report if (!rpt.empty() && m_channel > 0) - Core::Callback_WiimoteInterruptChannel(index, m_channel, - rpt.data(), rpt.size()); + { + Core::Callback_WiimoteInterruptChannel(index, m_channel, + rpt.data(), (u32)rpt.size()); + } } void Wiimote::Prepare(int _index) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index c4807ed95f..bc953102a9 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -106,7 +106,7 @@ private: void WriteReport(Report rpt); int IORead(u8* buf); - int IOWrite(u8 const* buf, int len); + int IOWrite(u8 const* buf, size_t len); void IOWakeup(); void ThreadFunc(); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 22115e4900..3bd37ba373 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -83,7 +83,7 @@ static u64 last_reply_time; void EnqueReplyCallback(u64 userdata, int) { std::lock_guard lk(s_reply_queue); - reply_queue.push_back(userdata); + reply_queue.push_back((u32)userdata); } void Init() @@ -546,7 +546,9 @@ void ExecuteCommand(u32 _Address) const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks(); if (ticks_til_last_reply > 0) - reply_delay = ticks_til_last_reply; + { + reply_delay = (int)ticks_til_last_reply; + } last_reply_time = CoreTiming::GetTicks() + reply_delay; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 58ff0917ed..ea4230f485 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -133,7 +133,7 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p) p.Do(m_AccessIdentID); p.Do(m_TitleIDs); - u32 Count = m_ContentAccessMap.size(); + u32 Count = (u32)(m_ContentAccessMap.size()); p.Do(Count); u32 CFD, Position; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index edbcc0967a..4de7af8e06 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -571,7 +571,7 @@ void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p) } else { - u32 size = entry.size; + u32 size = (u32)entry.size; p.Do(size); File::IOFile handle(entry.physicalName, "rb"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 990a9e6a7d..aa7d84d661 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -866,7 +866,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRoleChange(bdaddr_t _bd, bool bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets() { - SQueuedEvent Event(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size(), 0); + SQueuedEvent Event((u32)(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + (sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size())), 0); INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventNumberOfCompletedPackets"); diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index 7e71584c35..6ca13b4836 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -445,10 +445,11 @@ void NetPlayClient::SendWiimoteState(const PadMapping in_game_pad, const NetWiim sf::Packet spac; spac << (MessageId)NP_MSG_WIIMOTE_DATA; spac << in_game_pad; - u8 size = nw.size(); - spac << size; - for (unsigned int i = 0; i < size; ++i) - spac << nw.data()[i]; + spac << (u8)nw.size(); + for (auto it : nw) + { + spac << it; + } std::lock_guard lks(m_crit.send); m_socket.Send(spac); diff --git a/Source/Core/Core/Src/NetPlayServer.cpp b/Source/Core/Core/Src/NetPlayServer.cpp index 0049719a05..296fcd29a4 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -153,7 +153,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) rpac >> player.name; // give new client first available id - player.pid = m_players.size() + 1; + player.pid = (PlayerId)(m_players.size() + 1); // try to automatically assign new user a pad for (unsigned int m = 0; m < 4; ++m) @@ -435,12 +435,14 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) case NP_MSG_PONG : { - const u32 ping = m_ping_timer.GetTimeElapsed(); + const u32 ping = (u32)m_ping_timer.GetTimeElapsed(); u32 ping_key = 0; packet >> ping_key; if (m_ping_key == ping_key) + { player.ping = ping; + } sf::Packet spac; spac << (MessageId)NP_MSG_PLAYER_PING_DATA; diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index dd481da9bc..b7cc031c99 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -234,7 +234,7 @@ const u8 *Jitx86Base::BackPatch(u8 *codePtr, u32 emAddress, void *ctx_void) XEmitter emitter(start); const u8 *trampoline = trampolines.GetWriteTrampoline(info, registersInUse); emitter.CALL((void *)trampoline); - emitter.NOP(codePtr + info.instructionSize - emitter.GetCodePtr()); + emitter.NOP((int)(codePtr + info.instructionSize - emitter.GetCodePtr())); return start; } #else diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index 00e24e7a20..5c4a712024 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -323,7 +323,7 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write TEST(32, R(reg_addr), Imm32(mem_mask)); FixupBranch fast = J_CC(CC_Z, true); - bool noProlog = flags & SAFE_LOADSTORE_NO_PROLOG; + bool noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG)); bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); ABI_PushRegistersAndAdjustStack(registersInUse, noProlog); switch (accessSize) diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index d901f639e5..625e416299 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -192,7 +192,7 @@ void PrintInstructionRunCounts() { op_inf x; x.name = m_allInstructions[i]->opname; - x.count = m_allInstructions[i]->runCount; + x.count = (int)(m_allInstructions[i]->runCount); temp.push_back(x); } std::sort(temp.begin(), temp.end()); diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 99a1236123..f33003fdb1 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -247,7 +247,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) // Setting up the header StateHeader header; memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6); - header.size = g_use_compression ? buffer_size : 0; + header.size = g_use_compression ? (u32)buffer_size : 0; header.time = Common::Timer::GetDoubleTime(); f.WriteArray(&header, 1); @@ -261,9 +261,13 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) lzo_uint out_len = 0; if ((i + IN_LEN) >= buffer_size) - cur_len = buffer_size - i; + { + cur_len = (lzo_uint32)(buffer_size - i); + } else + { cur_len = IN_LEN; + } if (lzo1x_1_compress(buffer_data + i, cur_len, out, &out_len, wrkmem) != LZO_E_OK) PanicAlertT("Internal LZO Error - compression failed"); diff --git a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp index bcd3586dc6..24e0d0de58 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp @@ -154,12 +154,13 @@ Joystick::~Joystick() { // stop/destroy all effects SDL_HapticStopAll(m_haptic); - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) - if (i->id != -1) - SDL_HapticDestroyEffect(m_haptic, i->id); + for (auto &i : m_state_out) + { + if (i.id != -1) + { + SDL_HapticDestroyEffect(m_haptic, i.id); + } + } // close haptic first SDL_HapticClose(m_haptic); } @@ -210,7 +211,7 @@ void Joystick::ConstantEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.constant.level; - m_effect.effect.constant.level = state * 0x7FFF; + m_effect.effect.constant.level = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.constant.level) m_effect.changed = true; } @@ -228,7 +229,7 @@ void Joystick::RampEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.ramp.start; - m_effect.effect.ramp.start = state * 0x7FFF; + m_effect.effect.ramp.start = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.ramp.start) m_effect.changed = true; } @@ -247,7 +248,7 @@ void Joystick::SineEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 500; @@ -293,7 +294,7 @@ void Joystick::TriangleEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 100; @@ -313,34 +314,35 @@ bool Joystick::UpdateInput() bool Joystick::UpdateOutput() { #ifdef USE_SDL_HAPTIC - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) + for (auto &i : m_state_out) { - if (i->changed) // if SetState was called on this output + if (i.changed) // if SetState was called on this output { - if (-1 == i->id) // effect isn't currently uploaded + if (-1 == i.id) // effect isn't currently uploaded { - if (i->effect.type) // if outputstate is >0 this would be true - if ((i->id = SDL_HapticNewEffect( m_haptic, &i->effect )) > -1) // upload the effect - SDL_HapticRunEffect(m_haptic, i->id, 1); // run the effect + if (i.effect.type) // if outputstate is >0 this would be true + { + if ((i.id = SDL_HapticNewEffect(m_haptic, &i.effect)) > -1) // upload the effect + { + SDL_HapticRunEffect(m_haptic, i.id, 1); // run the effect + } + } } else // effect is already uploaded { - if (i->effect.type) // if ouputstate >0 + if (i.effect.type) // if ouputstate >0 { - SDL_HapticUpdateEffect(m_haptic, i->id, &i->effect); // update the effect + SDL_HapticUpdateEffect(m_haptic, i.id, &i.effect); // update the effect } else { - SDL_HapticStopEffect(m_haptic, i->id); // else, stop and remove the effect - SDL_HapticDestroyEffect(m_haptic, i->id); - i->id = -1; // mark it as not uploaded + SDL_HapticStopEffect(m_haptic, i.id); // else, stop and remove the effect + SDL_HapticDestroyEffect(m_haptic, i.id); + i.id = -1; // mark it as not uploaded } } - i->changed = false; + i.changed = false; } } #endif diff --git a/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp b/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp index c1817f3eeb..42b8963784 100644 --- a/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp +++ b/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp @@ -144,7 +144,7 @@ RasterFont::RasterFont() for(u32 y=0; y Date: Thu, 14 Nov 2013 02:27:53 -0500 Subject: [PATCH 39/81] build fix --- Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 2 +- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index ada6237756..57034ff09a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -72,7 +72,7 @@ int Wiimote::IORead(u8* buf) return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 860a9a3d57..0f4fe5e730 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -263,9 +263,9 @@ int Wiimote::IORead(u8* buf) return r; } -int Wiimote::IOWrite(u8 const* buf, int len) +int Wiimote::IOWrite(u8 const* buf, size_t len) { - return write(int_sock, buf, len); + return write(int_sock, buf, (int)len); } }; // WiimoteReal From 7e9b970240ec10d416226666aa761131d459ee0f Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 14 Nov 2013 21:02:49 +1300 Subject: [PATCH 40/81] Use libpng for saving images. TODO: Needs threading done similiar to OGL backend. Fixes issue 6779. --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 6 + .../Core/VideoBackends/D3D/Src/D3DTexture.cpp | 177 +++++++----------- .../Core/VideoBackends/D3D/Src/D3DTexture.h | 2 +- Source/Core/VideoBackends/D3D/Src/Render.cpp | 2 +- .../VideoBackends/D3D/Src/TextureCache.cpp | 2 +- Source/VSProps/Base.props | 1 + 6 files changed, 78 insertions(+), 112 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index a4177f6909..15d968b97f 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -93,9 +93,15 @@ + + {4c9f135b-a85e-430c-bad4-4c67ef5fc12c} + {1c8436c9-dbaf-42be-83bc-cf3ec9175abe} + + {ff213b23-2c26-4214-9f88-85271e557e87} + {3de9ee35-3e91-4f27-a014-2866ad8c3fe3} diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp index fed4c69ef3..2b632b5466 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp @@ -5,9 +5,7 @@ #include "D3DBase.h" #include "D3DTexture.h" -#include -#include -#pragma comment(lib, "WindowsCodecs.lib") +#include "png.h" namespace DX11 { @@ -15,125 +13,86 @@ namespace DX11 namespace D3D { -HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, LPCWSTR wzFilename, int width, int height, bool saveAlpha) +bool TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, const char* filename, int width, int height, bool saveAlpha) { - IWICImagingFactory *piFactory = NULL; - IWICBitmapEncoder *piEncoder = NULL; - IWICBitmapFrameEncode *piBitmapFrame = NULL; - IPropertyBag2 *pPropertybag = NULL; - - IWICStream *piStream = NULL; - - HRESULT hr = CoCreateInstance( - CLSID_WICImagingFactory, - NULL, - CLSCTX_INPROC_SERVER, - IID_IWICImagingFactory, - (LPVOID*)&piFactory); - - if (SUCCEEDED(hr)) + bool success = false; + if (map.pData != NULL) { - hr = piFactory->CreateStream(&piStream); - } + FILE *fp = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; - if (SUCCEEDED(hr)) - { - hr = piStream->InitializeFromFilename(wzFilename, GENERIC_WRITE); - } - - if (SUCCEEDED(hr)) - { - hr = piFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &piEncoder); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag); - } - - if (SUCCEEDED(hr)) - { - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->Initialize(pPropertybag); + // Open file for writing (binary mode) + fp = fopen(filename, "wb"); + if (fp == NULL) { + PanicAlert("Could not open file %s for writing\n", filename); + goto finalise; } - } - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->SetSize(width, height); - } + // Initialize write structure + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + PanicAlert("Could not allocate write struct\n"); + goto finalise; + + } - WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA; - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->SetPixelFormat(&formatGUID); - } + // Initialize info structure + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + PanicAlert("Could not allocate info struct\n"); + goto finalise; + } - if (SUCCEEDED(hr)) - { - // We're expecting to write out 32bppBGRA. Fail if the encoder cannot do it. - hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat32bppBGRA) ? S_OK : E_FAIL; - } + // Setup Exception handling + if (setjmp(png_jmpbuf(png_ptr))) { + PanicAlert("Error during png creation\n"); + goto finalise; + } - if (SUCCEEDED(hr)) - { - if (map.pData != NULL) + png_init_io(png_ptr, fp); + + // Write header (8 bit colour depth) + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + char title[] = "Dolphin Screenshot"; + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.key = "Title"; + title_text.text = title; + png_set_text(png_ptr, info_ptr, &title_text, 1); + + png_write_info(png_ptr, info_ptr); + + // Write image data + for (auto y = 0; y < height; ++y) { - for (int y = 0; y < height; ++y) + u8* row_ptr = (u8*)map.pData + y * map.RowPitch; + u8* ptr = row_ptr; + for (UINT x = 0; x < map.RowPitch / 4; ++x) { - u8* ptr = (u8*)map.pData + y * map.RowPitch; - for (unsigned int x = 0; x < map.RowPitch/4; ++x) - { - u8 r = ptr[0]; - u8 g = ptr[1]; - u8 b = ptr[2]; - ptr[0] = b; - ptr[1] = g; - ptr[2] = r; - if (!saveAlpha) - ptr[3] = 0xff; - - - ptr += 4; - } + if (!saveAlpha) + ptr[3] = 0xff; + ptr += 4; } - hr = piBitmapFrame->WritePixels(height, map.RowPitch, height * map.RowPitch, (BYTE*)map.pData); - } - else - { - hr = E_OUTOFMEMORY; + png_write_row(png_ptr, row_ptr); } + + // End write + png_write_end(png_ptr, NULL); + + success = true; + + finalise: + + if (fp != NULL) fclose(fp); + if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + } - - if (SUCCEEDED(hr)) - { - hr = piBitmapFrame->Commit(); - } - - if (SUCCEEDED(hr)) - { - hr = piEncoder->Commit(); - } - - if (piFactory) - piFactory->Release(); - - if (piBitmapFrame) - piBitmapFrame->Release(); - - if (piEncoder) - piEncoder->Release(); - - if (piStream) - piStream->Release(); - - return hr; + return false; } void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h index d047d3f249..71583d04ea 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h @@ -11,7 +11,7 @@ namespace DX11 namespace D3D { - HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, LPCWSTR wzFilename, int width, int height, bool saveAlpha = true); + bool TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, const char* filename, int width, int height, bool saveAlpha = true); void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); } diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 33528359c5..e2e26997c7 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -694,7 +694,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); // ready to be saved - HRESULT hr = D3D::TextureToPng(map, UTF8ToUTF16(filename.c_str()).c_str(), rc.GetWidth(), rc.GetHeight(), false); + HRESULT hr = D3D::TextureToPng(map, filename.c_str(), rc.GetWidth(), rc.GetHeight(), false); D3D::context->Unmap(s_screenshot_texture, 0); if (SUCCEEDED(hr)) diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index 9d1e28b9b0..0c6e759de5 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -62,7 +62,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); if (SUCCEEDED(hr)) { - hr = D3D::TextureToPng(map, UTF8ToUTF16(filename).c_str(), desc.Width, desc.Height); + hr = D3D::TextureToPng(map, filename, desc.Width, desc.Height); D3D::context->Unmap(pNewTexture, 0); } SAFE_RELEASE(pNewTexture); diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 2ee5bd8e8e..1b40800891 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -44,6 +44,7 @@ $(ExternalsDir)Bochs_disasm;%(AdditionalIncludeDirectories) $(ExternalsDir)CLRun\include;%(AdditionalIncludeDirectories) $(ExternalsDir)GLew\include;%(AdditionalIncludeDirectories) + $(ExternalsDir)libpng;%(AdditionalIncludeDirectories) $(ExternalsDir)libusbx\libusb;%(AdditionalIncludeDirectories) $(ExternalsDir)LZO;%(AdditionalIncludeDirectories) $(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories) From 0fced651a5d550eae28991de39d0f3724958026f Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Thu, 14 Nov 2013 03:11:40 -0500 Subject: [PATCH 41/81] More warning fixes, OSX build fix. --- .../Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h | 60 +++++++++++-------- Source/Core/Core/Src/HW/GCPadEmu.cpp | 2 +- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 4 +- Source/Core/VideoBackends/OGL/Src/Render.cpp | 28 +++++---- .../VideoBackends/OGL/Src/StreamBuffer.cpp | 18 ++++-- .../VideoBackends/OGL/Src/VertexManager.cpp | 16 ++--- 6 files changed, 73 insertions(+), 55 deletions(-) diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h index 6819b05818..fce6cdf6a2 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h @@ -469,36 +469,42 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl // Mix LRS, AUXA and AUXB depending on mixer_control // TODO: Handle DPL2 on AUXB. - if (mctrl & MIX_L) - MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP); - if (mctrl & MIX_R) - MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP); - if (mctrl & MIX_S) - MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP); +#define MIX_ON(C) (0 != (mctrl & MIX_##C)) +#define RAMP_ON(C) (0 != (mctrl & MIX_##C##_RAMP)) - if (mctrl & MIX_AUXA_L) - MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP); - if (mctrl & MIX_AUXA_R) - MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP); - if (mctrl & MIX_AUXA_S) - MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP); + if (MIX_ON(L)) + MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, RAMP_ON(L)); + if (MIX_ON(R)) + MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, RAMP_ON(R)); + if (MIX_ON(S)) + MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, RAMP_ON(S)); - if (mctrl & MIX_AUXB_L) - MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP); - if (mctrl & MIX_AUXB_R) - MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP); - if (mctrl & MIX_AUXB_S) - MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP); + if (MIX_ON(AUXA_L)) + MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, RAMP_ON(AUXA_L)); + if (MIX_ON(AUXA_R)) + MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, RAMP_ON(AUXA_R)); + if (MIX_ON(AUXA_S)) + MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, RAMP_ON(AUXA_S)); + + if (MIX_ON(AUXB_L)) + MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, RAMP_ON(AUXB_L)); + if (MIX_ON(AUXB_R)) + MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, RAMP_ON(AUXB_R)); + if (MIX_ON(AUXB_S)) + MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, RAMP_ON(AUXB_S)); #ifdef AX_WII - if (mctrl & MIX_AUXC_L) - MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP); - if (mctrl & MIX_AUXC_R) - MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP); - if (mctrl & MIX_AUXC_S) - MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP); + if (MIX_ON(AUXC_L)) + MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, RAMP_ON(AUXC_L)); + if (MIX_ON(AUXC_R)) + MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, RAMP_ON(AUXC_R)); + if (MIX_ON(AUXC_S)) + MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, RAMP_ON(AUXC_S)); #endif +#undef MIX_ON +#undef RAMP_ON + // Optionally, phase shift left or right channel to simulate 3D sound. if (pb.initial_time_delay.on) { @@ -524,8 +530,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl pb.remote_src.cur_addr_frac = curr_pos & 0xFFFF; // Mix to main[0-3] and aux[0-3] -#define WMCHAN_MIX_ON(n) ((pb.remote_mixer_control >> (2 * n)) & 3) -#define WMCHAN_MIX_RAMP(n) ((pb.remote_mixer_control >> (2 * n)) & 2) +#define WMCHAN_MIX_ON(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 3)) +#define WMCHAN_MIX_RAMP(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 2)) if (WMCHAN_MIX_ON(0)) MixAdd(buffers.wm_main0, wm_samples, wm_count, &pb.remote_mixer.main0, &pb.remote_dpop.main0, WMCHAN_MIX_RAMP(0)); @@ -544,6 +550,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl if (WMCHAN_MIX_ON(7)) MixAdd(buffers.wm_aux3, wm_samples, wm_count, &pb.remote_mixer.aux3, &pb.remote_dpop.aux3, WMCHAN_MIX_RAMP(7)); } +#undef WMCHAN_MIX_RAMP +#undef WMCHAN_MIX_ON #endif } diff --git a/Source/Core/Core/Src/HW/GCPadEmu.cpp b/Source/Core/Core/Src/HW/GCPadEmu.cpp index 80fc48b9db..fa219c369a 100644 --- a/Source/Core/Core/Src/HW/GCPadEmu.cpp +++ b/Source/Core/Core/Src/HW/GCPadEmu.cpp @@ -209,5 +209,5 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface) bool GCPad::GetMicButton() const { - return (0 != m_buttons->controls.back()->control_ref->State()); + return (0.0f != m_buttons->controls.back()->control_ref->State()); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index f59cffee2c..c094c97c13 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -310,14 +310,14 @@ int Wiimote::IORead(unsigned char *buf) return inputlen; } -int Wiimote::IOWrite(const unsigned char *buf, int len) +int Wiimote::IOWrite(const unsigned char *buf, size_t len) { IOReturn ret; if (!IsConnected()) return 0; - ret = [ichan writeAsync: const_cast((void *)buf) length: len refcon: nil]; + ret = [ichan writeAsync: const_cast((void *)buf) length: (int)len refcon: nil]; if (ret == kIOReturnSuccess) return len; diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 63f8a3db49..020fac0d43 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -485,19 +485,23 @@ Renderer::Renderer() } - g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; - g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; - g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1 || GLEW_NV_primitive_restart; - g_Config.backend_info.bSupportsEarlyZ = GLEW_ARB_shader_image_load_store; +#define TO_BOOL(c) (0 != (c)) - g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; - g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; - g_ogl_config.bSupportsGLSync = GLEW_ARB_sync; - g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex; - g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage; - g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading; - g_ogl_config.bSupportOGL31 = GLEW_VERSION_3_1; - g_ogl_config.bSupportViewportFloat = GLEW_ARB_viewport_array; + g_Config.backend_info.bSupportsDualSourceBlend = TO_BOOL(GLEW_ARB_blend_func_extended); + g_Config.backend_info.bSupportsGLSLUBO = TO_BOOL(GLEW_ARB_uniform_buffer_object); + g_Config.backend_info.bSupportsPrimitiveRestart = TO_BOOL(GLEW_VERSION_3_1) || TO_BOOL(GLEW_NV_primitive_restart); + g_Config.backend_info.bSupportsEarlyZ = TO_BOOL(GLEW_ARB_shader_image_load_store); + + g_ogl_config.bSupportsGLSLCache = TO_BOOL(GLEW_ARB_get_program_binary); + g_ogl_config.bSupportsGLPinnedMemory = TO_BOOL(GLEW_AMD_pinned_memory); + g_ogl_config.bSupportsGLSync = TO_BOOL(GLEW_ARB_sync); + g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex); + g_ogl_config.bSupportCoverageMSAA = TO_BOOL(GLEW_NV_framebuffer_multisample_coverage); + g_ogl_config.bSupportSampleShading = TO_BOOL(GLEW_ARB_sample_shading); + g_ogl_config.bSupportOGL31 = TO_BOOL(GLEW_VERSION_3_1); + g_ogl_config.bSupportViewportFloat = TO_BOOL(GLEW_ARB_viewport_array); + +#undef TO_BOOL if(strstr(g_ogl_config.glsl_version, "1.00") || strstr(g_ogl_config.glsl_version, "1.10") || strstr(g_ogl_config.glsl_version, "1.20")) { diff --git a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp index 9826033098..15135f3621 100644 --- a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp @@ -59,7 +59,7 @@ StreamBuffer::~StreamBuffer() glDeleteBuffers(1, &m_buffer); } -#define SLOT(x) (x)*SYNC_POINTS/m_size +#define SLOT(x) ((x)*SYNC_POINTS/m_size) void StreamBuffer::Alloc ( size_t size, u32 stride ) { @@ -81,14 +81,14 @@ void StreamBuffer::Alloc ( size_t size, u32 stride ) case PINNED_MEMORY: // insert waiting slots for used memory - for(u32 i=SLOT(m_used_iterator); i= m_size) { // insert waiting slots in unused space at the end of the buffer - for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_used_iterator); i < SYNC_POINTS; i++) + { fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } // move to the start m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned @@ -244,10 +246,14 @@ void StreamBuffer::Shutdown() void StreamBuffer::DeleteFences() { - for(u32 i=SLOT(m_free_iterator)+1; i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_free_iterator) + 1; i < SYNC_POINTS; i++) + { glDeleteSync(fences[i]); - for(u32 i=0; iAlloc(vertex_data_size, stride); - u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); + size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); s_baseVertex = offset / stride; s_indexBuffer->Alloc(index_size); @@ -121,17 +121,17 @@ void VertexManager::Draw(u32 stride) if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex); + glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (point_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex); + glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } } @@ -236,9 +236,9 @@ void VertexManager::vFlush() tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), + (0 != (tex.texMode0[i&3].min_filter & 3)), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + (0 != tex.texImage1[i&3].image_type)); if (tentry) { From 2703cae8d3847f826c88cce4622b75c2fd725795 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Thu, 14 Nov 2013 03:15:03 -0500 Subject: [PATCH 42/81] Fixed ZComploc and Zfreeze values being incorrectly saved. --- Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp index 43b6a96ef7..eb7cb79d40 100644 --- a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp @@ -65,8 +65,8 @@ void SWVideoConfig::Save(const char* ini_file) iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer); - iniFile.Set("Rendering", "ZComploc", &bZComploc); - iniFile.Set("Rendering", "ZFreeze", &bZFreeze); + iniFile.Set("Rendering", "ZComploc", bZComploc); + iniFile.Set("Rendering", "ZFreeze", bZFreeze); iniFile.Set("Info", "ShowStats", bShowStats); From 033ed9477e9e2319df449b1e310de96e5c371968 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Fri, 15 Nov 2013 13:00:38 +1300 Subject: [PATCH 43/81] Reworked Screenshot saving. Now OGL doesn't rely on WX for PNG saving. FlipImageData supports (pixel data len > 3) now. TextureToPng is now in ImageWrite.cpp/h Video Common depends on zlib and png. D3D no longer depends on zlib and png. --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 6 - .../Core/VideoBackends/D3D/Src/D3DTexture.cpp | 84 -------------- .../Core/VideoBackends/D3D/Src/D3DTexture.h | 1 - Source/Core/VideoBackends/D3D/Src/Render.cpp | 17 ++- .../VideoBackends/D3D/Src/TextureCache.cpp | 13 ++- Source/Core/VideoBackends/OGL/Src/Render.cpp | 107 ++---------------- Source/Core/VideoBackends/OGL/Src/Render.h | 2 +- Source/Core/VideoCommon/Src/ImageWrite.cpp | 93 +++++++++++++++ Source/Core/VideoCommon/Src/ImageWrite.h | 1 + Source/Core/VideoCommon/VideoCommon.vcxproj | 6 + 10 files changed, 134 insertions(+), 196 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index 15d968b97f..a4177f6909 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -93,15 +93,9 @@ - - {4c9f135b-a85e-430c-bad4-4c67ef5fc12c} - {1c8436c9-dbaf-42be-83bc-cf3ec9175abe} - - {ff213b23-2c26-4214-9f88-85271e557e87} - {3de9ee35-3e91-4f27-a014-2866ad8c3fe3} diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp index 2b632b5466..abf34b3cca 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.cpp @@ -5,96 +5,12 @@ #include "D3DBase.h" #include "D3DTexture.h" -#include "png.h" - namespace DX11 { namespace D3D { -bool TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, const char* filename, int width, int height, bool saveAlpha) -{ - bool success = false; - if (map.pData != NULL) - { - FILE *fp = NULL; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - - // Open file for writing (binary mode) - fp = fopen(filename, "wb"); - if (fp == NULL) { - PanicAlert("Could not open file %s for writing\n", filename); - goto finalise; - } - - // Initialize write structure - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - PanicAlert("Could not allocate write struct\n"); - goto finalise; - - } - - // Initialize info structure - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - PanicAlert("Could not allocate info struct\n"); - goto finalise; - } - - // Setup Exception handling - if (setjmp(png_jmpbuf(png_ptr))) { - PanicAlert("Error during png creation\n"); - goto finalise; - } - - png_init_io(png_ptr, fp); - - // Write header (8 bit colour depth) - png_set_IHDR(png_ptr, info_ptr, width, height, - 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - char title[] = "Dolphin Screenshot"; - png_text title_text; - title_text.compression = PNG_TEXT_COMPRESSION_NONE; - title_text.key = "Title"; - title_text.text = title; - png_set_text(png_ptr, info_ptr, &title_text, 1); - - png_write_info(png_ptr, info_ptr); - - // Write image data - for (auto y = 0; y < height; ++y) - { - u8* row_ptr = (u8*)map.pData + y * map.RowPitch; - u8* ptr = row_ptr; - for (UINT x = 0; x < map.RowPitch / 4; ++x) - { - if (!saveAlpha) - ptr[3] = 0xff; - ptr += 4; - } - png_write_row(png_ptr, row_ptr); - } - - // End write - png_write_end(png_ptr, NULL); - - success = true; - - finalise: - - if (fp != NULL) fclose(fp); - if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - - } - return false; -} - void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) { if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) diff --git a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h index 71583d04ea..5c2aa57f4a 100644 --- a/Source/Core/VideoBackends/D3D/Src/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/Src/D3DTexture.h @@ -11,7 +11,6 @@ namespace DX11 namespace D3D { - bool TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, const char* filename, int width, int height, bool saveAlpha = true); void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage); } diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index e2e26997c7..ae6d21ef03 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -34,6 +34,7 @@ #include "FPSCounter.h" #include "ConfigManager.h" #include +#include "ImageWrite.h" namespace DX11 { @@ -693,11 +694,19 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - // ready to be saved - HRESULT hr = D3D::TextureToPng(map, filename.c_str(), rc.GetWidth(), rc.GetHeight(), false); + bool saved_png = false; + if (map.pData) + { + u8* data = new u8[map.RowPitch * rc.GetHeight()]; + memcpy(data, map.pData, map.RowPitch * rc.GetHeight()); + + saved_png = TextureToPng(data, map.RowPitch, filename.c_str(), rc.GetWidth(), rc.GetHeight(), false); + } + D3D::context->Unmap(s_screenshot_texture, 0); - if (SUCCEEDED(hr)) + + if (saved_png) { OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), rc.GetHeight(), filename.c_str())); @@ -707,7 +716,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str())); } - return SUCCEEDED(hr); + return saved_png; } void formatBufferDump(const u8* in, u8* out, int w, int h, int p) diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index 0c6e759de5..faf83c23ca 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -14,6 +14,7 @@ #include "PSTextureEncoder.h" #include "HW/Memmap.h" #include "VideoConfig.h" +#include "ImageWrite.h" namespace DX11 { @@ -54,6 +55,8 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::device->CreateTexture2D(&desc, NULL, &pNewTexture); + bool saved_png = false; + if (SUCCEEDED(hr) && pNewTexture) { D3D::context->CopyResource(pNewTexture, pSurface); @@ -62,13 +65,19 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); if (SUCCEEDED(hr)) { - hr = D3D::TextureToPng(map, filename, desc.Width, desc.Height); + if (map.pData) + { + u8* data = new u8[map.RowPitch * desc.Height]; + memcpy(data, map.pData, map.RowPitch * desc.Height); + + saved_png = TextureToPng(data, map.RowPitch, filename, desc.Width, desc.Height); + } D3D::context->Unmap(pNewTexture, 0); } SAFE_RELEASE(pNewTexture); } - return SUCCEEDED(hr); + return saved_png; } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 020fac0d43..b32fc74f34 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -63,10 +63,6 @@ #include "AVIDump.h" #endif -#if defined(HAVE_WX) && HAVE_WX -#include -#endif - // glew1.8 doesn't define KHR_debug #ifndef GL_DEBUG_OUTPUT #define GL_DEBUG_OUTPUT 0x92E0 @@ -78,18 +74,6 @@ void VideoConfig::UpdateProjectionHack() ::UpdateProjectionHack(g_Config.iPhackvalue, g_Config.sPhackvalue); } - -#if defined(HAVE_WX) && HAVE_WX -// Screenshot thread struct -typedef struct -{ - int W, H; - std::string filename; - wxImage *img; -} ScrStrct; -#endif - - int OSDInternalW, OSDInternalH; namespace OGL @@ -1804,69 +1788,21 @@ void Renderer::SetInterlacingMode() // TODO } -void Renderer::FlipImageData(u8 *data, int w, int h) +void Renderer::FlipImageData(u8 *data, int w, int h, int pixel_width) { // Flip image upside down. Damn OpenGL. - for (int y = 0; y < h / 2; y++) + for (int y = 0; y < h / 2; ++y) { - for(int x = 0; x < w; x++) + for(int x = 0; x < w; ++x) { - std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]); - std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]); - std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]); + for (auto delta = 0; delta < pixel_width; ++delta) + std::swap(data[(y * w + x) * pixel_width + delta], data[((h - 1 - y) * w + x) * pixel_width + delta]); } } } } -// TODO: remove -extern bool g_aspect_wide; - -#if defined(HAVE_WX) && HAVE_WX -void TakeScreenshot(ScrStrct* threadStruct) -{ - // These will contain the final image size - float FloatW = (float)threadStruct->W; - float FloatH = (float)threadStruct->H; - - // Handle aspect ratio for the final ScrStrct to look exactly like what's on screen. - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) - { - bool use16_9 = g_aspect_wide; - - // Check for force-settings and override. - if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) - use16_9 = true; - else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) - use16_9 = false; - - float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - - // If ratio > 1 the picture is too wide and we have to limit the width. - if (Ratio > 1) - FloatW /= Ratio; - // ratio == 1 or the image is too high, we have to limit the height. - else - FloatH *= Ratio; - - // This is a bit expensive on high resolutions - threadStruct->img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); - } - - // Save the screenshot and finally kill the wxImage object - // This is really expensive when saving to PNG, but not at all when using BMP - threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename), - wxBITMAP_TYPE_PNG); - threadStruct->img->Destroy(); - - // Show success messages - OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, - threadStruct->filename.c_str()), 2000); - delete threadStruct; -} -#endif - namespace OGL { @@ -1874,10 +1810,10 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle { u32 W = back_rc.GetWidth(); u32 H = back_rc.GetHeight(); - u8 *data = (u8 *)malloc((sizeof(u8) * 3 * W * H)); + u8 *data = (u8 *)malloc((sizeof(u8) * 4 * W * H)); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGB, GL_UNSIGNED_BYTE, data); + glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGBA, GL_UNSIGNED_BYTE, data); // Show failure message if (GL_REPORT_ERROR() != GL_NO_ERROR) @@ -1888,34 +1824,9 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle } // Turn image upside down - FlipImageData(data, W, H); + FlipImageData(data, W, H, 4); -#if defined(HAVE_WX) && HAVE_WX - // Create wxImage - wxImage *a = new wxImage(W, H, data); - - if (scrshotThread.joinable()) - scrshotThread.join(); - - ScrStrct *threadStruct = new ScrStrct; - threadStruct->filename = filename; - threadStruct->img = a; - threadStruct->H = H; threadStruct->W = W; - - scrshotThread = std::thread(TakeScreenshot, threadStruct); -#ifdef _WIN32 - SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); -#endif - bool result = true; - - OSD::AddMessage("Saving Screenshot... ", 2000); - -#else - bool result = SaveTGA(filename.c_str(), W, H, data); - free(data); -#endif - - return result; + return TextureToPng(data, W*4, filename.c_str(), W, H, false); } } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.h b/Source/Core/VideoBackends/OGL/Src/Render.h index 9b4838ee25..0cda2f4c0e 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.h +++ b/Source/Core/VideoBackends/OGL/Src/Render.h @@ -63,7 +63,7 @@ public: void RenderText(const char* pstr, int left, int top, u32 color) override; void DrawDebugInfo(); - void FlipImageData(u8 *data, int w, int h); + void FlipImageData(u8 *data, int w, int h, int pixel_width = 3); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index f53bd1c18f..f42e89cfd0 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -5,6 +5,7 @@ #include #include +#include "png.h" #include "ImageWrite.h" #include "FileUtil.h" @@ -62,3 +63,95 @@ bool SaveData(const char* filename, const char* data) return true; } + + +/* +TextureToPng + +Inputs: +data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. +data is a newly allocated memory and must have delete[] run on it before returning. + +row_stride: Determines the amount of bytes per row of pixels. +*/ +bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha) +{ + bool success = false; + + if (!data) + return false; + + // Open file for writing (binary mode) + FILE *fp = fopen(filename, "wb"); + if (fp == NULL) { + PanicAlert("Screenshot failed: Could not open file %s\n", filename); + goto finalise; + } + + // Initialize write structure + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate write struct\n"); + goto finalise; + + } + + // Initialize info structure + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate info struct\n"); + goto finalise; + } + + // Setup Exception handling + if (setjmp(png_jmpbuf(png_ptr))) { + PanicAlert("Screenshot failed: Error during png creation\n"); + goto finalise; + } + + png_init_io(png_ptr, fp); + + // Write header (8 bit colour depth) + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + char title[] = "Dolphin Screenshot"; + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.key = "Title"; + title_text.text = title; + png_set_text(png_ptr, info_ptr, &title_text, 1); + + png_write_info(png_ptr, info_ptr); + + // Write image data + for (auto y = 0; y < height; ++y) + { + u8* row_ptr = (u8*)data + y * row_stride; + u8* ptr = row_ptr; + for (auto x = 0; x < row_stride / 4; ++x) + { + if (!saveAlpha) + ptr[3] = 0xff; + ptr += 4; + } + png_write_row(png_ptr, row_ptr); + } + + // End write + png_write_end(png_ptr, NULL); + + success = true; + +finalise: + + if (fp != NULL) fclose(fp); + if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + + // Our duty to delete the inputted data. + delete[] data; + + return success; +} diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index 7d1d6fa1e8..af7f11ad27 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -9,6 +9,7 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata); bool SaveData(const char* filename, const char* pdata); +bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha = true); #endif // _IMAGEWRITE_H diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index dd8bbc6f6d..fa7ef921ae 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -152,9 +152,15 @@ {aa862e5e-a993-497a-b6a0-0e8e94b10050} + + {4c9f135b-a85e-430c-bad4-4c67ef5fc12c} + {b441cc62-877e-4b3f-93e0-0de80544f705} + + {ff213b23-2c26-4214-9f88-85271e557e87} + {2e6c348c-c75c-4d94-8d1e-9c1fcbf3efe4} From ba71cdcc5161602474dbf52f6149af6a4ec1ba39 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Fri, 15 Nov 2013 13:05:03 +1300 Subject: [PATCH 44/81] Goto crosses initialization error. Sorry. --- Source/Core/VideoCommon/Src/ImageWrite.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index f42e89cfd0..7249a59952 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -81,15 +81,20 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int if (!data) return false; + char title[] = "Dolphin Screenshot"; + FILE *fp = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + // Open file for writing (binary mode) - FILE *fp = fopen(filename, "wb"); + fp = fopen(filename, "wb"); if (fp == NULL) { PanicAlert("Screenshot failed: Could not open file %s\n", filename); goto finalise; } // Initialize write structure - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { PanicAlert("Screenshot failed: Could not allocate write struct\n"); goto finalise; @@ -97,7 +102,7 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int } // Initialize info structure - png_infop info_ptr = png_create_info_struct(png_ptr); + info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { PanicAlert("Screenshot failed: Could not allocate info struct\n"); goto finalise; @@ -116,7 +121,6 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - char title[] = "Dolphin Screenshot"; png_text title_text; title_text.compression = PNG_TEXT_COMPRESSION_NONE; title_text.key = "Title"; From 117bf435b077bbb2fe2339b1dbe7496cda25d749 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 01:09:38 +0000 Subject: [PATCH 45/81] Fix GUI-less build. Also potentially OS X. We now require libpng due to our screenshot code relying on it now. WXWidgets links in libpng by itself so it isn't noticed in a wxwidgets build. OS X seems to not have libpng linked in from wxWidgets so just link in libpng at all times. --- CMakeLists.txt | 9 +++++++-- Source/Core/VideoCommon/CMakeLists.txt | 3 +-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7123f23d7..d350fdeb2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,11 +524,16 @@ else() set(LZO lzo2) endif() -if(ANDROID) +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) + check_lib(PNG png png.h QUIET) +endif() +if (PNG_FOUND) + message("Using shared libpng") +else() message("Using static libpng from Externals") add_subdirectory(Externals/libpng) include_directories(Externals/libpng) - set(PNG libpng) + set(PNG png) endif() if(OPENAL_FOUND) diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 594624592c..9566712191 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -39,8 +39,7 @@ set(SRCS Src/BPFunctions.cpp Src/XFMemory.cpp Src/XFStructs.cpp Src/memcpy_amd.cpp) - -set(LIBS core) +set(LIBS core png) if(NOT _M_GENERIC) set(SRCS ${SRCS} Src/x64TextureDecoder.cpp From 3e6e997e8b2c32557562c96b2341b3f6bf77d0d5 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 01:15:44 +0000 Subject: [PATCH 46/81] Fix OS X wxWidgets complaining. --- Externals/wxWidgets3/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Externals/wxWidgets3/CMakeLists.txt b/Externals/wxWidgets3/CMakeLists.txt index 1ce7a73418..6629d0865e 100644 --- a/Externals/wxWidgets3/CMakeLists.txt +++ b/Externals/wxWidgets3/CMakeLists.txt @@ -868,8 +868,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ${SRCS_GENERICOSX} ${SRCS_OSX} ${SRCS_UNIX}) - include_directories(../libpng) - add_subdirectory(../libpng ../libpng) set(LIBS png iconv From 714633f311c0cf029e65a07ad55386bb393a6b45 Mon Sep 17 00:00:00 2001 From: Jordan Cristiano Date: Thu, 14 Nov 2013 22:23:55 -0500 Subject: [PATCH 47/81] Fixed console commands not registering. Code cleanup. --- Source/Core/Core/Src/Console.cpp | 9 ++- Source/Core/Core/Src/PowerPC/PPCTables.cpp | 69 +++++++++++----------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp index 15a19b4b74..2d48d0b5c6 100644 --- a/Source/Core/Core/Src/Console.cpp +++ b/Source/Core/Core/Src/Console.cpp @@ -17,8 +17,8 @@ #include "PowerPCDisasm.h" #include "Console.h" -#define CASE1(x) if (memcmp(cmd, x, 2*sizeof(TCHAR))==0) -#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0) +#define CASE1(x) if (!strcmp(cmd, (x))) +#define CASE(x) else if (!strcmp(cmd, (x))) void Console_Submit(const char *cmd) { @@ -27,7 +27,7 @@ void Console_Submit(const char *cmd) Core::StartTrace(false); INFO_LOG(CONSOLE, "Read tracing started."); } - CASE1("w") + CASE("w") { Core::StartTrace(true); INFO_LOG(CONSOLE, "Write tracing started."); @@ -141,3 +141,6 @@ void Console_Submit(const char *cmd) ERROR_LOG(CONSOLE, "Invalid command"); } } + +#undef CASE1 +#undef CASE diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index 625e416299..5854f1f0da 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -14,24 +14,15 @@ #include "Interpreter/Interpreter_Tables.h" #include "JitInterface.h" -struct op_inf -{ - const char *name; - int count; - bool operator < (const op_inf &o) const - { - return count > o.count; - } -}; - GekkoOPInfo *m_infoTable[64]; - GekkoOPInfo *m_infoTable4[1024]; - GekkoOPInfo *m_infoTable19[1024]; - GekkoOPInfo *m_infoTable31[1024]; - GekkoOPInfo *m_infoTable59[32]; - GekkoOPInfo *m_infoTable63[1024]; +GekkoOPInfo *m_infoTable[64]; +GekkoOPInfo *m_infoTable4[1024]; +GekkoOPInfo *m_infoTable19[1024]; +GekkoOPInfo *m_infoTable31[1024]; +GekkoOPInfo *m_infoTable59[32]; +GekkoOPInfo *m_infoTable63[1024]; - GekkoOPInfo *m_allInstructions[512]; - int m_numInstructions; +GekkoOPInfo *m_allInstructions[512]; +int m_numInstructions; GekkoOPInfo *GetOpInfo(UGeckoInstruction _inst) { @@ -182,26 +173,34 @@ void CountInstruction(UGeckoInstruction _inst) { GekkoOPInfo *info = GetOpInfo(_inst); if (info) + { info->runCount++; + } } void PrintInstructionRunCounts() { - std::vector temp; - for (int i = 0; i < m_numInstructions; i++) + typedef std::pair OpInfo; + std::vector temp; + temp.reserve(m_numInstructions); + for (int i = 0; i < m_numInstructions; ++i) { - op_inf x; - x.name = m_allInstructions[i]->opname; - x.count = (int)(m_allInstructions[i]->runCount); - temp.push_back(x); + GekkoOPInfo *pInst = m_allInstructions[i]; + temp.emplace_back(pInst->opname, pInst->runCount); } - std::sort(temp.begin(), temp.end()); - for (int i = 0; i < m_numInstructions; i++) + std::sort(temp.begin(), temp.end(), + [](const OpInfo &a, const OpInfo &b) + { + return a.second > b.second; + }); + + for (auto &inst : temp) { - if (temp[i].count == 0) + if (inst.second == 0) break; - DEBUG_LOG(POWERPC, "%s : %i", temp[i].name,temp[i].count); - //PanicAlert("%s : %i", temp[i].name,temp[i].count); + + DEBUG_LOG(POWERPC, "%s : %llu", inst.first, inst.second); + //PanicAlert("%s : %llu", inst.first, inst.second); } } @@ -212,20 +211,22 @@ void LogCompiledInstructions() File::IOFile f(StringFromFormat("%sinst_log%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount > 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount > 0) { - fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount, m_allInstructions[i]->lastUse); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", pInst->opname, + pInst->compileCount, pInst->runCount, pInst->lastUse); } } f.Open(StringFromFormat("%sinst_not%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount == 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount == 0) { - fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", pInst->opname, + pInst->compileCount, pInst->runCount); } } From c712fb7356791a3fb0c6f321d79badd9420123e4 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Fri, 15 Nov 2013 17:58:57 +1300 Subject: [PATCH 48/81] Fix introduced ImageWrite warning. --- Source/Core/VideoCommon/Src/ImageWrite.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index 7249a59952..b00975e615 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -82,6 +82,7 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int return false; char title[] = "Dolphin Screenshot"; + char title_key[] = "Title"; FILE *fp = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; @@ -123,7 +124,7 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int png_text title_text; title_text.compression = PNG_TEXT_COMPRESSION_NONE; - title_text.key = "Title"; + title_text.key = title_key; title_text.text = title; png_set_text(png_ptr, info_ptr, &title_text, 1); From 0e415467c43715a2f1e51c342f57b1bcb29e0849 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 14:17:47 -0600 Subject: [PATCH 49/81] [Android] Spawn a message if someone's phone doesn't support NEON. NEON is a requirement for Dolphin Mobile on ARM, CPU core will crash without it. --- .../dolphinemu/DolphinEmulator.java | 5 +++ .../dolphinemu/dolphinemu/NativeLibrary.java | 7 ++++ .../dolphinemu/gamelist/GameListActivity.java | 33 ++++++++++++++++--- Source/Core/DolphinWX/Src/MainAndroid.cpp | 6 ++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java index b06669f8f7..bdbe53dfcb 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java @@ -86,4 +86,9 @@ public final class DolphinEmulator extends Activity UserPreferences.LoadIniToPrefs(this); } } + protected void onRestart() + { + super.onRestart(); + finish(); // If we are ever returning to this activity then we are exiting. + } } \ No newline at end of file diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index 80fcf64ff6..7d655566d3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -104,6 +104,13 @@ public final class NativeLibrary */ public static native String GetVersionString(); + /** + * Returns if the phone supports NEON or not + * + * @return if it supports NEON + */ + public static native boolean SupportsNEON(); + /** * Saves a game state to the slot number. * diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index 96f1783310..2a1ae4a8b2 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -13,16 +13,16 @@ import android.app.FragmentManager; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.widget.DrawerLayout; -import android.view.*; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; import android.widget.AdapterView; import android.widget.ListView; - -import java.util.ArrayList; -import java.util.List; - import org.dolphinemu.dolphinemu.AboutFragment; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; @@ -31,6 +31,9 @@ import org.dolphinemu.dolphinemu.settings.PrefsActivity; import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter; import org.dolphinemu.dolphinemu.sidemenu.SideMenuItem; +import java.util.ArrayList; +import java.util.List; + /** * The activity that implements all of the functions * for the game list. @@ -104,6 +107,26 @@ public final class GameListActivity extends Activity mCurFragment = new GameListFragment(); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + + // Create an alert telling them that their phone sucks + if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON()) + { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("ALERT!"); + builder.setMessage("Your phone doesn't support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway?"); + builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // Do Nothing. Just create the Yes button + } + }); + builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) + { + finish(); + } + }); + builder.show(); + } } /** diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index 21bb84446b..e0155d6bbe 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -282,6 +282,12 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersio { return env->NewStringUTF(scm_rev_str); } + +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SupportsNEON(JNIEnv *env, jobject obj) +{ + return cpu_info.bNEON; +} + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jKey, jstring jValue, jstring jDefault) { IniFile ini; From d3731d0827f9d991570423b88158c09b5f61ea9f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 15 Nov 2013 16:31:52 -0500 Subject: [PATCH 50/81] [Android] Get rid of some unnecessary variables in the getView() methods of some adapters. Directly referencing convertView is fine. --- .../folderbrowser/FolderBrowserAdapter.java | 13 ++++++------- .../dolphinemu/gamelist/GameListAdapter.java | 13 ++++++------- .../dolphinemu/sidemenu/SideMenuAdapter.java | 9 ++++----- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java index 8d96a8232c..81d738b143 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java @@ -56,19 +56,18 @@ public final class FolderBrowserAdapter extends ArrayAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); } final FolderBrowserItem item = items.get(position); if (item != null) { - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); + ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); + TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); if(title != null) { @@ -100,6 +99,6 @@ public final class FolderBrowserAdapter extends ArrayAdapter } } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java index d0b3642ffe..ca30f4f284 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java @@ -55,19 +55,18 @@ public final class GameListAdapter extends ArrayAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); } final GameListItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); + TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); if (title != null) title.setText(item.getName()); @@ -83,7 +82,7 @@ public final class GameListAdapter extends ArrayAdapter } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java index 6ea97e3f66..60fd8b56f3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java @@ -54,23 +54,22 @@ public final class SideMenuAdapter extends ArrayAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, null); + convertView = vi.inflate(id, null); } final SideMenuItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.SideMenuTitle); + TextView title = (TextView) convertView.findViewById(R.id.SideMenuTitle); if (title != null) title.setText(item.getName()); } - return v; + return convertView; } } From 4bb22aa0ab7c06c28e09de0f1b6db042ad23e84a Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 15 Nov 2013 16:48:36 -0500 Subject: [PATCH 51/81] [Android] Indicate whether or not the device supports NEON within the About fragment. --- Source/Android/res/values-ja/strings.xml | 1 + Source/Android/res/values/strings.xml | 1 + .../Android/src/org/dolphinemu/dolphinemu/AboutFragment.java | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index bf19db23f0..f5858aa4bb 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -11,6 +11,7 @@ ビルドのバージョン サポートのOpenGL ES 3 + サポートのNEON 現在のディレクトリ: %1$s diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 983f9e6ace..0f56eb1df4 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -11,6 +11,7 @@ Build Revision Supports OpenGL ES 3 + Supports NEON Current Dir: %1$s diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java index 8b29e607d7..6a0d033265 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java @@ -35,12 +35,13 @@ public final class AboutFragment extends ListFragment View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); - String yes = getString(R.string.yes); - String no = getString(R.string.no); + final String yes = getString(R.string.yes); + final String no = getString(R.string.no); List Input = new ArrayList(); Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString())); Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); + Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); AboutFragmentAdapter adapter = new AboutFragmentAdapter(m_activity, R.layout.about_layout, Input); mMainList.setAdapter(adapter); From 8c7d1afd5fdd8086324068774d3565dc39f3df2e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 15 Nov 2013 17:05:56 -0500 Subject: [PATCH 52/81] [Android] Externalize the device compatibility warning strings. --- Source/Android/res/values-ja/strings.xml | 4 ++++ Source/Android/res/values/strings.xml | 4 ++++ .../Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java | 2 +- .../org/dolphinemu/dolphinemu/gamelist/GameListActivity.java | 4 ++-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index f5858aa4bb..f489bc75f4 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -26,6 +26,10 @@ 設定 について + + デバイスの互換性の警告 + この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか? + クリックされたファイル: %1$s diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 0f56eb1df4..505c493afd 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -26,6 +26,10 @@ Settings About + + Device Compatibility Warning + Your phone doesn\'t support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway? + File clicked: %1$s diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index 7d655566d3..d5c10f8fad 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -107,7 +107,7 @@ public final class NativeLibrary /** * Returns if the phone supports NEON or not * - * @return if it supports NEON + * @return true if it supports NEON, false otherwise. */ public static native boolean SupportsNEON(); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index 2a1ae4a8b2..eba52036e5 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -112,8 +112,8 @@ public final class GameListActivity extends Activity if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON()) { AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("ALERT!"); - builder.setMessage("Your phone doesn't support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway?"); + builder.setTitle(R.string.device_compat_warning); + builder.setMessage(R.string.device_compat_warning_msg); builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Do Nothing. Just create the Yes button From 483a28f34a5aa45d43f3091a215cc55e82031ecf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 15 Nov 2013 17:19:09 -0500 Subject: [PATCH 53/81] [Android] Simplify the AboutFragmentAdapter a little bit. - Removes an unnecessary variable. - Shortens the LayoutInflater usage. - Gets rid of an unnecessary override of onAttach. --- .../dolphinemu/dolphinemu/AboutFragment.java | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java index 6a0d033265..c2adb2a702 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java @@ -6,7 +6,6 @@ package org.dolphinemu.dolphinemu; -import android.app.Activity; import android.app.ListFragment; import android.content.Context; import android.os.Bundle; @@ -27,8 +26,6 @@ import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment; */ public final class AboutFragment extends ListFragment { - private static Activity m_activity; - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -43,22 +40,13 @@ public final class AboutFragment extends ListFragment Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); - AboutFragmentAdapter adapter = new AboutFragmentAdapter(m_activity, R.layout.about_layout, Input); + AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input); mMainList.setAdapter(adapter); mMainList.setEnabled(false); // Makes the list view non-clickable. return mMainList; } - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - - // Cache the activity instance. - m_activity = activity; - } - // Represents an item in the AboutFragment. private static final class AboutFragmentItem { @@ -107,18 +95,17 @@ public final class AboutFragment extends ListFragment @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { - LayoutInflater vi = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(id, parent, false); + LayoutInflater vi = LayoutInflater.from(ctx); + convertView = vi.inflate(id, parent, false); } final AboutFragmentItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.AboutItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.AboutItemSubTitle); + TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); if (title != null) title.setText(item.getTitle()); @@ -127,7 +114,7 @@ public final class AboutFragment extends ListFragment subtitle.setText(item.getSubTitle()); } - return v; + return convertView; } } } From b9d7bb90129fac1c67b870267af1ae68fa602beb Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 16:51:01 -0600 Subject: [PATCH 54/81] [Android] Broken UBOs has been fixed in Adreno driver v53, so update the comment in DriverDetails.h. Also enable dynamic UBO array member access with that version since there is a high chance of it being fixed. Dynamic UBO member access is commonly noticed with character models being terrible looking. --- Source/Core/VideoCommon/Src/DriverDetails.cpp | 2 +- Source/Core/VideoCommon/Src/DriverDetails.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 21b2273a49..1a9a56f532 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -27,7 +27,7 @@ namespace DriverDetails // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, 46.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_ANNIHILATEDUBOS, 41.0, 46.0, true}, diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index b9ace5b4f5..2a5fb3ce22 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -53,7 +53,7 @@ namespace DriverDetails // Bug: No Dynamic UBO array object access // Affected Devices: Qualcomm/Adreno // Started Version: 14 - // Ended Version: -1 + // Ended Version: 53 // Accessing UBO array members dynamically causes the Adreno shader compiler to crash // Errors out with "Internal Error" BUG_NODYNUBOACCESS = 0, @@ -102,7 +102,7 @@ namespace DriverDetails // Bug: Entirely broken UBOs // Affected devices: Qualcomm/Adreno // Started Version: ? (Noticed on v45) - // Ended Version: -1 + // Ended Version: 53 // Uniform buffers are entirely broken on Qualcomm drivers with v45 // Trying to use the uniform buffers causes a malloc to fail inside the driver // To be safe, blanket drivers from v41 - v45 From 0720026dab7c1899cf788f4ed24514c5a89d8717 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 16:56:21 -0600 Subject: [PATCH 55/81] [Android] Disable the workaround for Qualcomm devices with driver >= 53 for the rotated framebuffer since it is fixed now. --- .../dolphinemu/dolphinemu/emulation/EmulationActivity.java | 4 +++- .../dolphinemu/settings/VideoSettingsFragment.java | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java index 912fc021c5..0fdd0c1bee 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java @@ -68,12 +68,14 @@ public final class EmulationActivity extends Activity // Due to a bug in Adreno, it renders the screen rotated 90 degrees when using OpenGL // Flip the width and height when on Adreno to work around this. + // This bug is fixed in Qualcomm driver v53 // Mali isn't affected by this bug. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (prefs.getString("gpuPref", "Software Rendering").equals("OGL") && VideoSettingsFragment.SupportsGLES3() && VideoSettingsFragment.m_GLVendor != null - && VideoSettingsFragment.m_GLVendor.equals("Qualcomm")) + && VideoSettingsFragment.m_GLVendor.equals("Qualcomm") + && VideoSettingsFragment.m_QualcommVersion < 53.0f) NativeLibrary.SetDimensions((int)screenHeight, (int)screenWidth); else NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java index 8cf7cf0cf4..b88ea07afe 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java @@ -28,6 +28,7 @@ public final class VideoSettingsFragment extends PreferenceFragment public static String m_GLVendor; public static String m_GLRenderer; public static String m_GLExtensions; + public static float m_QualcommVersion; private Activity m_activity; /** @@ -165,7 +166,6 @@ public final class VideoSettingsFragment extends PreferenceFragment { int mVStart = m_GLVersion.indexOf("V@") + 2; int mVEnd = 0; - float mVersion; for (int a = mVStart; a < m_GLVersion.length(); ++a) { @@ -176,9 +176,9 @@ public final class VideoSettingsFragment extends PreferenceFragment } } - mVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); + m_QualcommVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); - if (mVersion >= 14.0f) + if (m_QualcommVersion >= 14.0f) mSupportsGLES3 = true; } } From 15bb9742249872e8a6af016622bf00fe732af8fd Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 17:32:50 -0600 Subject: [PATCH 56/81] [Android] Add screenshot nativelibrary function. --- .../src/org/dolphinemu/dolphinemu/NativeLibrary.java | 6 ++++++ Source/Core/DolphinWX/Src/MainAndroid.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index d5c10f8fad..4662ca4372 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -111,6 +111,12 @@ public final class NativeLibrary */ public static native boolean SupportsNEON(); + /** + * Saves a screen capture of the game + * + */ + public static native void SaveScreenShot(); + /** * Saves a game state to the slot number. * diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index e0155d6bbe..1c1c481b24 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -278,6 +278,7 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle( env->ReleaseStringUTFChars(jFile, File); return env->NewStringUTF(Name.c_str()); } + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj) { return env->NewStringUTF(scm_rev_str); @@ -288,6 +289,11 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Supports return cpu_info.bNEON; } +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj) +{ + Core::SaveScreenShot(); +} + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jKey, jstring jValue, jstring jDefault) { IniFile ini; From 3a13dfdd9b9717a4610908e973a886e115b6ac36 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 16 Nov 2013 15:59:59 +1300 Subject: [PATCH 57/81] [OGL] Textures now save to PNG not TGA --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 2 +- .../VideoBackends/OGL/Src/TextureCache.cpp | 15 ++--- .../VideoBackends/OGL/Src/VertexManager.cpp | 2 +- .../VideoBackends/Software/Src/DebugUtil.cpp | 57 ++++++++----------- .../VideoBackends/Software/Src/DebugUtil.h | 2 +- .../Software/Src/HwRasterizer.cpp | 7 +-- Source/Core/VideoCommon/Src/ImageWrite.cpp | 48 +--------------- Source/Core/VideoCommon/Src/ImageWrite.h | 1 - 8 files changed, 35 insertions(+), 99 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index b32fc74f34..784e2612bf 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1627,7 +1627,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // For testing zbuffer targets. // Renderer::SetZBufferRender(); - // SaveTexture("tex.tga", GL_TEXTURE_2D, s_FakeZTarget, + // SaveTexture("tex.png", GL_TEXTURE_2D, s_FakeZTarget, // GetTargetWidth(), GetTargetHeight()); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); XFBWrited = false; diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp index 41c52ec724..0c4fe8a187 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp @@ -64,10 +64,10 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width #ifndef USE_GLES3 int width = std::max(virtual_width >> level, 1); int height = std::max(virtual_height >> level, 1); - std::vector data(width * height); + u8* data = new u8[width * height * 4]; glActiveTexture(GL_TEXTURE0+9); glBindTexture(textarget, tex); - glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data); glBindTexture(textarget, 0); TextureCache::SetStage(); @@ -75,10 +75,11 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width if (GL_NO_ERROR != err) { PanicAlert("Can't save texture, GL Error: %s", gluErrorString(err)); + delete[] data; return false; } - return SaveTGA(filename, width, height, &data[0]); + return TextureToPng(data, width*4, filename, width, height, true); #else return false; #endif @@ -127,11 +128,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) { - // TODO: make ogl dump PNGs - std::string tga_filename(filename); - tga_filename.replace(tga_filename.size() - 3, 3, "tga"); - - return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); + return SaveTexture(filename, GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, @@ -395,7 +392,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (g_ActiveConfig.bDumpEFBTarget) { static int count = 0; - SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + SaveTexture(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); } diff --git a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp index 438eff890d..1ff9b53e28 100644 --- a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp @@ -335,7 +335,7 @@ void VertexManager::vFlush() if (g_ActiveConfig.iLog & CONF_SAVETARGETS) { char str[128]; - sprintf(str, "%starg%.3d.tga", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + sprintf(str, "%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); TargetRectangle tr; tr.left = 0; tr.right = Renderer::GetTargetWidth(); diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 4472639a20..3f21e6a758 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -54,28 +54,20 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip) u8 *data = new u8[width * height * 4]; - GetTextureBGRA(data, texmap, mip, width, height); + GetTextureRGBA(data, texmap, mip, width, height); - (void)SaveTGA(filename, width, height, data); + (void)TextureToPng(data, width*4, filename, width, height, true); - delete []data; } -void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) +void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) { - u8 sample[4]; - for (u32 y = 0; y < height; y++) { for (u32 x = 0; x < width; x++) { - TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample); - - // RGBA to BGRA - *(dst++) = sample[2]; - *(dst++) = sample[1]; - *(dst++) = sample[0]; - *(dst++) = sample[3]; + TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, dst); + dst += 4; } } } @@ -104,7 +96,7 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); } @@ -121,7 +113,7 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); } @@ -139,17 +131,15 @@ void DumpEfb(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { EfbInterface::GetColor(x, y, sample); - // ABGR to BGRA - *(writePtr++) = sample[1]; - *(writePtr++) = sample[2]; + // ABGR to RGBA *(writePtr++) = sample[3]; + *(writePtr++) = sample[2]; + *(writePtr++) = sample[1]; *(writePtr++) = sample[0]; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); } void DumpDepth(const char* filename) @@ -162,17 +152,15 @@ void DumpDepth(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { u32 depth = EfbInterface::GetDepth(x, y); - // depth to bgra - *(writePtr++) = (depth >> 16) & 0xff; + // depth to rgba + *(writePtr++) = depth & 0xff; *(writePtr++) = (depth >> 8) & 0xff; - *(writePtr++) = depth & 0xff; + *(writePtr++) = (depth >> 16) & 0xff; *(writePtr++) = 255; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); } void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name) @@ -232,7 +220,7 @@ void OnObjectEnd() if (!g_bSkipCurrentFrame) { if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) - DumpEfb(StringFromFormat("%sobject%i.tga", + DumpEfb(StringFromFormat("%sobject%i.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.thisFrame.numDrawnObjects).c_str()); @@ -247,10 +235,11 @@ void OnObjectEnd() if (DrawnToBuffer[i]) { DrawnToBuffer[i] = false; - (void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(), - EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]); + std::string filename = StringFromFormat("%sobject%i_%s(%i).png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), + swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]); + + (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename.c_str(), EFB_WIDTH, EFB_HEIGHT, true); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); } } @@ -265,9 +254,9 @@ void OnFrameEnd() { if (g_SWVideoConfig.bDumpFrames) { - DumpEfb(StringFromFormat("%sframe%i_color.tga", + DumpEfb(StringFromFormat("%sframe%i_color.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); - DumpDepth(StringFromFormat("%sframe%i_depth.tga", + DumpDepth(StringFromFormat("%sframe%i_depth.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); } } diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.h b/Source/Core/VideoBackends/Software/Src/DebugUtil.h index 3cbb318ffb..7d5ac4beea 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.h +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.h @@ -9,7 +9,7 @@ namespace DebugUtil { void Init(); - void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); + void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); void DumpActiveTextures(); diff --git a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp index 996b440dc4..88b3e15ebd 100644 --- a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp +++ b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp @@ -329,15 +329,12 @@ namespace HwRasterizer int image_width = texImage0.width; int image_height = texImage0.height; - DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height); + DebugUtil::GetTextureRGBA(temp, 0, 0, image_width, image_height); glGenTextures(1, (GLuint *)&texture); glBindTexture(TEX2D, texture); -#ifdef USE_GLES glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); -#else - glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); -#endif + GL_REPORT_ERRORD(); } diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index b00975e615..5bf3f28e45 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -9,52 +9,6 @@ #include "ImageWrite.h" #include "FileUtil.h" -#pragma pack(push, 1) - -struct TGA_HEADER -{ - u8 identsize; // size of ID field that follows 18 u8 header (0 usually) - u8 colourmaptype; // type of colour map 0=none, 1=has palette - u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed - - s16 colourmapstart; // first colour map entry in palette - s16 colourmaplength; // number of colours in palette - u8 colourmapbits; // number of bits per palette entry 15,16,24,32 - - s16 xstart; // image x origin - s16 ystart; // image y origin - s16 width; // image width in pixels - s16 height; // image height in pixels - u8 bits; // image bits per pixel 8,16,24,32 - u8 descriptor; // image descriptor bits (vh flip bits) - - // pixel data follows header -}; - -#pragma pack(pop) - -bool SaveTGA(const char* filename, int width, int height, void* pdata) -{ - TGA_HEADER hdr; - File::IOFile f(filename, "wb"); - if (!f) - return false; - - _assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); - - memset(&hdr, 0, sizeof(hdr)); - hdr.imagetype = 2; - hdr.bits = 32; - hdr.width = width; - hdr.height = height; - hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical - - f.WriteArray(&hdr, 1); - f.WriteBytes(pdata, width * height * 4); - - return true; -} - bool SaveData(const char* filename, const char* data) { std::ofstream f; @@ -90,7 +44,7 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int // Open file for writing (binary mode) fp = fopen(filename, "wb"); if (fp == NULL) { - PanicAlert("Screenshot failed: Could not open file %s\n", filename); + PanicAlert("Screenshot failed: Could not open file %s %d\n", filename, errno); goto finalise; } diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index af7f11ad27..82a942c767 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -7,7 +7,6 @@ #include "Common.h" -bool SaveTGA(const char* filename, int width, int height, void* pdata); bool SaveData(const char* filename, const char* pdata); bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha = true); From 23c84c220f396c53731360dd90acaf278d212422 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 15 Nov 2013 22:21:50 -0500 Subject: [PATCH 58/81] [Android] Add ability to take screenshots into the emulation menu. --- Source/Android/res/menu/emuwindow_overlay.xml | 8 ++++++-- Source/Android/res/values-ja/strings.xml | 1 + Source/Android/res/values/strings.xml | 1 + .../dolphinemu/emulation/EmulationActivity.java | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Source/Android/res/menu/emuwindow_overlay.xml b/Source/Android/res/menu/emuwindow_overlay.xml index d1c480c284..dc875203e8 100644 --- a/Source/Android/res/menu/emuwindow_overlay.xml +++ b/Source/Android/res/menu/emuwindow_overlay.xml @@ -1,7 +1,11 @@ + クリックされたファイル: %1$s + スクリーンショットを撮る ステートセーブ ステートロード 終了 diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 505c493afd..ca7157fd44 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -34,6 +34,7 @@ File clicked: %1$s + Take Screenshot Save State Load State Exit diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java index 0fdd0c1bee..926b971398 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java @@ -175,6 +175,11 @@ public final class EmulationActivity extends Activity { switch(item.getItemId()) { + // Screenshot capturing + case R.id.takeScreenshot: + NativeLibrary.SaveScreenShot(); + return true; + // Save state slots case R.id.saveSlot1: NativeLibrary.SaveState(0); From e8a4cc0f711b9b9c6f39bc281bc6a82ea36d2060 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 15 Nov 2013 22:07:08 -0600 Subject: [PATCH 59/81] Screenshot capability of Software rasterizer for feature completness. --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 3 +-- .../VideoBackends/Software/Src/SWRenderer.cpp | 26 +++++++++++++++++++ .../VideoBackends/Software/Src/SWRenderer.h | 6 +++-- .../VideoBackends/Software/Src/SWmain.cpp | 3 ++- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 784e2612bf..5a2e6dfe01 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1810,7 +1810,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle { u32 W = back_rc.GetWidth(); u32 H = back_rc.GetHeight(); - u8 *data = (u8 *)malloc((sizeof(u8) * 4 * W * H)); + u8 *data = new u8[W * 4 * H]; glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGBA, GL_UNSIGNED_BYTE, data); @@ -1825,7 +1825,6 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // Turn image upside down FlipImageData(data, W, H, 4); - return TextureToPng(data, W*4, filename.c_str(), W, H, false); } diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index 1d894b18da..c2d9b626f7 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -5,6 +5,8 @@ #include "Common.h" #include "../../OGL/Src/GLUtil.h" +#include "ImageWrite.h" +#include "ImageWrite.h" #include "RasterFont.h" #include "SWRenderer.h" #include "SWStatistics.h" @@ -17,6 +19,11 @@ static GLint attr_pos = -1, attr_tex = -1; static GLint uni_tex = -1; static GLuint program; +static volatile bool s_bScreenshot; +static std::mutex s_criticalScreenshot; +static std::string s_sScreenshotName; + + // Rasterfont isn't compatible with GLES // degasus: I think it does, but I can't test it #ifndef USE_GLES @@ -25,6 +32,7 @@ RasterFont* s_pfont = NULL; void SWRenderer::Init() { + s_bScreenshot = false; } void SWRenderer::Shutdown() @@ -80,6 +88,13 @@ void SWRenderer::Prepare() GL_REPORT_ERRORD(); } +void SWRenderer::SetScreenshot(const char *_szFilename) +{ + std::lock_guard lk(s_criticalScreenshot); + s_sScreenshotName = _szFilename; + s_bScreenshot = true; +} + void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color) { #ifndef USE_GLES @@ -124,6 +139,17 @@ void SWRenderer::DrawDebugText() void SWRenderer::DrawTexture(u8 *texture, int width, int height) { + // Save screenshot + if (s_bScreenshot) + { + std::lock_guard lk(s_criticalScreenshot); + u8 *data = new u8[width * 4 * height]; + memcpy(data, texture, sizeof(u8) * 4 * width * height); + TextureToPng(data, width*4, s_sScreenshotName.c_str(), width, height, false); + // Reset settings + s_sScreenshotName.clear(); + s_bScreenshot = false; + } GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.h b/Source/Core/VideoBackends/Software/Src/SWRenderer.h index ba856936cb..80a93ea203 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.h @@ -6,13 +6,15 @@ #define _RENDERER_H_ #include "CommonTypes.h" +#include "Thread.h" namespace SWRenderer -{ +{ void Init(); void Prepare(); void Shutdown(); - + + void SetScreenshot(const char *_szFilename); void RenderText(const char* pstr, int left, int top, u32 color); void DrawDebugText(); diff --git a/Source/Core/VideoBackends/Software/Src/SWmain.cpp b/Source/Core/VideoBackends/Software/Src/SWmain.cpp index 939dd4553a..074b6bc38b 100644 --- a/Source/Core/VideoBackends/Software/Src/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWmain.cpp @@ -236,7 +236,8 @@ u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) bool VideoSoftware::Video_Screenshot(const char *_szFilename) { - return false; + SWRenderer::SetScreenshot(_szFilename); + return true; } // ------------------------------- From 777b5a109bc1d507957f4a10a3d94ae151f35e96 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 01:48:17 -0500 Subject: [PATCH 60/81] [Android] Fix the handling of orientation changes for the Fragments related to the game list. Now screen orientation changes don't kick you back to the root view. --- .../dolphinemu/gamelist/GameListActivity.java | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index eba52036e5..bc0aeed446 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -9,7 +9,7 @@ package org.dolphinemu.dolphinemu.gamelist; import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; -import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; @@ -23,6 +23,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; + import org.dolphinemu.dolphinemu.AboutFragment; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; @@ -103,10 +104,16 @@ public final class GameListActivity extends Activity }; mDrawerLayout.setDrawerListener(mDrawerToggle); - // Display the game list fragment. - mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + // Display the game list fragment on activity creation, + // but only if no previous states have been saved. + if (savedInstanceState == null) + { + mCurFragment = new GameListFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, mCurFragment); + ft.commit(); + } + // Create an alert telling them that their phone sucks if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON()) @@ -151,8 +158,9 @@ public final class GameListActivity extends Activity mCurFragmentNum = 0; mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, mCurFragment); + ft.commit(); invalidateOptionsMenu(); } break; @@ -161,8 +169,10 @@ public final class GameListActivity extends Activity { mCurFragmentNum = 1; mCurFragment = new FolderBrowser(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, mCurFragment); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -178,8 +188,10 @@ public final class GameListActivity extends Activity { mCurFragmentNum = 3; mCurFragment = new AboutFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, mCurFragment); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -281,10 +293,4 @@ public final class GameListActivity extends Activity return super.onOptionsItemSelected(item); } - - @Override - public void onBackPressed() - { - SwitchPage(0); - } } From 21a196f9af6fa97d9a8de977f2bce19d2ec950e3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 03:09:07 -0500 Subject: [PATCH 61/81] [Android] Eliminate the need to hold a reference to the shown Fragment within GameListActivity. Now we only care about the numeric ID of the one being shown. --- .../dolphinemu/gamelist/GameListActivity.java | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index bc0aeed446..bdf4f7c314 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -43,7 +43,6 @@ public final class GameListActivity extends Activity implements GameListFragment.OnGameListZeroListener { private int mCurFragmentNum = 0; - private Fragment mCurFragment; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; @@ -108,9 +107,9 @@ public final class GameListActivity extends Activity // but only if no previous states have been saved. if (savedInstanceState == null) { - mCurFragment = new GameListFragment(); + final GameListFragment gameList = new GameListFragment(); FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(R.id.content_frame, mCurFragment); + ft.replace(R.id.content_frame, gameList); ft.commit(); } @@ -157,9 +156,9 @@ public final class GameListActivity extends Activity setTitle(R.string.app_name); mCurFragmentNum = 0; - mCurFragment = new GameListFragment(); + final GameListFragment gameList = new GameListFragment(); FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(R.id.content_frame, mCurFragment); + ft.replace(R.id.content_frame, gameList, ""); ft.commit(); invalidateOptionsMenu(); } @@ -168,9 +167,9 @@ public final class GameListActivity extends Activity case 1: // Folder Browser { mCurFragmentNum = 1; - mCurFragment = new FolderBrowser(); + final FolderBrowser folderBrowser = new FolderBrowser(); FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(R.id.content_frame, mCurFragment); + ft.replace(R.id.content_frame, folderBrowser); ft.addToBackStack(null); ft.commit(); invalidateOptionsMenu(); @@ -187,9 +186,9 @@ public final class GameListActivity extends Activity case 3: // About { mCurFragmentNum = 3; - mCurFragment = new AboutFragment(); + final AboutFragment aboutFragment = new AboutFragment(); FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(R.id.content_frame, mCurFragment); + ft.replace(R.id.content_frame, aboutFragment); ft.addToBackStack(null); ft.commit(); invalidateOptionsMenu(); @@ -278,7 +277,7 @@ public final class GameListActivity extends Activity NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", "0"); // Now finally, clear the game list. - ((GameListFragment) mCurFragment).clearGameList(); + ((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList(); } }); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @@ -293,4 +292,26 @@ public final class GameListActivity extends Activity return super.onOptionsItemSelected(item); } + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + + outState.putInt("currentFragmentNum", mCurFragmentNum); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + + mCurFragmentNum = savedInstanceState.getInt("currentFragmentNum"); + } + + @Override + public void onBackPressed() + { + SwitchPage(0); + } } From c90ce1aad121eacda4f932bbebe2fb3de0ba6c43 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 03:31:02 -0500 Subject: [PATCH 62/81] [Android] Change the name of the XML layout file gamelist_folderbrowser_list.xml to gamelist_folderbrowser_list_item.xml. More accurate name on what it is. --- ...derbrowser_list.xml => gamelist_folderbrowser_list_item.xml} | 0 .../org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java | 2 +- .../org/dolphinemu/dolphinemu/gamelist/GameListFragment.java | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename Source/Android/res/layout/{gamelist_folderbrowser_list.xml => gamelist_folderbrowser_list_item.xml} (100%) diff --git a/Source/Android/res/layout/gamelist_folderbrowser_list.xml b/Source/Android/res/layout/gamelist_folderbrowser_list_item.xml similarity index 100% rename from Source/Android/res/layout/gamelist_folderbrowser_list.xml rename to Source/Android/res/layout/gamelist_folderbrowser_list_item.xml diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 1697311fe3..63a4f2bbd7 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -96,7 +96,7 @@ public final class FolderBrowser extends ListFragment if (!currDir.getPath().equalsIgnoreCase("/")) dir.add(0, new FolderBrowserItem("..", getString(R.string.parent_directory), currDir.getParent())); - adapter = new FolderBrowserAdapter(m_activity, R.layout.gamelist_folderbrowser_list, dir); + adapter = new FolderBrowserAdapter(m_activity, R.layout.gamelist_folderbrowser_list_item, dir); mFolderBrowserList = (ListView) rootView.findViewById(R.id.gamelist); mFolderBrowserList.setAdapter(adapter); } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 41eb271b99..4224e16282 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -94,7 +94,7 @@ public final class GameListFragment extends ListFragment } Collections.sort(fls); - mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_folderbrowser_list, fls); + mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_folderbrowser_list_item, fls); setListAdapter(mGameAdapter); if (fls.isEmpty()) From 94f8c68a35b6b29e6670092ebc78e0dcd206463e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 03:56:58 -0500 Subject: [PATCH 63/81] [Android] Use the ViewHolder design pattern for the FolderBrowserAdapter. In directories with a lot of files, this should be noticeably smoother in terms of scrolling. Also fixed the case where the subtitle text might disappear. --- .../folderbrowser/FolderBrowserAdapter.java | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java index 81d738b143..a9dc002733 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java @@ -27,9 +27,21 @@ import org.dolphinemu.dolphinemu.R; */ public final class FolderBrowserAdapter extends ArrayAdapter { + // ViewHolder which is used to hold onto + // items within a listview. This is done + // so that findViewById is not needed to + // be excessively called over and over. + private static final class ViewHolder + { + TextView title; + TextView subtitle; + ImageView icon; + } + private final Context context; private final int id; private final List items; + private ViewHolder viewHolder; /** * Constructor @@ -60,42 +72,50 @@ public final class FolderBrowserAdapter extends ArrayAdapter { LayoutInflater vi = LayoutInflater.from(context); convertView = vi.inflate(id, parent, false); + + // Initialize the ViewHolder and store it. + viewHolder = new ViewHolder(); + viewHolder.title = (TextView) convertView.findViewById(R.id.ListItemTitle); + viewHolder.subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + viewHolder.icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); + convertView.setTag(viewHolder); + } + else // Can recover the holder. + { + viewHolder = (ViewHolder) convertView.getTag(); } final FolderBrowserItem item = items.get(position); if (item != null) { - ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); - TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); - - if(title != null) + if (viewHolder.title != null) { - title.setText(item.getName()); + viewHolder.title.setText(item.getName()); } - if(subtitle != null) + if (viewHolder.subtitle != null) { // Remove the subtitle for all folders, except for the parent directory folder. if (item.isDirectory() && !item.getSubtitle().equals(context.getString(R.string.parent_directory))) { - subtitle.setVisibility(View.GONE); + viewHolder.subtitle.setVisibility(View.GONE); } else { - subtitle.setText(item.getSubtitle()); + viewHolder.subtitle.setVisibility(View.VISIBLE); + viewHolder.subtitle.setText(item.getSubtitle()); } } - if (icon != null) + if (viewHolder.icon != null) { if (item.isDirectory()) { - icon.setImageResource(R.drawable.ic_menu_folder); + viewHolder.icon.setImageResource(R.drawable.ic_menu_folder); } else { - icon.setImageResource(R.drawable.ic_menu_file); + viewHolder.icon.setImageResource(R.drawable.ic_menu_file); } } } From c8ddc70c973a86053c663efb3b63092ea3aeb8b0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 04:09:30 -0500 Subject: [PATCH 64/81] [Android] Simplify the AboutFragment view inflating. Considering the backing layout is a direct ListView, the original rootView can just be casted to a ListView, no need for an intermediate. --- .../src/org/dolphinemu/dolphinemu/AboutFragment.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java index c2adb2a702..defefcc0d4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java @@ -29,8 +29,7 @@ public final class AboutFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); final String yes = getString(R.string.yes); final String no = getString(R.string.no); @@ -41,10 +40,10 @@ public final class AboutFragment extends ListFragment Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input); - mMainList.setAdapter(adapter); - mMainList.setEnabled(false); // Makes the list view non-clickable. + rootView.setAdapter(adapter); + rootView.setEnabled(false); // Makes the list view non-clickable. - return mMainList; + return rootView; } // Represents an item in the AboutFragment. From d98664b05357fb35764bf5e4df9da61f793d4b7d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 04:36:22 -0500 Subject: [PATCH 65/81] [Android] Simplify the FolderBrowserAdapter a little, as well as the Fill method within FolderBrowser.java. Previously the fill method would create an entire new adapter and assign it to the backing ListView. This is pretty unnecessary, so what it now does is, when the function is called, it clears out the adapter, then simply fills it in again with the new directory's contents. Simple, and doesn't require a reference to the actual ListView to be used. --- .../folderbrowser/FolderBrowser.java | 35 ++++++++----------- .../folderbrowser/FolderBrowserAdapter.java | 18 ++-------- 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 63a4f2bbd7..8aa561376a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -6,7 +6,6 @@ package org.dolphinemu.dolphinemu.folderbrowser; -import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; import android.os.Environment; @@ -37,16 +36,18 @@ import org.dolphinemu.dolphinemu.gamelist.GameListActivity; */ public final class FolderBrowser extends ListFragment { - private Activity m_activity; private FolderBrowserAdapter adapter; - private ListView mFolderBrowserList; - private ListView rootView; private static File currentDir = null; // Populates the FolderView with the given currDir's contents. private void Fill(File currDir) { - m_activity.setTitle(String.format(getString(R.string.current_dir), currDir.getName())); + // Clear the adapter of previous items. + adapter.clear(); + + // Set the activity title to the current directory the FolderBrowser is in. + getActivity().setTitle(String.format(getString(R.string.current_dir), currDir.getName())); + File[] dirs = currDir.listFiles(); List dir = new ArrayList(); List fls = new ArrayList(); @@ -96,9 +97,9 @@ public final class FolderBrowser extends ListFragment if (!currDir.getPath().equalsIgnoreCase("/")) dir.add(0, new FolderBrowserItem("..", getString(R.string.parent_directory), currDir.getParent())); - adapter = new FolderBrowserAdapter(m_activity, R.layout.gamelist_folderbrowser_list_item, dir); - mFolderBrowserList = (ListView) rootView.findViewById(R.id.gamelist); - mFolderBrowserList.setAdapter(adapter); + // Add the items to the adapter and notify the adapter users of its new contents. + adapter.addAll(dir); + adapter.notifyDataSetChanged(); } @Override @@ -122,22 +123,14 @@ public final class FolderBrowser extends ListFragment if(currentDir == null) currentDir = new File(Environment.getExternalStorageDirectory().getPath()); - rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + adapter = new FolderBrowserAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(adapter); Fill(currentDir); - return mFolderBrowserList; + return rootView; } - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - - // Cache the activity instance. - m_activity = activity; - } - - private void FolderSelected() { String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0"); @@ -168,6 +161,6 @@ public final class FolderBrowser extends ListFragment NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPath" + Integer.toString(intDirectories), currentDir.getPath()); } - ((GameListActivity)m_activity).SwitchPage(0); + ((GameListActivity)getActivity()).SwitchPage(0); } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java index a9dc002733..f97799e6e4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java @@ -6,15 +6,12 @@ package org.dolphinemu.dolphinemu.folderbrowser; -import java.util.List; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import org.dolphinemu.dolphinemu.R; @@ -40,7 +37,6 @@ public final class FolderBrowserAdapter extends ArrayAdapter private final Context context; private final int id; - private final List items; private ViewHolder viewHolder; /** @@ -48,21 +44,13 @@ public final class FolderBrowserAdapter extends ArrayAdapter * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public FolderBrowserAdapter(Context context, int resourceId, List objects) + public FolderBrowserAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public FolderBrowserItem getItem(int i) - { - return items.get(i); } @Override @@ -85,7 +73,7 @@ public final class FolderBrowserAdapter extends ArrayAdapter viewHolder = (ViewHolder) convertView.getTag(); } - final FolderBrowserItem item = items.get(position); + final FolderBrowserItem item = getItem(position); if (item != null) { if (viewHolder.title != null) From 11a156615f35ded70ad7c1736d3474f384c79527 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 05:30:58 -0500 Subject: [PATCH 66/81] [Android] Like the previous commit (but for the GameListFragment), don't constantly create a new adapter when filling the game list. --- .../dolphinemu/gamelist/GameListAdapter.java | 18 +++------------ .../dolphinemu/gamelist/GameListFragment.java | 22 +++++++++---------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java index ca30f4f284..d4dedd29aa 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java @@ -12,11 +12,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; -import java.util.List; - import org.dolphinemu.dolphinemu.R; /** @@ -28,28 +25,19 @@ public final class GameListAdapter extends ArrayAdapter { private final Context context; private final int id; - private final Listitems; /** * Constructor * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public GameListAdapter(Context context, int resourceId, List objects) + public GameListAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public GameListItem getItem(int i) - { - return items.get(i); } @Override @@ -61,7 +49,7 @@ public final class GameListAdapter extends ArrayAdapter convertView = vi.inflate(id, parent, false); } - final GameListItem item = items.get(position); + final GameListItem item = getItem(position); if (item != null) { TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 4224e16282..9dedf914dc 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -35,7 +35,6 @@ import org.dolphinemu.dolphinemu.emulation.EmulationActivity; public final class GameListFragment extends ListFragment { private GameListAdapter mGameAdapter; - private static GameListActivity mMe; private OnGameListZeroListener mCallback; /** @@ -84,7 +83,7 @@ public final class GameListFragment extends ListFragment if (!entry.isHidden() && !entry.isDirectory()) { if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.')))) - fls.add(new GameListItem(mMe, entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); + fls.add(new GameListItem(getActivity(), entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); } } } @@ -94,8 +93,9 @@ public final class GameListFragment extends ListFragment } Collections.sort(fls); - mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_folderbrowser_list_item, fls); - setListAdapter(mGameAdapter); + // Add all the items to the adapter + mGameAdapter.addAll(fls); + mGameAdapter.notifyDataSetChanged(); if (fls.isEmpty()) { @@ -106,12 +106,13 @@ public final class GameListFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + mGameAdapter = new GameListAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(mGameAdapter); Fill(); - return mMainList; + return rootView; } @Override @@ -120,12 +121,12 @@ public final class GameListFragment extends ListFragment GameListItem item = mGameAdapter.getItem(position); // Show a toast indicating which game was clicked. - Toast.makeText(mMe, String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); // Start the emulation activity and send the path of the clicked ROM to it. - Intent intent = new Intent(mMe, EmulationActivity.class); + Intent intent = new Intent(getActivity(), EmulationActivity.class); intent.putExtra("SelectedGame", item.getPath()); - mMe.startActivity(intent); + startActivity(intent); } @Override @@ -138,7 +139,6 @@ public final class GameListFragment extends ListFragment try { mCallback = (OnGameListZeroListener) activity; - mMe = (GameListActivity) activity; } catch (ClassCastException e) { From 2025f00f8836f529fecf6b6caded24c5db158357 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 16 Nov 2013 09:40:55 -0600 Subject: [PATCH 67/81] Woops, vim copy and paste issue with a double include. --- Source/Core/VideoBackends/Software/Src/SWRenderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index c2d9b626f7..fc26a93ad5 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -6,7 +6,6 @@ #include "../../OGL/Src/GLUtil.h" #include "ImageWrite.h" -#include "ImageWrite.h" #include "RasterFont.h" #include "SWRenderer.h" #include "SWStatistics.h" From ee32c8b4e9cc621a3cc9b4e8b897204322248f53 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 15:17:37 -0500 Subject: [PATCH 68/81] [Android] Remove accidental fragment tag in GameListActivity (it was useless, since it's an empty string) --- .../org/dolphinemu/dolphinemu/gamelist/GameListActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index bdf4f7c314..940632a8ea 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -158,7 +158,7 @@ public final class GameListActivity extends Activity mCurFragmentNum = 0; final GameListFragment gameList = new GameListFragment(); FragmentTransaction ft = getFragmentManager().beginTransaction(); - ft.replace(R.id.content_frame, gameList, ""); + ft.replace(R.id.content_frame, gameList); ft.commit(); invalidateOptionsMenu(); } From 71d70d896fd6012eea94042e962dad2009086038 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 10:34:34 +1300 Subject: [PATCH 69/81] Api was too confusing for people. --- Source/Core/VideoBackends/D3D/Src/Render.cpp | 1 + Source/Core/VideoBackends/D3D/Src/TextureCache.cpp | 1 + Source/Core/VideoBackends/OGL/Src/Render.cpp | 6 +++++- Source/Core/VideoBackends/OGL/Src/TextureCache.cpp | 5 +++-- Source/Core/VideoBackends/Software/Src/DebugUtil.cpp | 4 ++++ Source/Core/VideoBackends/Software/Src/SWRenderer.cpp | 2 ++ Source/Core/VideoCommon/Src/ImageWrite.cpp | 5 ----- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index ae6d21ef03..18eb1e26cc 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -701,6 +701,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle memcpy(data, map.pData, map.RowPitch * rc.GetHeight()); saved_png = TextureToPng(data, map.RowPitch, filename.c_str(), rc.GetWidth(), rc.GetHeight(), false); + delete[] data; } D3D::context->Unmap(s_screenshot_texture, 0); diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index faf83c23ca..cfc25bd38f 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -71,6 +71,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) memcpy(data, map.pData, map.RowPitch * desc.Height); saved_png = TextureToPng(data, map.RowPitch, filename, desc.Width, desc.Height); + delete[] data; } D3D::context->Unmap(pNewTexture, 0); } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 5a2e6dfe01..8f06c2547c 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1825,7 +1825,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // Turn image upside down FlipImageData(data, W, H, 4); - return TextureToPng(data, W*4, filename.c_str(), W, H, false); + bool success = TextureToPng(data, W*4, filename.c_str(), W, H, false); + delete[] data; + + return success; + } } diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp index 0c4fe8a187..6d69c62ec0 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp @@ -78,8 +78,9 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width delete[] data; return false; } - - return TextureToPng(data, width*4, filename, width, height, true); + bool success = TextureToPng(data, width * 4, filename, width, height, true); + delete[] data; + return success; #else return false; #endif diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 3f21e6a758..106b32647c 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -57,6 +57,7 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip) GetTextureRGBA(data, texmap, mip, width, height); (void)TextureToPng(data, width*4, filename, width, height, true); + delete[] data; } @@ -140,6 +141,7 @@ void DumpEfb(const char* filename) } (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } void DumpDepth(const char* filename) @@ -161,6 +163,7 @@ void DumpDepth(const char* filename) } (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name) @@ -241,6 +244,7 @@ void OnObjectEnd() (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename.c_str(), EFB_WIDTH, EFB_HEIGHT, true); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); + } } diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index fc26a93ad5..5db452dd94 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -145,6 +145,8 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height) u8 *data = new u8[width * 4 * height]; memcpy(data, texture, sizeof(u8) * 4 * width * height); TextureToPng(data, width*4, s_sScreenshotName.c_str(), width, height, false); + delete[] data; + // Reset settings s_sScreenshotName.clear(); s_bScreenshot = false; diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index 5bf3f28e45..974efe7474 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -24,8 +24,6 @@ TextureToPng Inputs: data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. -data is a newly allocated memory and must have delete[] run on it before returning. - row_stride: Determines the amount of bytes per row of pixels. */ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha) @@ -109,8 +107,5 @@ finalise: if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - // Our duty to delete the inputted data. - delete[] data; - return success; } From 4a9c8e6f55312127e49a4202b0a2c0438d1de00f Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 16 Nov 2013 15:37:40 -0600 Subject: [PATCH 70/81] Change software rasterizer screenshot code due to change in api just now. --- Source/Core/VideoBackends/Software/Src/SWRenderer.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index 5db452dd94..1f5430ae49 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -142,11 +142,7 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height) if (s_bScreenshot) { std::lock_guard lk(s_criticalScreenshot); - u8 *data = new u8[width * 4 * height]; - memcpy(data, texture, sizeof(u8) * 4 * width * height); - TextureToPng(data, width*4, s_sScreenshotName.c_str(), width, height, false); - delete[] data; - + TextureToPng(texture, width*4, s_sScreenshotName.c_str(), width, height, false); // Reset settings s_sScreenshotName.clear(); s_bScreenshot = false; From cce869ae0169970ef20663d04701c58527755ddf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 16 Nov 2013 17:05:51 -0500 Subject: [PATCH 71/81] [Core] Fix a mismatched dealloc in Render.cpp in the OGL backend. Should be delete[] --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 8f06c2547c..7d68bb4924 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1818,7 +1818,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // Show failure message if (GL_REPORT_ERROR() != GL_NO_ERROR) { - free(data); + delete[] data; OSD::AddMessage("Error capturing or saving screenshot.", 2000); return false; } From 33d8166620d308f5d7644e64ca92e588ff75fa44 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 11:12:07 +1300 Subject: [PATCH 72/81] Use IOFile for TextureToPng to support non-ascii Changed save texture/screenshot uses to std::string Removed unneeded new/delete calls when dealing with temp data. --- Source/Core/VideoBackends/D3D/Src/Render.cpp | 10 +--------- Source/Core/VideoBackends/D3D/Src/TextureCache.cpp | 11 ++--------- Source/Core/VideoBackends/D3D/Src/TextureCache.h | 2 +- Source/Core/VideoBackends/OGL/Src/Render.cpp | 2 +- Source/Core/VideoBackends/OGL/Src/TextureCache.cpp | 6 +++--- Source/Core/VideoBackends/OGL/Src/TextureCache.h | 4 ++-- .../Core/VideoBackends/Software/Src/DebugUtil.cpp | 8 ++++---- .../Core/VideoBackends/Software/Src/SWRenderer.cpp | 2 +- Source/Core/VideoCommon/Src/ImageWrite.cpp | 11 ++++------- Source/Core/VideoCommon/Src/ImageWrite.h | 2 +- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 14 +++++++------- Source/Core/VideoCommon/Src/TextureCacheBase.h | 2 +- 12 files changed, 28 insertions(+), 46 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 18eb1e26cc..d2938e6600 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -694,15 +694,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - bool saved_png = false; - if (map.pData) - { - u8* data = new u8[map.RowPitch * rc.GetHeight()]; - memcpy(data, map.pData, map.RowPitch * rc.GetHeight()); - - saved_png = TextureToPng(data, map.RowPitch, filename.c_str(), rc.GetWidth(), rc.GetHeight(), false); - delete[] data; - } + bool saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, rc.GetWidth(), rc.GetHeight(), false); D3D::context->Unmap(s_screenshot_texture, 0); diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index cfc25bd38f..22e644b2d8 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -33,7 +33,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { // TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs) static bool warn_once = true; @@ -65,14 +65,7 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); if (SUCCEEDED(hr)) { - if (map.pData) - { - u8* data = new u8[map.RowPitch * desc.Height]; - memcpy(data, map.pData, map.RowPitch * desc.Height); - - saved_png = TextureToPng(data, map.RowPitch, filename, desc.Width, desc.Height); - delete[] data; - } + saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, desc.Width, desc.Height); D3D::context->Unmap(pNewTexture, 0); } SAFE_RELEASE(pNewTexture); diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.h b/Source/Core/VideoBackends/D3D/Src/TextureCache.h index 94adfe8cce..91603bc56d 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.h @@ -36,7 +36,7 @@ private: const float *colmat); void Bind(unsigned int stage); - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 7d68bb4924..b9a3fa4fce 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1825,7 +1825,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // Turn image upside down FlipImageData(data, W, H, 4); - bool success = TextureToPng(data, W*4, filename.c_str(), W, H, false); + bool success = TextureToPng(data, W*4, filename, W, H, false); delete[] data; return success; diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp index 6d69c62ec0..eb2198ee7f 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.cpp @@ -59,7 +59,7 @@ struct VBOCache { }; static std::map s_VBO; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) { #ifndef USE_GLES3 int width = std::max(virtual_width >> level, 1); @@ -127,7 +127,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) } } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { return SaveTexture(filename, GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); } @@ -394,7 +394,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo { static int count = 0; SaveTexture(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); + count++), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); } g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.h b/Source/Core/VideoBackends/OGL/Src/TextureCache.h index 1c95d35f98..af1b60bc06 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.h @@ -53,7 +53,7 @@ private: const float *colmat) override; void Bind(unsigned int stage) override; - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; ~TextureCache(); @@ -64,7 +64,7 @@ private: TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) override; }; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); } diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 106b32647c..bac6ef6152 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -42,7 +42,7 @@ void Init() } } -void SaveTexture(const char* filename, u32 texmap, s32 mip) +void SaveTexture(const std::string filename, u32 texmap, s32 mip) { FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1]; u8 subTexmap = texmap & 3; @@ -98,7 +98,7 @@ void DumpActiveTextures() for (s32 mip = 0; mip <= maxLod; ++mip) { SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", - File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + File::GetUserPath(D_DUMPTEXTURES_IDX), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); } } @@ -115,7 +115,7 @@ void DumpActiveTextures() for (s32 mip = 0; mip <= maxLod; ++mip) { SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", - File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + File::GetUserPath(D_DUMPTEXTURES_IDX), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); } } @@ -242,7 +242,7 @@ void OnObjectEnd() File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]); - (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename.c_str(), EFB_WIDTH, EFB_HEIGHT, true); + (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); } diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index 1f5430ae49..069ca5eebc 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -142,7 +142,7 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height) if (s_bScreenshot) { std::lock_guard lk(s_criticalScreenshot); - TextureToPng(texture, width*4, s_sScreenshotName.c_str(), width, height, false); + TextureToPng(texture, width*4, s_sScreenshotName, width, height, false); // Reset settings s_sScreenshotName.clear(); s_bScreenshot = false; diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index 974efe7474..b44bb3e903 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -26,7 +26,7 @@ Inputs: data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. row_stride: Determines the amount of bytes per row of pixels. */ -bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha) +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha) { bool success = false; @@ -35,13 +35,12 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int char title[] = "Dolphin Screenshot"; char title_key[] = "Title"; - FILE *fp = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; // Open file for writing (binary mode) - fp = fopen(filename, "wb"); - if (fp == NULL) { + File::IOFile fp(filename, "wb"); + if (!fp.IsOpen()) { PanicAlert("Screenshot failed: Could not open file %s %d\n", filename, errno); goto finalise; } @@ -67,7 +66,7 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int goto finalise; } - png_init_io(png_ptr, fp); + png_init_io(png_ptr, fp.GetHandle()); // Write header (8 bit colour depth) png_set_IHDR(png_ptr, info_ptr, width, height, @@ -102,8 +101,6 @@ bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int success = true; finalise: - - if (fp != NULL) fclose(fp); if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index 82a942c767..04de765d32 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -8,7 +8,7 @@ #include "Common.h" bool SaveData(const char* filename, const char* pdata); -bool TextureToPng(u8* data, int row_stride, const char* filename, int width, int height, bool saveAlpha = true); +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha = true); #endif // _IMAGEWRITE_H diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 05c2e88aae..31ba3d5e61 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -283,7 +283,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) { - char szTemp[MAX_PATH]; + std::string filename; std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; @@ -295,19 +295,19 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) // TODO: TLUT format should actually be stored in filename? :/ if (level == 0) { - sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); + filename = StringFromFormat("%s/%s_%08x_%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32)(entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); } else { - sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(), + filename = StringFromFormat("%s/%s_%08x_%i_mip%i.png", szDir.c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); } - if (false == File::Exists(szTemp)) - entry->Save(szTemp, level); + if (!File::Exists(filename)) + entry->Save(filename, level); } static u32 CalculateLevelSize(u32 level_0_size, u32 level) diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 1afcb8cd2d..4db768f5e4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -73,7 +73,7 @@ public: virtual ~TCacheEntryBase(); virtual void Bind(unsigned int stage) = 0; - virtual bool Save(const char filename[], unsigned int level) = 0; + virtual bool Save(const std::string filename, unsigned int level) = 0; virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) = 0; From ea3990a41b3ea1a5d2b483ef79029972d7d03b65 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 11:25:12 +1300 Subject: [PATCH 73/81] Don't pass char* to std::string. Windows was fine with this :( --- .../Core/VideoBackends/Software/Src/DebugUtil.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index bac6ef6152..8e93624b6c 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -99,7 +99,7 @@ void DumpActiveTextures() { SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } @@ -116,12 +116,12 @@ void DumpActiveTextures() { SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } } -void DumpEfb(const char* filename) +void DumpEfb(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -144,7 +144,7 @@ void DumpEfb(const char* filename) delete[] data; } -void DumpDepth(const char* filename) +void DumpDepth(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -225,7 +225,7 @@ void OnObjectEnd() if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) DumpEfb(StringFromFormat("%sobject%i.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects).c_str()); + swstats.thisFrame.numDrawnObjects)); if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles) { @@ -259,9 +259,9 @@ void OnFrameEnd() if (g_SWVideoConfig.bDumpFrames) { DumpEfb(StringFromFormat("%sframe%i_color.png", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); DumpDepth(StringFromFormat("%sframe%i_depth.png", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); } } } From f4a1f183b9a34c9962dadfd3a6ac2bb9b7f92c28 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 11:28:11 +1300 Subject: [PATCH 74/81] std::string can't be passed to ... format. --- Source/Core/VideoBackends/Software/Src/DebugUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 8e93624b6c..75c6c08ada 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -98,7 +98,7 @@ void DumpActiveTextures() for (s32 mip = 0; mip <= maxLod; ++mip) { SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", - File::GetUserPath(D_DUMPTEXTURES_IDX), + File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } @@ -115,7 +115,7 @@ void DumpActiveTextures() for (s32 mip = 0; mip <= maxLod; ++mip) { SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", - File::GetUserPath(D_DUMPTEXTURES_IDX), + File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } From b372f97675687a7cfcf66c5b7670d53a0ab48ea5 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 11:30:05 +1300 Subject: [PATCH 75/81] Imagewrite.cpp had same problem. I hate windows :( --- Source/Core/VideoCommon/Src/ImageWrite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index b44bb3e903..193f058541 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -41,7 +41,7 @@ bool TextureToPng(u8* data, int row_stride, const std::string filename, int widt // Open file for writing (binary mode) File::IOFile fp(filename, "wb"); if (!fp.IsOpen()) { - PanicAlert("Screenshot failed: Could not open file %s %d\n", filename, errno); + PanicAlert("Screenshot failed: Could not open file %s %d\n", filename.c_str(), errno); goto finalise; } From e805bf60685bb5f4bd5ac1bf0a290519a678e5b4 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 17 Nov 2013 21:14:22 +1300 Subject: [PATCH 76/81] Only add real HID devices to HID list. --- .../Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index 00415a526f..c1b82e4d55 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -385,12 +385,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4)); OffsetBuffer += Align(wii_device.bLength, 4); bool deviceValid = true; + bool isHID = false; for (c = 0; deviceValid && c < desc.bNumConfigurations; c++) { struct libusb_config_descriptor *config = NULL; int cRet = libusb_get_config_descriptor(device, c, &config); - // do not try to use usb devices with more than one interface, games can crash if(cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES) { @@ -402,10 +402,14 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) for (ic = 0; ic < config->bNumInterfaces; ic++) { const struct libusb_interface *interfaceContainer = &config->interface[ic]; + for (i = 0; i < interfaceContainer->num_altsetting; i++) { const struct libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i]; + if (interface->bInterfaceClass == LIBUSB_CLASS_HID) + isHID = true; + WiiHIDInterfaceDescriptor wii_interface; ConvertInterfaceToWii(&wii_interface, interface); Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(wii_interface.bLength, 4)); @@ -435,6 +439,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) } } // configs + if (!isHID) + { + deviceValid = false; + OffsetBuffer = OffsetStart; + } + if (deviceValid) { Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length From 4f13f6ecaaace721f826a158fdd9d67465b38e02 Mon Sep 17 00:00:00 2001 From: comex Date: Mon, 18 Nov 2013 14:34:21 -0500 Subject: [PATCH 77/81] "warning fixes" commit introduced warnings; fix them. (And I refuse to use PRI macros.) --- Source/Core/Core/Src/HW/GCMemcard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index 2421e572ae..d320f0177a 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -43,12 +43,12 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) auto size = mcdFile.GetSize(); if (size < MC_FST_BLOCKS*BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, (unsigned) size); return; } if (size % BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, (unsigned) size); return; } @@ -63,7 +63,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) case MemCard2043Mb: break; default: - PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, (unsigned) size); return; } } From bcefa880e4d062121df9ab8b831170ec3a689a50 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Wed, 20 Nov 2013 21:30:49 +0100 Subject: [PATCH 78/81] Jit64: fix fmrx regression Revision ddaf29e039d1736be1ca48c1c0b6af1c8d4ec47d introduced a register corruption bug (#6825). Since fmrx/MOVSD only modifies ps0 but we save both ps0 and ps1 in one xmm register, not loading the previous value when binding to a x64 register trashed ps1. But hey, a good opportunity to shave off one more instruction ;) --- .../Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index b0d0ab4853..65f186e802 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -229,11 +229,12 @@ void Jit64::fmrx(UGeckoInstruction inst) } int d = inst.FD; int b = inst.FB; - fpr.Lock(b, d); - fpr.BindToRegister(d, d == b, true); - MOVSD(XMM0, fpr.R(b)); - MOVSD(fpr.R(d), XMM0); - fpr.UnlockAll(); + if (d != b) { + fpr.Lock(b, d); + fpr.BindToRegister(d); + MOVSD(fpr.RX(d), fpr.R(b)); + fpr.UnlockAll(); + } } void Jit64::fcmpx(UGeckoInstruction inst) From 286b6110f1c358ec76205dc931e7c7dd2669ebc4 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 20 Nov 2013 22:53:10 +0100 Subject: [PATCH 79/81] Revert "Handle BP mask register better to avoid useless BP writes (causing flushes)" This reverts commit 954be9e2d9bfca8b33ac1cb36d3226bf2555f2c1. Fixes issue 6826. --- Source/Core/VideoCommon/Src/BPMemory.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp index 7bc976a943..7272ed0993 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.cpp +++ b/Source/Core/VideoCommon/Src/BPMemory.cpp @@ -19,18 +19,15 @@ void LoadBPReg(u32 value0) int opcode = value0 >> 24; int oldval = ((u32*)&bpmem)[opcode]; int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + BPCmd bp = {opcode, changes, newval}; + + //reset the mask register if (opcode != 0xFE) - { - //reset the mask register bpmem.bpMask = 0xFFFFFF; - int changes = (oldval ^ newval) & 0xFFFFFF; - BPCmd bp = {opcode, changes, newval}; - BPWritten(bp); - } - else - bpmem.bpMask = newval; + BPWritten(bp); } void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size) From 011fe86d01ebec800ed1018e99a364a620d051bd Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 21 Nov 2013 05:16:58 +0100 Subject: [PATCH 80/81] jit64: add regcache option IsBound Lots of x86 instructions are different on memory vs registers. So to generate code, we often have to check if a ppc register is already bound to a x86 register. --- Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp | 2 +- Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp index b2317c9394..1be04a0d5d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp @@ -166,7 +166,7 @@ int RegCache::SanityCheck() const void RegCache::DiscardRegContentsIfCached(int preg) { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) { X64Reg xr = regs[preg].location.GetSimpleReg(); xregs[xr].free = true; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h index cacd1e0e4e..f27dcae91c 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h @@ -93,7 +93,7 @@ public: const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) return regs[preg].location.GetSimpleReg(); PanicAlert("Not so simple - %i", preg); return (X64Reg)-1; @@ -111,6 +111,11 @@ public: return xregs[xreg].free && !xlocks[xreg]; } + bool IsBound(int preg) const + { + return regs[preg].away && regs[preg].location.IsSimpleReg(); + } + X64Reg GetFreeXReg(); From ff917897731d400a8e71c1480425733e651126ee Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Thu, 21 Nov 2013 05:31:55 +0100 Subject: [PATCH 81/81] Jit64: really fix fmrx regression This is more tricky than I thought! --- .../Src/PowerPC/Jit64/Jit_FloatingPoint.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index 65f186e802..7f77112ae9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -224,15 +224,26 @@ void Jit64::fmrx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) - if (inst.Rc) { + if (inst.Rc) + { Default(inst); return; } int d = inst.FD; int b = inst.FB; - if (d != b) { + if (d != b) + { fpr.Lock(b, d); - fpr.BindToRegister(d); - MOVSD(fpr.RX(d), fpr.R(b)); + + // we don't need to load d, but if it already is, it must be marked as dirty + if (fpr.IsBound(d)) + { + fpr.BindToRegister(d); + } + fpr.BindToRegister(b, true, false); + + // caveat: the order of ModRM:r/m, ModRM:reg is deliberate! + // "MOVSD reg, mem" zeros out the upper half of the destination register + MOVSD(fpr.R(d), fpr.RX(b)); fpr.UnlockAll(); } }